summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTar Committer <tar@ocjtech.us>2000-02-03 17:55:28 +0000
committerTar Committer <tar@ocjtech.us>2000-02-03 17:55:28 +0000
commitb24aa5051db5d4bf9757efe7df06cb1892898382 (patch)
tree9cdcee7bb6f7780d08f94997af4f8232b5bd0417
parent42de2e53682c49b050f19fdbaaf68451ba487303 (diff)
downloadrancid-b24aa5051db5d4bf9757efe7df06cb1892898382.tar.gz
rancid-b24aa5051db5d4bf9757efe7df06cb1892898382.tar.xz
rancid-b24aa5051db5d4bf9757efe7df06cb1892898382.zip
Imported from rancid-1.4.tar.gz.rancid-1.4
-rw-r--r--CHANGES25
-rw-r--r--README62
-rw-r--r--Todo7
-rwxr-xr-xbin/clogin181
-rwxr-xr-xbin/control_rancid107
-rwxr-xr-xbin/create_cvs32
-rw-r--r--bin/cvs_helper28
-rwxr-xr-xbin/do-diffs4
-rw-r--r--bin/env14
-rwxr-xr-xbin/flogin530
-rwxr-xr-xbin/francid383
-rwxr-xr-xbin/jrancid242
-rwxr-xr-xbin/rancid1172
-rwxr-xr-xbin/rancid-fe6
-rwxr-xr-xbin/rrancid347
-rwxr-xr-xbin/run-me35
-rw-r--r--cloginrc.sample37
17 files changed, 2398 insertions, 814 deletions
diff --git a/CHANGES b/CHANGES
index 1a091c0..abe3961 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,28 @@
+1.4
+ sort cisco route-maps
+
+ added (crude) foundry switch bits
+
+ reworked code to reduce jumps. improvement in speed/cpu util.
+
+ add bits to cvs delete configs which have been removed from
+ a group's router.db.
+
+ add support for redback. modified from contrib by scao@verio.net.
+
+ add support for ssh in clogin
+
+ modify format of the admin up/down/delete'd msgs.
+
+ add NOPIPE bin/env var
+
+ order ARP lists in cisco configs
+
+1.3
+ update comments re: mail aliases in bin/env
+
+ add more info/clarification to README for install.
+
1.2
add more info/clarification to README for install.
diff --git a/README b/README
index efaeefd..e595c2c 100644
--- a/README
+++ b/README
@@ -5,14 +5,18 @@ The following is the packing list for Rancid:
README - This file.
env - Enviromental settings needed.
-run-me - Script designed to be run from cron calling control_rancid.
+do-diffs - Script designed to be run from cron calling control_rancid.
control_rancid - Builds router list, calls rancid on each router and
handles cvs routines.
-rancid-fe - chooses between rancid an jrancid
-rancid - Runs commands on router and processes the output - the meat.
-jrancid - Runs commands on juniper routers and processes the output
+rancid-fe - chooses between rancid/francid/jrancid/rrancid.
+rancid - Runs commands on cisco routers and processes the output - the meat.
+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.
clogin - Expect script that logs into routers 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
clogin. it is not terribly robust, but mainly used for it's
-c and -s options.
@@ -22,14 +26,12 @@ par - Parallel processing of commands - any commands.
rancid will also need to have the following packages:
cvs - code revision system available from prep.ai.mit.edu:/pub/gnu
-rcs - code revision system which cvs built on top of. available from
- prep.ai.mit.edu:/pub/gnu
-gnudiff - gnudiff provides the -u option. if you do not have gnu's diff,
+gnudiff - gnudiff provides the -u option. if you do not have gnudiff,
you will have to modify control_rancid to use 'diff -c' or some
such. see examples.
perl5 - perl version 5 or greater available from www.cpan.org
-expect -
-tcl - required by expect
+expect - http://expect.nist.gov/
+tcl - required by expect.
Quick Installation Guide (an example):
@@ -40,7 +42,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 clogin, par, rancid, rancid-fe, jlogin,
- jrancid and rename if necessary.
+ jrancid, and rename if necessary. Make sure that you are using perl
+ version 5 and not perl version 4. There are also 3 calls to perl in
+ control_rancid.
4) Modify <basedir>/bin/env.
@@ -48,13 +52,18 @@ Quick Installation Guide (an example):
6) Modify .cloginrc.
+ Test to make sure that you can log into every router.
+
+ Note: the juniper user you use *must* log into a cli shell (which
+ is the default on a juniper).
+
7) Modify /etc/aliases
Rancid sends the diffs and other controlling emails to rancid-<GROUP>
and problems to rancid-admin-<GROUP>, where <GROUP> is the "GROUP" of
routers. This way you can seperate your backbone routers from your
access routers or seperate based upon network etc... Different router
uses forced different people being interested in router "groups" -
- thus is setup. Make sure email to rancid-<GROUP> works. /etc/aliases
+ thus this setup. Make sure email to rancid-<GROUP> works. /etc/aliases
can be maintainable by Majordomo stuff.
- OR -
Modify your home directory's .mailrc. Control_rancid uses sendmail
@@ -62,33 +71,28 @@ Quick Installation Guide (an example):
be modified to use ucbmail or, better yet, something else which allow
the Precedence header to be set. Pick your poison.
- The Precedence header set to bulk or junk *hopefully* avoids
+ The Precedence header set to bulk or junk *hopefully* avoids replies from
auto-responders and vacation type mail filters.
-8) Modify run-me &/ do-diffs.
- Set path to env.
-
-9) Modify create_cvs.
- Set path to env.
-
-10) Run create_cvs.
- This creates all of the CVS necessary directories and all of the
- config directories.
+8) Run create_cvs.
+ This creates all of the CVS necessary directories and all of the
+ config directories.
-11) For each "group", create the router.db file in the group directory.
- The file is of the form "router:mfg:state" where "router" is the name
- of the router, mfg is the manufacturer (cisco|juniper), and "state"
- is either up or down. Each router listed as "up" will have the
- configuration grabbed.
+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), and "state" is either up or
+ down. Each router listed as "up" will have the configuration
+ grabbed.
-12) Put run-me/do-diffs in cron to be called however often you want it to run
- for each group (run-me <GROUP>). eg:
+10) Put do-diffs in cron to be called however often you want it to run
+ for each group (do-diffs [<GROUP>]). eg:
# run config differ hourly
1 * * * * <BASEDIR>/bin/do-diffs
# clean out hourly differ logs
50 23 * * * /usr/bin/find <BASEDIR>/logs -mtime +2 -exec rm {} \;
-13) Send me any bugs, suggestions or updates (rancid@shrubbery.net).
+11) Send any bugs, suggestions or updates to rancid@shrubbery.net.
-Hank
diff --git a/Todo b/Todo
index b13b717..72d8547 100644
--- a/Todo
+++ b/Todo
@@ -1,3 +1,8 @@
- detect 'same' vty configs
- ignoring length/width/passwd is a start, but need more
-- sort route-maps into alpha order
+- add .cloginrc var to say to use ssh or telnet
+- rancid needs to treat the 3600s like the 7Ks and 12Ks...
+- Also, need to allow 12012s, and force 700s to not be treated like 7Ks.
+- change rancid to work on a file
+- flogin (for foundry) needs more testing and should be integrated with
+ clogin when foundry fixes their UI.
diff --git a/bin/clogin b/bin/clogin
index b8b693e..cad94cd 100755
--- a/bin/clogin
+++ b/bin/clogin
@@ -7,7 +7,7 @@
## 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
@@ -29,8 +29,8 @@
# Usage line
set usage "Usage: $argv0 \[-u user\] \[-p user-password\] \[-v vty-password\] \
\[-w enable-username\] \[-e enable-password\] \[-noenable\] \
-\[-f cloginrc-file\] \[-c command\] \[-s script-file\] \[-autoenable\] \
-\[-t timeout\] router \[router...\]\n"
+\[-f cloginrc-file\] \[-y ssh_cypher_type\] \[-c command\] \[-s script-file\] \
+\[-x command-file\] \[-autoenable\] \[-t timeout\] router \[router...\]\n"
# env(CLOGIN) may contain:
# x == do not set xterm banner or name
@@ -53,8 +53,8 @@ set do_enapasswd 1
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 -
+ # 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
}
@@ -125,6 +125,13 @@ for {set i 0} {$i < $argc} {incr i} {
exit 1
}
set do_script 1
+ # cypher type
+ } -y* -
+ -Y* {
+ if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ incr i
+ set cypher [ lindex $argv $i ]
+ }
# alternate cloginrc file
} -f* -
-F* {
@@ -136,17 +143,17 @@ for {set i 0} {$i < $argc} {incr i} {
-T* {
incr i
set timeout [ lindex $argv $i ]
- } -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
+ } -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 {
set enable 0
@@ -192,20 +199,20 @@ proc label { host } {
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 sl* pete cow
+# add password at* steve
# add password * hanky-pie
-proc add {var args} { global $var ;lappend $var $args}
+proc add {var args} { global $var ;lappend $var $args}
proc find {var router} {
- source_password_file
- upvar $var list
- if { [info exists list] } {
+ 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]
@@ -219,11 +226,11 @@ proc find {var router} {
# 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
+# 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 } {
+ if { [info exists password_file] == 0 } {
set password_file $env(HOME)/.cloginrc
}
set read_password_file 1
@@ -236,9 +243,10 @@ proc source_password_file { } {
}
# Log into the router.
-proc login { router user userpswd passwd enapasswd prompt } {
+proc login { router user userpswd passwd enapasswd prompt cyphertype } {
global spawn_id in_proc do_command do_script
set in_proc 1
+ set tryssh 1
# Telnet to the router & try to login.
if [ catch {spawn telnet $router} reason ] {
@@ -253,19 +261,19 @@ proc login { router user userpswd passwd enapasswd prompt } {
send_user "\nError: TIMEOUT reached\n"
close; wait
if { $in_proc} {
- return 1
+ return 1
} else {
- continue
+ continue
}
- } eof {
+ } eof {
send_user "\nError: EOF received\n"
close; wait
if { $in_proc} {
- return 1
+ return 1
} else {
- continue
+ continue
}
- }
+ }
}
# Here we get a little tricky. There are several possibilities:
@@ -274,12 +282,24 @@ proc login { router user userpswd passwd enapasswd prompt } {
# TACACS server is not working, then it will use the enable
# passwd. Or, the router might not have TACACS turned on,
# then it will just send the passwd.
+ # if telnet fails with connection refused, try ssh
expect {
- eof { send_user "Error: Couldn't login\n"; wait; return 1 }
- "Connection refused" {
- expect eof
- send_user "Error: Connection Refused\n"; wait; return 1
- } "Unknown host\r\n" {
+ "Connection refused" {
+ close; wait
+ if { $tryssh } {
+ if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
+ send_user "Error: failed to ssh: $reason\n"
+ exit 1
+ }
+ set tryssh 0
+ sleep 0.3
+ exp_continue
+ } else {
+ 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" {
@@ -289,32 +309,40 @@ proc login { router user userpswd passwd enapasswd prompt } {
expect eof
send_user "Error: Unknown host\n"; wait; return 1
}
+ -re "Host key not found .* \(yes\/no\)\?" {
+ send "yes\r"
+ send_user "Host $router added to the list of known hosts.\n"
+ exp_continue }
+ -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n"
+ return 1 }
-re "(Username|login):" { send "$user\r"
- expect {
- eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ expect {
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
-re "\[Pp]assword:" { send "$userpswd\r" }
"$prompt" { set in_proc 0; return 0 }
}
exp_continue
}
- "Password:" { send "$passwd\r"
- expect {
- eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ "\[Pp]assword:" { send "$passwd\r"
+ expect {
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
"Password:" { send "$enapasswd\r" }
- "$prompt" { set in_proc 0; return 0 }
+ "$prompt" { set in_proc 0; return 0 }
}
exp_continue
}
- "$prompt" { }
- denied { send_user "Error: Check your passwd for $router\n"
- if { $do_command || $do_script } {
+ "$prompt" { }
+ denied { send_user "Error: Check your passwd for $router\n"
+ if { $do_command || $do_script } {
send "quit"
wait
return 1
} else {
return 1
}
- }
+ }
"% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 }
}
set in_proc 0
@@ -358,17 +386,17 @@ proc run_commands { prompt command } {
for {set i 0} {$i < $num_commands} { incr i} {
send "[subst [lindex $commands $i]]\r"
expect {
- -re "^\[^\n\r]*$prompt." { exp_continue }
+ -re "^\[^\n\r]*$prompt." { exp_continue }
-re "^\[^\n\r *]*$prompt" {}
- "\n" { exp_continue }
- }
+ -re "\[\n\r]" { exp_continue }
+ }
}
} else {
send "[subst $command]\r"
expect {
-re "^\[^\n\r]*$prompt." { exp_continue }
-re "^\[^\n\r *]*$prompt" {}
- "\n" { exp_continue }
+ -re "\[\n\r]" { exp_continue }
}
}
send "exit\r"
@@ -410,49 +438,58 @@ foreach router [lrange $argv $i end] {
if { $do_passwd || $do_enapasswd } {
set pswd [find password $router]
if { [llength $pswd] == 0 } {
- send_user "Error - no password for $router in $password_file.\n"
- continue
- }
- if { $do_enapasswd && !$autoenable && [llength $pswd] < 2 } {
+ send_user "Error - no password for $router in $password_file.\n"
+ continue
+ }
+ if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
send_user "Error - no enable password for $router in $password_file.\n"
- continue
+ continue
}
- set passwd [lindex $pswd 0]
- set enapasswd [lindex $pswd 1]
+ set passwd [lindex $pswd 0]
+ set enapasswd [lindex $pswd 1]
}
# Figure out username
- if {[info exists username]} {
+ if {[info exists username]} {
# command line username
set ruser $username
} else {
- set ruser [find user $router]
+ 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 }
- }
-
+ set userpswd [find userpassword $router]
+ if { "$userpswd" == "" } { set userpswd $passwd }
+ }
+
# Figure out enable username
- if {[info exists enausername]} {
+ if {[info exists enausername]} {
# command line enausername
set enauser $enausername
} else {
- set enauser [find enauser $router]
- if { "$enauser" == "" } { set enauser $ruser }
- }
+ set enauser [find enauser $router]
+ if { "$enauser" == "" } { set enauser $ruser }
+ }
+
+ # Figure out cypher tpye
+ 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 $enapasswd $prompt]} {
+ if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cyphertype]} {
continue
}
- if { $enable } {
+ if { $enable } {
if {[do_enable $enauser $enapasswd]} {
if { $do_command || $do_script } {
close; wait
@@ -471,7 +508,7 @@ foreach router [lrange $argv $i end] {
source $sfile
close
} else {
- label $router
+ label $router
log_user 1
interact
}
diff --git a/bin/control_rancid b/bin/control_rancid
index 89ec0df..0728e7e 100755
--- a/bin/control_rancid
+++ b/bin/control_rancid
@@ -52,26 +52,58 @@ fi
# generate the list of routers we should try to fetch
cd $DIR
-rm -f $DIR/allrouters.new
+grep -v '^#' router.db > routers.db
+cut -d: -f1,2 routers.db | sort -u > routers.all.new
+diff routers.all routers.all.new > /dev/null 2>&1; RALL=$?
perl -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n")
- if ($F[2] =~ /^up$/i);}' $DIR/router.db | sort -u > $DIR/allrouters.new
+ if ($F[2] =~ /^down$/i);}' routers.db | sort -u > routers.down.new
+diff routers.down routers.down.new > /dev/null 2>&1; RDOWN=$?
+perl -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n")
+ if ($F[2] =~ /^up$/i);}' routers.db | sort -u > routers.up.new
+diff routers.up routers.up.new > /dev/null 2>&1; RUP=$?
-if diff $DIR/allrouters $DIR/allrouters.new > $DIR/allrouters.diffs
+if [ $RALL -ne 0 -o $RDOWN -ne 0 -o $RUP -ne 0 ]
then
- rm -f $DIR/allrouters.new
-else
(
- echo New routers:
- comm -13 $DIR/allrouters $DIR/allrouters.new | sed -e 's/^/ /' -e 's/:.*$//'
- echo
- echo Deleted routers:
- comm -23 $DIR/allrouters $DIR/allrouters.new | sed -e 's/^/ /' -e 's/:.*$//'
- ) | Mail -s "changes in $GROUP routers" rancid-admin-$GROUP
+ if [ $RUP -ne 0 ] ; then
+ if [ $RUP -eq 1 ] ; then
+ echo Routers changed to up:
+ comm -13 routers.up routers.up.new | sed -e 's/^/ /' -e 's/:.*$//'
+ echo
+ elif [ -s routers.up.new ] ; then
+ echo Routers changed to up:
+ sed -e 's/^/ /' -e 's/:.*$//' routers.up.new
+ echo
+ fi
+ fi
+ if [ $RDOWN -ne 0 ] ; then
+ if [ $RDOWN -eq 1 ] ; then
+ echo Routers changed to down:
+ comm -13 routers.down routers.down.new | sed -e 's/^/ /' -e 's/:.*$//'
+ echo
+ elif [ -s routers.down.new ] ; then
+ echo Routers changed to down:
+ sed -e 's/^/ /' -e 's/:.*$//' routers.down.new
+ echo
+ fi
+ fi
+ WC=`wc -l routers.all | sed -e 's/^ *\([^ ]*\) .*$/\1/'`
+ WCNEW=`wc -l routers.all.new | sed -e 's/^ *\([^ ]*\) .*$/\1/'`
+ if [ $RALL -eq 1 -a $WC -gt $WCNEW ] ; then
+ echo Deleted routers:
+ comm -23 routers.all routers.all.new | sed -e 's/^/ /' -e 's/:.*$//'
+ fi
+ ) > routers.mail
+
+ if [ -s routers.mail ] ; then
+ Mail -s "changes in $GROUP routers" rancid-admin-$GROUP < routers.mail
+ fi
+ rm -f routers.mail
cd $DIR/configs
# Add new routers to the CVS structure.
- for router in `comm -13 $DIR/allrouters $DIR/allrouters.new`
+ for router in `comm -13 $DIR/routers.up $DIR/routers.up.new`
do
OFS=$IFS
IFS=:
@@ -87,14 +119,31 @@ else
echo
cd $DIR
- mv $DIR/allrouters.new $DIR/allrouters
fi
-rm -f $DIR/allrouters.diffs $DIR/allrouters.new
+mv routers.all.new routers.all
+mv routers.down.new routers.down
+mv routers.up.new routers.up
+rm -f routers.db
+
+# cvs delete configs for routers not listed in routers.up.
+cd $DIR/configs
+for router in `find . \( -name \*.new -prune -o -name CVS -prune \) -o -type f -print | sed -e 's/^.\///'` ; do
+ grep "^$router:" ../router.db > /dev/null 2>&1
+ if [ $? -eq 1 ]; then
+ rm -f $router
+ cvs delete $router
+ cvs commit -m 'deleted router' $router
+ echo "Deleted $router"
+ fi
+done
+cd $DIR
# no routers, empty list or all 'down'
-if [ ! -s $DIR/allrouters ]
+if [ ! -s routers.up ]
then
- exit;
+ # commit router.db
+ cvs commit -m updates router.db > /dev/null
+ exit;
fi
# Now we can actually try to get the configs
@@ -103,22 +152,19 @@ cd $DIR/configs
# The number of processes running at any given time can be
# tailored to the specific installation.
echo "Trying to get all of the configs."
-par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/allrouters
+par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up
# This section will generate a list of missed routers
# and try to grab them again. It will run through
# $pass times.
pass=4
round=1
-if [ -f $DIR/allrouters.missed ]; then
- rm -f $DIR/allrouters.missed
+if [ -f $DIR/routers.up.missed ]; then
+ rm -f $DIR/routers.up.missed
fi
while [ $round -le $pass ]
do
- echo "====================================="
- echo "Getting missed routers: round $round."
-
- for router in `cat $DIR/allrouters`
+ for router in `cat $DIR/routers.up`
do
OFS=$IFS
IFS=':'
@@ -126,15 +172,17 @@ do
IFS=$OFS
router=$1; mfg=$2
- if [ ! -f $DIR/configs/$router.new ]
+ if [ ! -f $router.new ]
then
- echo "$router:$mfg" >> $DIR/allrouters.missed
+ echo "$router:$mfg" >> $DIR/routers.up.missed
fi
done
- if [ -f $DIR/allrouters.missed ]; then
- par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/allrouters.missed
- rm -f $DIR/allrouters.missed
+ if [ -f $DIR/routers.up.missed ]; then
+ echo "====================================="
+ echo "Getting missed routers: round $round."
+ par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up.missed
+ rm -f $DIR/routers.up.missed
round=`expr $round + 1`
else
echo "All routers sucessfully completed."
@@ -152,6 +200,7 @@ rename 's/.new$//' *.new
cd $DIR
#cvs diff -c3 >$TMP.diff
#cvs diff -C 3 >$TMP.diff
+# Change the output of a unified diff to make it a bit more readable.
cat > $TMP.sedf << EOF
/^RCS file: /d
#/^retrieving revision /d
@@ -180,7 +229,7 @@ fi
cd $DIR/configs
rm -f $DIR/routers.failed
perl -F: -ane '{$t = (stat($F[0]))[9]; print `ls -ld $F[0]`
- if (time() - $t >= 86400);}' $DIR/allrouters | sort -u > $DIR/routers.failed
+ if (time() - $t >= 86400);}' $DIR/routers.up | sort -u > $DIR/routers.failed
if [ -s $DIR/routers.failed ]
then
(
diff --git a/bin/create_cvs b/bin/create_cvs
index 675cda8..df7e56e 100755
--- a/bin/create_cvs
+++ b/bin/create_cvs
@@ -26,14 +26,21 @@ ENVFILE="`dirname $0`/env"
. $ENVFILE
+# Base dir
+if [ ! -d $BASEDIR ]; then
+ mkdir -p $BASEDIR
+fi
+
+cd $BASEDIR
+
# Top level CVS stuff
if [ ! -d $CVSROOT ]; then
cvs init
fi
# Log dir
-if [ ! -d $BASEDIR/logs ]; then
- mkdir $BASEDIR/logs
+if [ ! -d logs ]; then
+ mkdir logs
fi
# Which groups to do
@@ -57,25 +64,26 @@ do
cd $BASEDIR
cvs co $GROUP
fi
- if [ -d $DIR -a ! -d $DIR/configs ]; then
- cd $DIR
+ cd $DIR
+ if [ ! -d configs ]; then
mkdir configs
cvs add configs
cvs commit -m 'new' configs
- cd $BASEDIR
fi
# main files
- if [ ! -f $DIR/allrouters ]; then
- cd $DIR
- touch $DIR/allrouters
- cd $BASEDIR
+ if [ ! -f routers.all ]; then
+ touch routers.all
fi
- if [ ! -f $DIR/router.db ]; then
- cd $DIR
+ if [ ! -f routers.down ]; then
+ touch routers.down
+ fi
+ if [ ! -f routers.up ]; then
+ touch routers.up
+ fi
+ if [ ! -f router.db ]; then
touch router.db
cvs add router.db
cvs commit -m 'new' router.db
- cd $BASEDIR
fi
done
diff --git a/bin/cvs_helper b/bin/cvs_helper
deleted file mode 100644
index fe46435..0000000
--- a/bin/cvs_helper
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-##
-##
-## Copyright (C) 1996 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.
-##
-##
-#
-# cvs_helper
-#
-
-# Remove old config
-rm <file>
-cvs remove <file>
-
-# Look at an old revision...put file in <dir>
-cvs export -d <dir> -rX.YZ
-
diff --git a/bin/do-diffs b/bin/do-diffs
index 3b5eced..88cc445 100755
--- a/bin/do-diffs
+++ b/bin/do-diffs
@@ -37,7 +37,7 @@ do
/bin/rm -f $LOCKFILE
fi
- echo ending: `date`
echo
- ) >$BASEDIR/logs/$GROUP.`date +%y%m%d.%H%M%S` 2>&1
+ echo ending: `date`
+ ) >$BASEDIR/logs/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1
done
diff --git a/bin/env b/bin/env
index 14ae8a1..236ceca 100644
--- a/bin/env
+++ b/bin/env
@@ -9,13 +9,25 @@ TERM=network;export TERM
# a log directory for the logs from rancid and a directory for each group
# of routers. In addition to these directories, there will be the CVS
# repositories as well.
+# use a full path (no sym-links) for BASEDIR. some versions of CVS seemingly
+# don't take kindly to sym-links.
#
BASEDIR=$HOME/rancid; export BASEDIR
PATH=$BASEDIR/bin:/usr/local/bin:/usr/ucb:/usr/bin:/bin:/usr/lib:/usr/sbin;export PATH
CVSROOT=$BASEDIR/CVS; export CVSROOT
+#
+# if NOPIPE is set, temp files will be used instead of a cmd pipe during
+# collection from the router(s).
+#NOPIPE=YES; export NOPIPE
+#
LIST_OF_GROUPS="sl joebobisp"
-# For each group, define a list of people to receive the diffs
+#
+# For each group, define a list of people to receive the diffs.
# in a .mailrc file in the following format:
# alias rancid-$GROUP hank@rem.com pwhiting@sprint.net
+# or sendmail's /etc/aliases.
+# rancid-group: joe,moe@foo
+# rancid-group-admin: hostmaster
+# be sure to read ../README regarding aliases.
#
umask 007
diff --git a/bin/flogin b/bin/flogin
new file mode 100755
index 0000000..b168762
--- /dev/null
+++ b/bin/flogin
@@ -0,0 +1,530 @@
+#!/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.
+##
+##
+#
+# flogin - foundry login
+#
+# Most options are intuitive for logging into a foundry switch.
+# this should be the clogin, but foundry can't seem to dislodge
+# their heads and make the UI consistent. i think the UI
+# development has been outsourced to Fisher Price.
+# The default is to enable (thus -noenable). Some folks have
+# setup tacacs to have a user login at priv-lvl = 15 (enabled)
+# so the -autoenable flag was added for this case (don't go through
+# the process of enabling and the prompt will be the "#" prompt.
+# The default username password is the same as the vty password.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-u user\] \[-p user-password\] \[-v vty-password\] \
+\[-w enable-username\] \[-e enable-password\] \[-noenable\] \
+\[-f cloginrc-file\] \[-y ssh_cypher_type\] \[-c command\] \[-s script-file\] \
+\[-autoenable\] \[-t timeout\] 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
+set do_enapasswd 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* {
+ if {! [ regexp .\[wW\](.+) $arg ignore enauser]} {
+ incr i
+ set enausername [ lindex $argv $i ]
+ }
+ # Enable Password
+ } -e* -
+ -E* {
+ if {! [ regexp .\[eE\](.+) $arg ignore enapasswd]} {
+ incr i
+ set enapasswd [ lindex $argv $i ]
+ }
+ set do_enapasswd 0
+ # 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
+ # 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 ]
+ }
+ } -t* -
+ -T* {
+ incr i
+ set timeout [ lindex $argv $i ]
+ } -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 {
+ set enable 0
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ set autoenable 1
+ set enable 0
+ } -* {
+ 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
+ }
+ 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 enapasswd prompt cyphertype } {
+ global spawn_id in_proc do_command do_script
+ 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"
+ close; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ } eof {
+ send_user "\nError: EOF received\n"
+ close; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ }
+ }
+
+ # Here we get a little tricky. There are several possibilities:
+ # the router can ask for a username and passwd and then
+ # talk to the TACACS server to authenticate you, or if the
+ # TACACS server is not working, then it will use the enable
+ # passwd. Or, the router might not have TACACS turned on,
+ # then it will just send the passwd.
+ # if telnet fails with connection refused, try ssh
+ expect {
+ "Connection refused" {
+ close; wait
+ if { $tryssh } {
+ if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
+ send_user "Error: failed to ssh: $reason\n"
+ exit 1
+ }
+ set tryssh 0
+ sleep 0.3
+ exp_continue
+ } else {
+ 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 "Host key not found .* \(yes\/no\)\?" {
+ send "yes\r"
+ send_user "Host $router added to the list of known hosts.\n"
+ exp_continue }
+ -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n"
+ return 1 }
+ -re "(Username:|login:|Name :)" {
+ sleep 1;
+ send "$user\r"
+ expect {
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ -re "\[Pp]assword:" { send "$userpswd\r" }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ "\[Pp]assword:" { send "$passwd\r"
+ expect {
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ "Password:" { send "$enapasswd\r" }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ "$prompt" { }
+ denied { send_user "Error: Check your passwd for $router\n"
+ if { $do_command || $do_script } {
+ send "quit"
+ wait
+ return 1
+ } else {
+ return 1
+ }
+ }
+ "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 }
+ }
+ set in_proc 0
+ return 0
+}
+
+# Enable
+proc do_enable { enauser enapasswd } {
+ global prompt in_proc
+ set in_proc 1
+
+ sleep 1; # dont go too fast for it now...
+ send "enable\r"
+ expect {
+ -re "(Username|User Name):" { send "$enauser\r"; exp_continue}
+ "Password:" { send "$enapasswd\r"; exp_continue}
+ "#" { }
+ denied { send_user "Error: Check your Enable passwd\n"; return 1}
+ "% Bad passwords" { send_user "Error: Check your Enable passwd\n"
+ return 1
+ }
+ }
+ # Set the prompt variable so script files don't need to know what it is.
+ set prompt "#"
+ 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 "skip-page-display\r"
+ expect $prompt {}
+
+ # 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 [lindex $commands $i]]\r"
+ expect {
+ -re "^\[^\n\r]*$prompt." { exp_continue }
+ -re "^\[^\n\r *]*$prompt" {}
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ } else {
+ send "[subst $command]\r"
+ expect {
+ -re "^\[^\n\r]*$prompt." { exp_continue }
+ -re "^\[^\n\r *]*$prompt" {}
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ send "exit\r"
+ expect {
+ "\n" { exp_continue }
+ -re "^\[^ ]+>" {
+ send "exit\r"
+ 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.
+ # Since autoenable is off by default, if we have it defined, it
+ # was done on the command line. If it is not specifically set on the
+ # command line, check the password file.
+ if $autoenable {
+ set prompt "#"
+ } else {
+ set ae [find autoenable $router]
+ if { "$ae" == "1" } {
+ set autoenable 1
+ set enable 0
+ set prompt "#"
+ } else {
+ set autoenable 0
+ set prompt ">"
+ }
+ }
+
+ # Figure out passwords
+ if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user "Error - no password for $router in $password_file.\n"
+ continue
+ }
+ if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
+ send_user "Error - no enable password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [lindex $pswd 0]
+ set enapasswd [lindex $pswd 1]
+ }
+
+ # 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 enable username
+ if {[info exists enausername]} {
+ # command line enausername
+ set enauser $enausername
+ } else {
+ set enauser [find enauser $router]
+ if { "$enauser" == "" } { set enauser $ruser }
+ }
+
+ # Figure out cypher tpye
+ 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 $enapasswd $prompt $cyphertype]} {
+ continue
+ }
+ if { $enable } {
+ if {[do_enable $enauser $enapasswd]} {
+ if { $do_command || $do_script } {
+ close; wait
+ continue
+ }
+ }
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+ # fucking foundry
+ send "skip-page-display\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/francid b/bin/francid
new file mode 100755
index 0000000..3050aee
--- /dev/null
+++ b/bin/francid
@@ -0,0 +1,383 @@
+#!/usr/local/bin/perl
+##
+## Amazingly hacked version of Hank's rancid - this one tries to
+## deal with foundrys.
+##
+## 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 {
+ my($slot);
+
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ next if /^\s*$/;
+ last if(/^$prompt/);
+
+ next if (/^The system /);
+
+ s/^\s*(HW|SW)/$1/;
+ s/^\s*(Compiled on)/SW: $1/;
+ #s/^(HW.*)/$1\n/;
+ if (/^SL (\d)/) {
+ $slot = "Slot $1";
+ s/^SL \d+/$slot/;
+ }
+ if (/MHz .* processor/) {
+ $slot = "MGMT";
+ }
+ s/^(\s*\d+ )/$slot:$1/;
+ s/^===*//;
+
+ ProcessHistory("VERSION","","","!$_");
+ }
+ ProcessHistory("VERSION","","","!\n");
+ return(0);
+}
+
+# This routine parses "show chassis"
+sub ShowChassis {
+ print STDERR " In ShowChassis: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/ from /);
+ ProcessHistory("CHASSIS","","","! $_");
+ }
+ ProcessHistory("CHASSIS","","","!\n");
+ return(0);
+}
+
+# This routine parses "show flash"
+sub ShowFlash {
+ print STDERR " In ShowFlash: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if /^\s*$/;
+ ProcessHistory("FLASH","","","!Flash: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return;
+}
+
+# This routine parses "show module"
+sub ShowModule {
+ print STDERR " In ShowModule: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if /^\s*$/;
+ next if /:\s*$/;
+ ProcessHistory("MODULE","","","!Module: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /Current configuration:/i && next;
+ /^ver \d+\.\d+/ && next;
+ /^module \d+ / && next;
+
+ /^ntp clock-period / && next; # kill ntp clock-period
+ /^ length / && next; # kill length on serial lines
+ /^ width / && next; # kill width on serial lines
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+ # order access-lists
+ /^access-list\s+(\d+)\s+(perm|deny)\s+(\d\S+)(\/\d+)\s*$/ &&
+ ProcessHistory("PACL $1 $2","ipsort","$3","$_")
+ && next;
+ /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
+ ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next;
+ # order extended access-lists
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^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+/ &&
+ ProcessHistory("ARP","ipsort","$1","$_") && next;
+ # order logging statements
+ /^logging (\d+\.\d+\.\d+\.\d+)/ &&
+ ProcessHistory("LOGGING","ipsort","$1","$_") && next;
+ # 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;
+
+ # delete ntp auth password
+ /^(ntp authentication-key \d+ md5) / &&
+ 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);
+ ProcessHistory("NTP","keysort",$sortkey,"$_");
+ next;
+ }
+ # order ip host line statements
+ /^ip host line(\d+)/ &&
+ ProcessHistory("IPHOST","numsort","$1","$_") && next;
+ # order ip nat source static statements
+ /^ip nat (\S+) source static (\S+)/ &&
+ ProcessHistory("IP NAT $1","ipsort","$2","$_") && next;
+
+ ProcessHistory("","","","$_");
+ # end of config
+ if (/^end$/) {
+ $found_end = 1;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'show version' => "ShowVersion",
+ 'show chassis' => "ShowChassis",
+ 'show module' => "ShowModule",
+ 'show flash' => "ShowFlash",
+ 'write term' => "WriteTerm"
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important. pita
+@commands=(
+ "show version",
+ "show chassis",
+ "show module",
+ "show flash",
+ "write term"
+);
+$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 flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "flogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "flogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "flogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"flogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "flogin failed for $host: $!\n";
+ }
+}
+
+while(<INPUT>) {
+ tr/\015//d;
+ if (/\#exit$/) {
+ $clean_run=1;
+ last;
+ }
+ if (/Error:/) {
+ s/^.*Error:/Error:/;
+ print STDOUT ("$host flogin error: $_");
+ print STDERR ("$host flogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/#\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 b5b968e..c879737 100755
--- a/bin/jrancid
+++ b/bin/jrancid
@@ -138,86 +138,162 @@ sub sortbyipaddr {
# This routine parses "show chassis clocks"
sub ShowChassisClocks {
print STDERR " In ShowChassisClocks: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show chassis environment"
sub ShowChassisEnvironment {
print STDERR " In ShowChassisEnvironment: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- /Couldn\'t initiate connection/ && return;
- / backplane temperature/ && return;
- /(\s*Power supply.*), temperature/ && ProcessHistory("","","","# $1\n") && return;
- /(\s*.+) +\d+ degrees C.*$/ && ProcessHistory("","","","# $1\n") && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ /Couldn\'t initiate connection/ && return;
+ / backplane temperature/ && return;
+ /(\s*Power supply.*), temperature/ &&
+ ProcessHistory("","","","# $1\n") && next;
+ /(\s*.+) +\d+ degrees C.*$/ &&
+ ProcessHistory("","","","# $1\n") && next;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show chassis firmware"
sub ShowChassisFirmware {
print STDERR " In ShowChassisFirmware: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show chassis fpc detail"
sub ShowChassisFpcDetail {
print STDERR " In ShowChassisFpcDetail: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- / Temperature:/ && return;
- / Start time:/ && return;
- / Uptime:/ && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ / Temperature:/ && next;
+ / Start time:/ && next;
+ / Uptime:/ && next;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show chassis hardware"
sub ShowChassisHardware {
print STDERR " In ShowChassisHardware: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show chassis routing-engine"
sub ShowChassisRoutingEngine {
print STDERR " In ShowChassisRoutingEngine: $_" if ($debug);
- /^Routing Engine status:/ && ProcessHistory("","","","# $_") && return;
- / DRAM:/ && ProcessHistory("","","","# $_") && return;
- /^\s*$/ && ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /^Routing Engine status:/ && ProcessHistory("","","","# $_") && next;
+ / DRAM:/ && ProcessHistory("","","","# $_") && next;
+ /^\s*$/ && ProcessHistory("","","","# $_") && next;
+ }
return;
}
# This routine parses "show chassis scb"
sub ShowChassisSCB {
print STDERR " In ShowChassisSCB: $_" if ($debug);
- /error: the chassis subsystem is not running/ && return;
- / Temperature:/ && return;
- / utilization:/ && return;
- /time:/ && return;
- / (IP|MLPS) routes:/ && return;
- / used:/ && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /error: the chassis subsystem is not running/ && return;
+ / Temperature:/ && next;
+ / utilization:/ && next;
+ /time:/ && next;
+ / (IP|MLPS) routes:/ && next;
+ / used:/ && next;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show version"
sub ShowVersion {
print STDERR " In ShowVersionAndBlame: $_" if ($debug);
- /^Juniper Networks is:/ && ProcessHistory("","","","\n$_") && return;
- ProcessHistory("","","","# $_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /^Juniper Networks is:/ && ProcessHistory("","","","\n$_") && return;
+ ProcessHistory("","","","# $_");
+ }
return;
}
# This routine parses "show configuration"
sub ShowConfiguration {
print STDERR " In ShowConfiguration: $_" if ($debug);
- /^database header mismatch: / && return(-1);
- s/(\s*authentication-key ).*$/#$1<removed>;/;
- ProcessHistory("","","","$_") && return;
+
+ s/^[a-z]+@//;
+ ProcessHistory("","","","# $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if (/^\s*$/);
+
+ /^database header mismatch: / && return(-1);
+ s/(\s*authentication-key ).*$/#$1<removed>;/;
+ s/^(.*\ssecret \")\$9\$.*(\".*)$/#$1<removed>$2/;
+ ProcessHistory("","","","$_");
+ }
return;
}
@@ -228,39 +304,37 @@ sub ShowConfiguration {
# dummy function
sub DoNothing {print STDOUT;}
-# Main subroutine that splits up the work
-# All Subs return the name of the next function to use.
-# If the sub returns a new funtion name, that name will be used
-# else the main loop keeps using the current function
-sub FlailHelplessly {
- print STDERR "Flailing: $_" if ($debug);
- print STDOUT "Flailing: $_" if ($log);
- /(show chassis clocks)/ && delete($commands{$1}) && return("ShowChassisClocks");
- /(show chassis environment)/ && delete($commands{$1}) && return("ShowChassisEnvironment");
- /(show chassis firmware)/ && delete($commands{$1}) && return("ShowChassisFirmware");
- /(show chassis fpc detail)/ && delete($commands{$1}) && return("ShowChassisFpcDetail");
- /(show chassis hardware)/ && delete($commands{$1}) && return("ShowChassisHardware");
- /(show chassis routing-engine)/ && delete($commands{$1}) && return("ShowChassisRoutingEngine");
- /(show chassis scb)/ && delete($commands{$1}) && return("ShowChassisSCB");
- /(show version)/ && delete($commands{$1}) && return("ShowVersion");
- /(show configuration)/ && delete($commands{$1}) && return("ShowConfiguration");
- return "FlailHelplessly";
-}
-
# Main
-@commands=("show chassis clocks", "show chassis environment",
- "show chassis firmware", "show chassis fpc detail",
- "show chassis hardware", "show chassis routing-engine",
- "show chassis scb", "show version", "show configuration");
+%commands=(
+ "show chassis clocks" => "ShowChassisClocks",
+ "show chassis environment" => "ShowChassisEnvironment",
+ "show chassis firmware" => "ShowChassisFirmware",
+ "show chassis fpc detail" => "ShowChassisFpcDetail",
+ "show chassis hardware" => "ShowChassisHardware",
+ "show chassis routing-engine" => "ShowChassisRoutingEngine",
+ "show chassis scb" => "ShowChassisSCB",
+ "show version" => "ShowVersion",
+ "show configuration" => "ShowConfiguration"
+);
+@commands=(
+ "show chassis clocks",
+ "show chassis environment",
+ "show chassis firmware",
+ "show chassis fpc detail",
+ "show chassis hardware",
+ "show chassis routing-engine",
+ "show chassis scb",
+ "show version",
+ "show configuration"
+);
-foreach $c (@commands) { $commands{$c} = 1; }
$jnx_commands=join(";",@commands);
$cmds_regexp=join("|",@commands);
-$func = FlailHelplessly;
open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
# make OUTPUT unbuffered
-select(OUTPUT); $| = 1;
+if ($debug) { $| = 1; }
if ($file) {
print STDERR "opening file $host\n" if ($debug);
@@ -269,17 +343,19 @@ if ($file) {
} else {
print(STDERR "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug);
print(STDOUT "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug);
- open(INPUT,"jlogin -c\"$jnx_commands\" $host </dev/null |") ||
- die "jlogin failed for $host: $!\n";
+
+ if (defined($ENV{NOPIPE})) {
+ system "jlogin -c \"$jnx_commands\" $host </dev/null > $host.raw" || die "jlogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "jlogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"jlogin -c \"$jnx_commands\" $host </dev/null |") || die "jlogin failed for $host: $!\n";
+ }
+
}
while(<INPUT>) {
tr/\015//d;
- if (/quit/) {
- delete($commands{"quit"});
- $clean_run=1;
- last;
- }
if (/^Error:/) {
+ s/^.*Error:/Error:/;
print STDOUT ("$host jlogin error: $_");
print STDERR ("$host jlogin error: $_") if ($debug);
$clean_run=0;
@@ -291,17 +367,25 @@ while(<INPUT>) {
$clean_run = 0;
last;
}
- if (/($cmds_regexp)/) {
- ProcessHistory("","","","# $host> $1\n");
- $func = FlailHelplessly;
+ while (/>\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; }
print STDERR ("HIT COMMAND:$_") if ($debug);
- } else {
- $rval=eval $func;
+ 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;
- }
- $func=$rval if ($rval);
+ }
+ }
+ if (/>\s*quit/) {
+ $clean_run=1;
+ last;
}
}
print STDOUT "Done jlogin: $_\n" if ($log);
@@ -311,17 +395,21 @@ ProcessHistory("","","","");
close(INPUT);
close(OUTPUT);
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
# check for completeness
$commands = join(", ", keys(%commands));
if (scalar(%commands) || !$clean_run) {
if (scalar(%commands)) {
- print STDOUT "missed cmd(s): $commands\n";
- print STDERR "missed cmd(s): $commands[0]\n" if ($debug);
+ 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) {
- print STDOUT "End of run not found - removing $host.new\n";
- print STDERR "End of run not found - removing $host.new\n" if ($debug);
+ 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";
+ unlink "$host.new" if (! $debug);
}
diff --git a/bin/rancid b/bin/rancid
index 9b346fe..cd0cb8c 100755
--- a/bin/rancid
+++ b/bin/rancid
@@ -28,7 +28,7 @@ $file = $opt_f;
$host = $ARGV[0];
$clean_run = 0;
$found_end = 0;
-$timeo = 90; # clogin time in seconds
+$timeo = 90; # clogin timeout in seconds
# This routine is used to print out the router configuration
sub ProcessHistory {
@@ -89,8 +89,8 @@ sub valsort{
local($i) = 0;
local(@sorted_lines);
foreach $key (sort values %lines) {
- $sorted_lines[$i] = $key;
- $i++;
+ $sorted_lines[$i] = $key;
+ $i++;
}
@sorted_lines;
}
@@ -133,113 +133,141 @@ sub sortbyipaddr {
# This routine parses "show version"
sub ShowVersion {
print STDERR " In ShowVersion: $_" if ($debug);
- if (/^Slave in slot (\d+) is running/) {
- $slave = " Slave:";
- return;
- }
- /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
- ProcessHistory("COMMENTS","keysort","F1","!Image:$slave Software: $1, $2\n") && return;
- /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ &&
- ProcessHistory("COMMENTS","keysort","F2",
- "!Image:$slave $1 Synced to mainline version: $2\n") && return;
- /^Compiled (.*)$/ &&
- ProcessHistory("COMMENTS","keysort","F3","!Image:$slave Compiled: $1\n") && return;
- /^ROM: (System )?Bootstrap.*(Version.*)$/ &&
- ProcessHistory("COMMENTS","keysort","G1","!ROM Bootstrap: $2\n") && return;
- /^ROM: \d+ Bootstrap .*(Version.*)$/ &&
- ProcessHistory("COMMENTS","keysort","G2","!ROM Image: Bootstrap$1\n") &&
- return;
- /^ROM: .*(Version.*)$/ &&
- ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && return;
- /^BOOTFLASH: .*(Version.*)$/ &&
- ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && return;
- /^System image file is "([^\"]*)", booted via (\S*)/ &&
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+ if (/^Slave in slot (\d+) is running/) {
+ $slave = " Slave:";
+ next;
+ }
+ /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F1",
+ "!Image:$slave Software: $1, $2\n") && next;
+ /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F2",
+ "!Image:$slave $1 Synced to mainline version: $2\n") && next;
+ /^Compiled (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","F3",
+ "!Image:$slave Compiled: $1\n") && next;
+ /^ROM: (System )?Bootstrap.*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G1",
+ "!ROM Bootstrap: $2\n") && next;
+ /^ROM: \d+ Bootstrap .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G2",
+ "!ROM Image: Bootstrap $1\n!\n") && next;
+ /^ROM: .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && next;
+ /^BOOTFLASH: .*(Version.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && next;
+ /^System image file is "([^\"]*)", booted via (\S*)/ &&
# removed the booted source due to
# CSCdk28131: cycling info in 'sh ver'
# ProcessHistory("COMMENTS","keysort","F4","!Image: booted via $2, $1\n") &&
- ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") &&
- return;
- /^System image file is "([^\"]*)"$/ &&
- ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") &&
- return;
- if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+K) bytes/) {
- if ( $1 eq "CSC") {
- $type = "AGS";
- } elsif ( $1 eq "CSC4") {
- $type = "AGS+";
- } elsif ( $1 eq "RSP1") {
- $type = "7500";
- } elsif ( $1 eq "RSP2") {
- $type = "7500";
- } elsif ( $1 eq "RSP4") {
- $type = "7500";
- } elsif ( $1 eq "RSP7000") {
- $type = "7500";
- } elsif ( $1 eq "RP1") {
- $type = "7000";
- } elsif ( $1 eq "RP") {
- $type = "7000";
- } elsif ( $1 eq "7202" || $1 eq "7204" || $1 eq "7206") {
- $type = "7200";
- } elsif ($1 eq "12004/GRP" || $1 eq "12008/GRP" || $1 eq "12012/GRP") {
- $type = "12000";
- } else {
- $type = $1;
+ ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") &&
+ next;
+ /^System image file is "([^\"]*)"$/ &&
+ ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next;
+ if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+K) bytes/) {
+ my($proc) = $1;
+ my($cpu) = $2;
+ my($mem) = $3;
+ if ( $1 eq "CSC") {
+ $type = "AGS";
+ } elsif ( $1 eq "CSC4") {
+ $type = "AGS+";
+ } elsif ( $1 eq "RSP7000") {
+ $type = "7500";
+ } elsif ( $1 =~ /RSP\d/) {
+ $type = "7500";
+ } elsif ( $1 eq "RP1") {
+ $type = "7000";
+ } elsif ( $1 eq "RP") {
+ $type = "7000";
+ } elsif ( $1 eq "7202" || $1 eq "7204" || $1 eq "7206") {
+ $type = "7200";
+ } elsif ($1 eq "12004/GRP" || $1 eq "12008/GRP" || $1 eq "12012/GRP") {
+ $type = "12000";
+ } else {
+ $type = $1;
+ }
+ print STDERR "TYPE = $type\n" if ($debug);
+ ProcessHistory("COMMENTS","keysort","A1",
+ "!Chassis type:$slave $proc - a $type router\n");
+ ProcessHistory("COMMENTS","keysort","B1",
+ "!Memory:$slave main $mem\n");
+ ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n");
+ next;
+ }
+ if (/(\S+) Silicon\s*Switch Processor/) {
+ if (!defined($C0)) {
+ $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ }
+ ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n");
+ $ssp = 1;
+ $sspmem = $1;
+ next;
+ }
+ /^(\d+K) bytes of multibus/ &&
+ ProcessHistory("COMMENTS","keysort","B2",
+ "!Memory: multibus $1\n") && next;
+ /^(\d+K) bytes of non-volatile/ &&
+ ProcessHistory("COMMENTS","keysort","B3",
+ "!Memory: nvram $1\n") && next;
+ /^(\d+K) bytes of flash memory/ &&
+ ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") &&
+ next;
+ /^(\d+K) bytes of .*flash partition/ &&
+ ProcessHistory("COMMENTS","keysort","B6",
+ "!Memory: flash partition $1\n") && next;
+ /^(\d+K) bytes of Flash internal/ &&
+ ProcessHistory("COMMENTS","keysort","B4",
+ "!Memory: bootflash $1\n") && next;
+ if(/^(\d+K) bytes of (Flash|ATA)?.*PCMCIA .*slot ?(\d)/i) {
+ ProcessHistory("COMMENTS","keysort","B7",
+ "!Memory: pcmcia $2 slot$3 $1\n");
+ next;
+ }
+ if (/^Configuration register is (.*)$/) {
+ $config_register=$1;
+ next;
}
- print STDERR "TYPE = $type\n" if ($debug);
- ProcessHistory("COMMENTS","keysort","A1","!Chassis type:$slave $1 - a $type router\n");
- ProcessHistory("COMMENTS","keysort","B1","!Memory:$slave main $3\n");
- ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $2\n");
- return;
- }
- if (/(\S+) Silicon\s*Switch Processor/) {
- if (!defined($C0)) {$C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");}
- ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n");
- $ssp = 1;
- $sspmem = $1;
- return;
- }
- /^(\d+K) bytes of multibus/ &&
- ProcessHistory("COMMENTS","keysort","B2","!Memory: multibus $1\n") && return;
- /^(\d+K) bytes of non-volatile/ &&
- ProcessHistory("COMMENTS","keysort","B3","!Memory: nvram $1\n") && return;
- /^(\d+K) bytes of flash memory/ &&
- ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") &&
- return;
- /^(\d+K) bytes of .*flash partition/ &&
- ProcessHistory("COMMENTS","keysort","B6","!Memory: flash partition $1\n") &&
- return;
- /^(\d+K) bytes of Flash internal/ &&
- ProcessHistory("COMMENTS","keysort","B4","!Memory: bootflash $1\n") &&
- return;
- /^(\d+K) bytes of Flash PCMCIA card at slot 0 / &&
- ProcessHistory("COMMENTS","keysort","B7","!Memory: pcmcia slot0 $1\n") && return;
- /^(\d+K) bytes of Flash PCMCIA card at slot 1 / &&
- ProcessHistory("COMMENTS","keysort","B8","!Memory: pcmcia slot1 $1\n") && return;
- if (/^Configuration register is (.*)$/) {
- $config_register=$1;
- return;
}
- return;
+ return(0);
}
# This routine parses "show env all"
sub ShowEnv {
# Skip if this is not a 7500 or 7000.
print STDERR " In ShowEnv: $_" if ($debug);
- return if ($type !~ /^7/);
- if (!defined($E0)) {$E0=1; ProcessHistory("COMMENTS","keysort","E0","!\n");}
- if (/^Arbiter type (\d), backplane type (\S+)/) {
- if (!defined($C0)) {$C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");}
- ProcessHistory("COMMENTS","keysort","C1","!Enviromental Arbiter Type: $1\n");
- ProcessHistory("COMMENTS","keysort","A2","!Chassis type: $2 backplane\n");
- return;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^7/);
+ if (!defined($E0)) {
+ $E0=1;
+ ProcessHistory("COMMENTS","keysort","E0","!\n");
+ }
+ if (/^Arbiter type (\d), backplane type (\S+)/) {
+ if (!defined($C0)) {
+ $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n");
+ }
+ ProcessHistory("COMMENTS","keysort","C1",
+ "!Enviromental Arbiter Type: $1\n");
+ ProcessHistory("COMMENTS","keysort","A2",
+ "!Chassis type: $2 backplane\n");
+ next;
+ }
+ /^\s*(Power .*)/ &&
+ ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next;
+ /^\s*(Lower Power .*)/i &&
+ ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
}
- /^\s*(Power .*)/ &&
- ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && return;
- /^\s*(Lower Power .*)/i &&
- ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && return;
- return;
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
}
# This routine parses "show gsr chassis-info" for the gsr
@@ -247,135 +275,153 @@ sub ShowEnv {
sub ShowGSR {
# Skip if this is not a 1200n.
print STDERR " In ShowGSR: $_" if ($debug);
- return if ($type !~ /^120/);
- /^$/ && return;
- /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ &&
- ProcessHistory("COMMENTS","keysort","D0","!\n") &&
- ProcessHistory("COMMENTS","keysort","D1","!GSR Chassis type: $1 Fab Ver: $2\n") && return;
- /^\s+Chassis S\/N: (.*)$/ &&
- ProcessHistory("COMMENTS","keysort","D2","!GSR Chassis S/N: $1\n") && return;
- /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ &&
- ProcessHistory("COMMENTS","keysort","D3","!GSR Backplane PCA: $1, rev $2, ver $3\n") && return;
- /^\s+Backplane S\/N: (\S+)$/ &&
- ProcessHistory("COMMENTS","keysort","D4","!GSR Backplane S/N: $1\n") && return;
- return;
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^120/);
+ /^$/ && next;
+ /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ &&
+ ProcessHistory("COMMENTS","keysort","D0","!\n") &&
+ ProcessHistory("COMMENTS","keysort","D1",
+ "!GSR Chassis type: $1 Fab Ver: $2\n") &&
+ next;
+ /^\s+Chassis S\/N: (.*)$/ &&
+ ProcessHistory("COMMENTS","keysort","D2",
+ "!GSR Chassis S/N: $1\n") &&
+ next;
+ /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ &&
+ ProcessHistory("COMMENTS","keysort","D3",
+ "!GSR Backplane PCA: $1, rev $2, ver $3\n") &&
+ next;
+ /^\s+Backplane S\/N: (\S+)$/ &&
+ ProcessHistory("COMMENTS","keysort","D4",
+ "!GSR Backplane S/N: $1\n") &&
+ next;
+ }
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
}
# This routine parses "show boot"
sub ShowBoot {
# Pick up boot variables if 7000/7500/12000; otherwise pick up bootflash.
print STDERR " In ShowBoot: $_" if ($debug);
- return if /^\s*$/;
- return if /^\s*\^\s*$/;
- return if /Invalid input detected/;
- return if /(Open device \S+ failed|Error opening \S+:)/;
- if (!defined($H0)) {$H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");}
- if ($type !~ /^(1200|7)/) {
- ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
- } elsif (/variable/) {
- ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Ambiguous command/i;
+ return(1) if /Invalid input detected/;
+ return(1) if /(Open device \S+ failed|Error opening \S+:)/;
+ next if /CONFGEN variable/;
+ if (!defined($H0)) {
+ $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
+ }
+ if ($type !~ /^(1200|7)/) {
+ ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
+ } elsif (/variable/) {
+ ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
+ }
}
- return;
+ ProcessHistory("COMMENTS","","","!\n");
+ return(0);
}
# This routine parses "show flash"
sub ShowFlash {
# skip if this is 7000, 7200, 7500, or 12000.
print STDERR " In ShowFlash: $_" if ($debug);
- return if /^\s*$/;
- return if ($type =~ /^(1200|7.0)/);
- return if /^\s*\^\s*$/;
- return if /Invalid input detected/;
- ProcessHistory("FLASH","","","!Flash: $_");
- return;
-}
-
-# This routine parses "dir /all bootflash:"
-sub DirBootflash {
- # Skip if this is not a 7000, 7200, 7500, or 12000.
- print STDERR " In DirBootflash: $_" if ($debug);
- return if /^\s*$/;
- return if ($type !~ /^(1200|7.0)/);
- return if /^\s*\^\s*$/;
- return if /Invalid input detected/;
- /: device being squeezed/ && return(-1); # Flash is busy
- return if /(Open device \S+ failed|Error opening \S+:)/;
- ProcessHistory("FLASH","","","!Flash: BootFlash: $_");
- return;
-}
-# This routine parses "dir /all slot0:"
-sub DirSlot0 {
- # Skip if this is not a 3600, 7000, 7200, 7500, or 12000.
- print STDERR " In DirSlot0: $_" if ($debug);
- return if /^\s*$/;
- return if ($type !~ /^(1200|7.0|36.0)/);
- return if /^\s*\^\s*$/;
- return if /Invalid input detected/;
- /: device being squeezed/ && return(-1); # Flash is busy
- return if /(Open device \S+ failed|Error opening \S+:)/;
- ProcessHistory("FLASH","","","!Flash: Slot0: $_");
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type =~ /^(1200|7.0)/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Invalid input detected/;
+ ProcessHistory("FLASH","","","!Flash: $_");
+ }
+ ProcessHistory("","","","!\n");
return;
}
-# This routine parses "dir /all slot1:"
-sub DirSlot1 {
+# This routine parses "dir /all ((disk|slot)N|bootflash):"
+sub DirSlotN {
# Skip if this is not a 3600, 7000, 7200, 7500, or 12000.
- print STDERR " In DirSlot1: $_" if ($debug);
- return if /^\s*$/;
- return if ($type !~ /^(1200|7.0|36.0)/);
- return if /^\s*\^\s*$/;
- return if /Invalid input detected/;
- /: device being squeezed/ && return(-1); # Flash is busy
- return if /(Open device \S+ failed|Error opening \S+:)/;
- ProcessHistory("FLASH","","","!Flash: Slot1: $_");
- return;
+ print STDERR " In DirSlotN: $_" if ($debug);
+
+ my($dev) = (/\s([^\s]+):/);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^(1200|7.0|36.0)/);
+ return(1) if /^\s*\^\s*$/;
+ return(1) if /Invalid input detected/;
+ return(1) if /No space information available/;
+ return(-1) if /\%Error calling/;
+ return(-1) if /: device being squeezed/; # Flash is busy
+ return(1) if /(Open device \S+ failed|Error opening \S+:)/;
+ ProcessHistory("FLASH","","","!Flash: $dev: $_");
+ }
+ ProcessHistory("","","","!\n");
+ return(0);
}
# This routine parses "show controllers"
sub ShowContAll {
# Skip if this is a 70[01]0, 7500, or 12000.
print STDERR " In ShowContAll: $_" if ($debug);
- return if ($type =~ /^(1200|7[05])/);
- if (/^Interface (\S*)$/) { $INT = "$1, "; return; }
- /^(BRI unit \d)/ &&
- ProcessHistory("INT","","","!Interface: $1\n") && return;
- /^LANCE unit \d, NIM/ &&
- ProcessHistory("INT","","","!Interface: $_") && return;
- /^(LANCE unit \d)/ &&
- ProcessHistory("INT","","","!Interface: $1\n") && return;
- /(Media Type is \S+),/ &&
- ProcessHistory("INT","","","!\t$1\n");
- if (/(M\dT:) show controller:$/) {
- my($ctlr) = $1;
- $_ = <INPUT>; tr/\015//d; s/ subunit \d,//;
- ProcessHistory("INT","","","!Interface: $ctlr $_");
- }
- /^(HD unit \d), idb/ &&
- ProcessHistory("INT","","","!Interface: $1\n") && return;
- /^HD unit \d, NIM/ &&
- ProcessHistory("INT","","","!Interface: $_") && return;
- /^buffer size \d+ HD unit \d, (.*)/ &&
- ProcessHistory("INT","","","!\t$1\n") && return;
- /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && return;
- /^buffer size \d+ (Universal Serial: .*)/ &&
- ProcessHistory("INT","","","!\t$1\n") && return;
- /^Hardware is (.*)/ &&
- ProcessHistory("INT","","","!Interface: $INT$1\n") && return;
- /^(QUICC Serial unit \d),/ &&
- ProcessHistory("INT","","","!$1\n") && return;
- /^QUICC Ethernet .*/ &&
- ProcessHistory("INT","","","!$_") && return;
- /^DTE .*\.$/ &&
- ProcessHistory("INT","","","!\t$_") && return;
- /^(cable type :.*),/ &&
- ProcessHistory("INT","","","!\t$1\n") && return;
- /^(.* cable.*), received clockrate \d+$/ &&
- ProcessHistory("INT","","","!\t$1\n") && return;
- /^.* cable.*$/ &&
- ProcessHistory("INT","","","!\t$_") && return;
- return;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type =~ /^(1200|7[05])/);
+ if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; }
+ /^(BRI unit \d)/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /^LANCE unit \d, NIM/ &&
+ ProcessHistory("INT","","","!Interface: $_") && next;
+ /^(LANCE unit \d)/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /(Media Type is \S+),/ &&
+ ProcessHistory("INT","","","!\t$1\n");
+ if (/(M\dT:) show controller:$/) {
+ my($ctlr) = $1;
+ $_ = <INPUT>; tr/\015//d; s/ subunit \d,//;
+ ProcessHistory("INT","","","!Interface: $ctlr $_");
+ }
+ /^(HD unit \d), idb/ &&
+ ProcessHistory("INT","","","!Interface: $1\n") && next;
+ /^HD unit \d, NIM/ &&
+ ProcessHistory("INT","","","!Interface: $_") && next;
+ /^buffer size \d+ HD unit \d, (.*)/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next;
+ /^buffer size \d+ (Universal Serial: .*)/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^Hardware is (.*)/ &&
+ ProcessHistory("INT","","","!Interface: $INT$1\n") && next;
+ /^(QUICC Serial unit \d),/ &&
+ ProcessHistory("INT","","","!$1\n") && next;
+ /^QUICC Ethernet .*/ &&
+ ProcessHistory("INT","","","!$_") && next;
+ /^DTE .*\.$/ &&
+ ProcessHistory("INT","","","!\t$_") && next;
+ /^(cable type :.*),/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^(.* cable.*), received clockrate \d+$/ &&
+ ProcessHistory("INT","","","!\t$1\n") && next;
+ /^.* cable.*$/ &&
+ ProcessHistory("INT","","","!\t$_") && next;
+ }
+ return(0);
}
# This routine parses "show controllers cbus"
@@ -383,37 +429,43 @@ sub ShowContAll {
sub ShowContCbus {
# Skip if this is not a 7000 or 7500.
print STDERR " In ShowContCbus: $_" if ($debug);
- return if ($type !~ /^7[05]0/);
- if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) {
- $slot = $1;
- $board{$slot} = $2;
- $hwver{$slot} = $3;
- $hwucode{$slot} = $4;
- } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) {
- $slot = $2;
- $board{$slot} = $1;
- $hwver{$slot} = $3;
- $hwucode{$slot} = $4;
- } elsif (/(Microcode .*)/) {
- $ucode{$slot} = $1;
- } elsif (/(software loaded .*)/) {
- $ucode{$slot} = $1;
- } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) {
- $hwmemd{$slot} = $1;
- $hwmemc{$slot} = $2;
- } elsif (/byte buffers/) {
- chop;
- s/^\s*//;
- $hwbuf{$slot} = $_;
- } elsif (/Interface (\d+) - (\S+ \S+),/) {
- $interface = $1;
- ProcessHistory("HW","","","!\n!Int $interface: in slot $slot, named $2\n");
- return;
- } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) {
- ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n");
- return;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^7[05]0/);
+ if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) {
+ $slot = $1;
+ $board{$slot} = $2;
+ $hwver{$slot} = $3;
+ $hwucode{$slot} = $4;
+ } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) {
+ $slot = $2;
+ $board{$slot} = $1;
+ $hwver{$slot} = $3;
+ $hwucode{$slot} = $4;
+ } elsif (/(Microcode .*)/) {
+ $ucode{$slot} = $1;
+ } elsif (/(software loaded .*)/) {
+ $ucode{$slot} = $1;
+ } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) {
+ $hwmemd{$slot} = $1;
+ $hwmemc{$slot} = $2;
+ } elsif (/byte buffers/) {
+ chop;
+ s/^\s*//;
+ $hwbuf{$slot} = $_;
+ } elsif (/Interface (\d+) - (\S+ \S+),/) {
+ $interface = $1;
+ ProcessHistory("HW","","",
+ "!\n!Int $interface: in slot $slot, named $2\n"); next;
+ } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) {
+ ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n");
+ next;
+ }
}
- return;
+ return(0);
}
# This routine parses "show diagbus"
@@ -421,73 +473,84 @@ sub ShowContCbus {
sub ShowDiagbus {
# Skip if this is not a 7000, 70[01]0, or 7500.
print STDERR " In ShowDiagbus: $_" if ($debug);
- return if ($type !~ /^7[05]/);
- if (/^\s*Slot (\d+):/i) {
- $slot = $1;
- return;
- } elsif (/^\s*Slot (\d+) \(virtual\):/i) {
- $slot = $1;
- return;
- } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) {
- $board = $1;
- $hwver = $2;
- $boardrev = $3;
- if ($board =~ /Processor/) {
- if ($board =~ /7000 Route\/Switch/) {
- $board = "RSP7000";
- } elsif ($board =~ /Route\/Switch Processor (\d)/) {
- $board = "RSP$1";
- } elsif ($board =~ /Route/) {
- $board = "RP";
- } elsif ($board =~ /Silicon Switch/) {
- $board = "SSP";
- } elsif ($board =~ /Switch/) {
- $board = "SP";
- $board = "SSP $sspmem" if $ssp;
- } elsif ($board =~ /ATM/) {
- $board = "AIP";
- }
- } elsif ($board =~ /(.*) controller/i) {
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^7[05]/);
+ if (/^\s*Slot (\d+):/i) {
+ $slot = $1;
+ next;
+ } elsif (/^\s*Slot (\d+) \(virtual\):/i) {
+ $slot = $1;
+ next;
+ } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) {
$board = $1;
- }
- # hwucode{$slot} defined in ShowContCbus
- if (defined $hwucode{$slot}) {
- ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n");
- } else {
- ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n");
- }
- # These are also from the ShowContCbus
- ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot});
- ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n")
+ $hwver = $2;
+ $boardrev = $3;
+ if ($board =~ /Processor/) {
+ if ($board =~ /7000 Route\/Switch/) {
+ $board = "RSP7000";
+ } elsif ($board =~ /Route\/Switch Processor (\d)/) {
+ $board = "RSP$1";
+ } elsif ($board =~ /Route/) {
+ $board = "RP";
+ } elsif ($board =~ /Silicon Switch/) {
+ $board = "SSP";
+ } elsif ($board =~ /Switch/) {
+ $board = "SP";
+ $board = "SSP $sspmem" if $ssp;
+ } elsif ($board =~ /ATM/) {
+ $board = "AIP";
+ }
+ } elsif ($board =~ /(.*) controller/i) {
+ $board = $1;
+ }
+ # hwucode{$slot} defined in ShowContCbus
+ if (defined $hwucode{$slot}) {
+ ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n");
+ } else {
+ ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n");
+ }
+ # These are also from the ShowContCbus
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot});
+ ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n")
if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot}));
- ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot});
- return;
- }
- /Serial number: (\S+)\s*Part number: (\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && return;
- /^\s*Controller Memory Size: (.*)$/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") &&
- return;
- if (/PA Bay (\d) Information/) {
- $pano = $1;
- if ("PA" =~ /$board/) {
- ($s,$c) = split(/\//,$board);
- $board = "$s/$c/PA $pano";
- } else {
- $board =~ s/\/PA \d//;
- $board = "$board/PA $pano";
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot});
+ next;
}
- return;
- }
- /\s+(.*) PA, (\d) ports?, (\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && return;
- /\s+(.*) PA( \(\S+\))?, (\d) ports?/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && return;
- /^\s*HW rev (\S+), Board revision (\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && return;
- /Serial number: (\S+)\s*Part number: (\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && return;
- return;
+ /Serial number: (\S+)\s*Part number: (\S+)/ &&
+ ProcessHistory("SLOT","","",
+ "!Slot $slot/$board: part $2, serial $1\n") &&
+ next;
+ /^\s*Controller Memory Size: (.*)$/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") &&
+ next;
+ if (/PA Bay (\d) Information/) {
+ $pano = $1;
+ if ("PA" =~ /$board/) {
+ ($s,$c) = split(/\//,$board);
+ $board = "$s/$c/PA $pano";
+ } else {
+ $board =~ s/\/PA \d//;
+ $board = "$board/PA $pano";
+ }
+ next;
+ }
+ /\s+(.*) PA, (\d) ports?, (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") &&
+ next;
+ /\s+(.*) PA( \(\S+\))?, (\d) ports?/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") &&
+ next;
+ /^\s*HW rev (\S+), Board revision (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") &&
+ next;
+ /Serial number: (\S+)\s*Part number: (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next;
+ }
+ return(0);
}
# This routine parses "show diags" for the gsr, 7200, 3600
@@ -495,75 +558,84 @@ sub ShowDiagbus {
sub ShowDiags {
# Skip if this is not a 12000.
print STDERR " In ShowDiags: $_" if ($debug);
- return if ($type !~ /^(1200|720|36.0)/);
- /^$/ && return;
- if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");}
- s/Port Packet Over SONET/POS/;
- if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) {
- $slot = $1;
- ProcessHistory("SLOT","","","!Slot $slot: $2\n");
- $board = "RP" if (/Route Processor/);
- $board = "CLK" if (/Clock Scheduler Card/);
- return;
- }
- if (/^\s+PCA:\s+(.*)/){
- local($part) = $1;
- $_ = <INPUT>;
- /^\s+HW version (\S+)\s+S\/N (\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") &&
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^(1200|720|36.0)/);
+ /^$/ && next;
+ if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");}
+ s/Port Packet Over SONET/POS/;
+ if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) {
+ $slot = $1;
+ ProcessHistory("SLOT","","","!Slot $slot: $2\n");
+ $board = "RP" if (/Route Processor/);
+ $board = "CLK" if (/Clock Scheduler Card/);
+ next;
+ }
+ if (/^\s+PCA:\s+(.*)/){
+ local($part) = $1;
+ $_ = <INPUT>;
+ /^\s+HW version (\S+)\s+S\/N (\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") &&
ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n");
- return;
- }
+ next;
+ }
- if (/^\s+MBUS: .*\)\s+(.*)/) {
- local($tmp) = "!Slot $slot/MBUS: part $1";
- $_ = <INPUT>;
- /^\s+HW version (\S+)\s+S\/N (\S+)/ &&
- ProcessHistory("SLOT","","","$tmp, serial $2\n") &&
+ if (/^\s+MBUS: .*\)\s+(.*)/) {
+ local($tmp) = "!Slot $slot/MBUS: part $1";
+ $_ = <INPUT>;
+ /^\s+HW version (\S+)\s+S\/N (\S+)/ &&
+ ProcessHistory("SLOT","","","$tmp, serial $2\n") &&
ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n");
- return;
- }
- if (/^\s+MBUS Agent Software version (.*)/) {
- local($sw) = $1;
- local($tail) = "!\n" if ($board =~ /(CLK|RP)/);
- ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail");
- return;
- }
- if (/^\s+DRAM size: (\d+)/) {
- local($dram) = $1 / 1048576;
- $_ = <INPUT>;
- /^\s+FrFab SDRAM size: (\d+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, "
+ next;
+ }
+ if (/^\s+MBUS Agent Software version (.*)/) {
+ local($sw) = $1;
+ local($tail) = "!\n" if ($board =~ /(CLK|RP)/);
+ ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail");
+ next;
+ }
+ if (/^\s+DRAM size: (\d+)/) {
+ local($dram) = $1 / 1048576;
+ $_ = <INPUT>;
+ /^\s+FrFab SDRAM size: (\d+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, "
. $1 / 1024 . " Kbytes SDRAM\n!\n");
- return;
- }
- # 7200 and 3600 stuff
- if (/^(Slot) (\d+):/ || /^\s+(WIC) Slot (\d):/) {
- if ($1 eq "WIC") {
- $WIC = "/$2";
- } else {
- $slot = $2;
- undef($WIC);
+ next;
}
- $_ = <INPUT>; tr/\015//d;
- # clean up hideous 7200 format to look more like 7500 output
- s/Fast-ethernet on C7200 I\/O card/FE-IO/;
- s/ with MII or RJ45/-TX/;
- s/Fast-ethernet /100Base/; s/[)(]//g;
-
- /\s+(.*)\s+port adapter?,\s+(\d+)\s+/ &&
- ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n");
- /\s+(.*)\s+daughter card(.*)$/ &&
- ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n");
- /\s+(FT1)$/ &&
- ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n");
- return;
- }
- /revision\s+(\S+).*revision\s+(\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && return;
- /number\s+(\S+)\s+Part number\s+(\S+)/ &&
- ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && return;
- return;
+ # 7200 and 3600 stuff
+ if (/^(Slot) (\d+):/ || /^\s+(WIC) Slot (\d):/) {
+ if ($1 eq "WIC") {
+ $WIC = "/$2";
+ } else {
+ $slot = $2;
+ undef($WIC);
+ }
+ $_ = <INPUT>; tr/\015//d;
+
+ # clean up hideous 7200 format to look more like 7500 output
+ s/Fast-ethernet on C7200 I\/O card/FE-IO/;
+ s/ with MII or RJ45/-TX/;
+ s/Fast-ethernet /100Base/; s/[)(]//g;
+
+ /\s+(.*)\s+port adapter?,\s+(\d+)\s+/ &&
+ ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n");
+ /\s+(.*)\s+daughter card(.*)$/ &&
+ ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n");
+ /\s+(FT1)$/ &&
+ ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n");
+ next;
+ }
+ /revision\s+(\S+).*revision\s+(\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") &&
+ next;
+ /number\s+(\S+)\s+Part number\s+(\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") &&
+ next;
+}
+ return(0);
}
# This routine parses "show c7200" for the 7200
@@ -571,173 +643,212 @@ sub ShowDiags {
sub ShowC7200 {
# Skip if this is not a 7200.
print STDERR " In ShowC7200: $_" if ($debug);
- return if ($type !~ /^72/);
- /^$/ && return;
- if (/C7200 Midplane EEPROM:/) {
- $_ = <INPUT>;
- /revision\s+(\S+).*revision\s+(\S+)/;
- ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n");
- $_ = <INPUT>;
- /number\s+(\S+)\s+Part number\s+(\S+)/;
- ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n");
- return;
- }
- if (/C7200 CPU EEPROM:/) {
- $_ = <INPUT>;
- /revision\s+(\S+).*revision\s+(\S+)/ &&
- ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n");
- $_ = <INPUT>;
- /number\s+(\S+)\s+Part number\s+(\S+)/ &&
- ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n");
- return;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^72/);
+ /^$/ && next;
+ if (/C7200 Midplane EEPROM:/) {
+ $_ = <INPUT>;
+ /revision\s+(\S+).*revision\s+(\S+)/;
+ ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n");
+ $_ = <INPUT>;
+ /number\s+(\S+)\s+Part number\s+(\S+)/;
+ ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n");
+ next;
+ }
+ if (/C7200 CPU EEPROM:/) {
+ $_ = <INPUT>;
+ /revision\s+(\S+).*revision\s+(\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n");
+ $_ = <INPUT>;
+ /number\s+(\S+)\s+Part number\s+(\S+)/ &&
+ ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n");
+ next;
+ }
}
- return;
+ return(0);
}
# This routine processes a "write term"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
- /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
- # skip the crap
- if (/^(##+$|Building configuration...)/i) {
- while (<INPUT>) {
- next if (/^Current configuration:/i);
- next if (/^([%!].*|\s*)$/);
- next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S
- last;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ # skip the crap
+ if (/^(##+$|Building configuration...)/i) {
+ while (<INPUT>) {
+ next if (/^Current configuration:/i);
+ next if (/^([%!].*|\s*)$/);
+ next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S
+ last;
+ }
+ ProcessHistory("","","","!\nconfig-register $config_register\n");
+ tr/\015//d;
+ }
+ # some versions have other crap mixed in with the bits in the
+ # block above
+ /^! (Last configuration|NVRAM config last)/ && next;
+
+ # Dog gone Cool matches to process the rest of the config
+ /^tftp-server flash / && next; # kill any tftp remains
+ /^ntp clock-period / && next; # kill ntp clock-period
+ /^ length / && next; # kill length on serial lines
+ /^ width / && next; # kill width on serial lines
+ /^enable password / &&
+ ProcessHistory("ENABLE","","","!enable password <removed>\n") &&
+ next;
+ /^(username .*) password \d *(\S)\s*(.*)/ &&
+ ProcessHistory("USER","","","!$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;
+ /fair-queue individual-limit/ && next;
+ # sort route-maps
+ if (/^route-map ([^ ]+)/) {
+ my($key) = $1;
+ my($routemap) = $_;
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/ || ! /^(route-map |[ !])/);
+ if (/^route-map ([^ ]+)/) {
+ ProcessHistory("ROUTEMAP","keysort","$key","$routemap");
+ $key = $1;
+ $routemap = $_;
+ } else {
+ $routemap .= $_;
+ }
+ }
+ ProcessHistory("ROUTEMAP","keysort","$key","$routemap");
+ }
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+ # order access-lists
+ /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
+ ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next;
+ # order extended access-lists
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
+ ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next;
+ /^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+/ &&
+ 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+)/ &&
+ ProcessHistory("LOGGING","ipsort","$1","$_") && next;
+ # 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 clns host statements
+ /^clns host \S+ (\S+)/ &&
+ ProcessHistory("CLNS","keysort","$1","$_") && next;
+ # order alias statements
+ /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next;
+ # delete ntp auth password
+ /^(ntp authentication-key \d+ md5) / &&
+ 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);
+ ProcessHistory("NTP","keysort",$sortkey,"$_");
+ next;
+ }
+ # order ip host line statements
+ /^ip host line(\d+)/ &&
+ ProcessHistory("IPHOST","numsort","$1","$_") && next;
+ # order ip nat source static statements
+ /^ip nat (\S+) source static (\S+)/ &&
+ ProcessHistory("IP NAT $1","ipsort","$2","$_") && next;
+ # order atm map-list statements
+ /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ &&
+ ProcessHistory("ATM map-list","ipsort","$1","$_") && next;
+ # order ip rcmd lines
+ /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next;
+
+ ProcessHistory("","","","$_");
+ # end of config
+ if (/^end$/) {
+ $found_end = 1;
+ return(1);
}
- ProcessHistory("","","","!\nconfig-register $config_register\n");
- tr/\015//d;
- }
- # Dog gone Cool matches to process the rest of the config
- /^tftp-server flash / && return; # kill and tftp remains
- /^ntp clock-period / && return; # kill ntp clock-period
- /^ length / && return; # kill length on serial lines
- /^ width / && return; # kill width on serial lines
- /^enable password / &&
- ProcessHistory("ENABLE","","","!enable password <removed>\n") &&
- return;
- /^(username .*) password \d *(\S)\s*(.*)/ &&
- ProcessHistory("USER","","","$1 password <removed>\n") &&
- return;
- /^\s*password / &&
- ProcessHistory("LINE-PASS","","","! password <removed>\n") &&
- return;
- /^\s*neighbor (\S*) password / &&
- ProcessHistory("","","","! neighbor $1 password <removed>\n") &&
- return;
- /fair-queue individual-limit/ && return;
- # filter out any RCS/CVS tags to avoid confusing local CVS storage
- s/\$(Revision|Id):/ $1:/;
- # order access-lists
- /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
- ProcessHistory("ACL $1 $2","ipsort","$3","$_") && return;
- # order extended access-lists
- /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
- ProcessHistory("EACL $1 $2","ipsort","$3","$_") && return;
- /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
- ProcessHistory("EACL $1 $2","ipsort","$3","$_") && return;
- /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
- ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && return;
- /^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")
- && return;
- # order logging statements
- /^logging (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("LOGGING","ipsort","$1","$_") && return;
- # order name-server statements
- /^ip name-server (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("NAMESERVER","ipsort","$1","$_") && return;
- # order snmp-server host statements
- /^snmp-server host (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_") && return;
- /^snmp-server community / &&
- ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && return;
- # order tacacs server statements
- /^tacacs-server host (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("TAC","ipsort","$1","$_") && return;
- # order clns host statements
- /^clns host \S+ (\S+)/ && ProcessHistory("CLNS","keysort","$1","$_") && return;
- # order alias statements
- /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && return;
- # delete ntp auth password
- /^(ntp authentication-key \d+ md5) / &&
- ProcessHistory("","","","!$1 <removed>\n") && return;
- # order ntp peers/servers
- if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
- $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
- ProcessHistory("NTP","keysort",$sortkey,"$_");
- return;
- }
- # order ip host line statements
- /^ip host line(\d+)/ &&
- ProcessHistory("IPHOST","numsort","$1","$_") && return;
- # order ip nat source static statements
- /^ip nat (\S+) source static (\S+)/ &&
- ProcessHistory("IP NAT $1","ipsort","$2","$_") && return;
- # order atm map-list statements
- /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ &&
- ProcessHistory("ATM map-list","ipsort","$1","$_") && return;
- # order ip rcmd lines
- /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && return;
- ProcessHistory("","","","$_");
- # end of config
- if (/^end$/) {
- $found_end = 1;
- return "FlailHelplessly";
}
- return;
+ return(0);
}
# dummy function
sub DoNothing {print STDOUT;}
-# Main subroutine that splits up the work
-# All Subs return the name of the next function to use.
-# If the sub returns a new funtion name, that name will be used
-# else the main loop keeps using the current function
-sub FlailHelplessly {
- print STDERR "Flailing: $_" if ($debug);
- print STDOUT "Flailing: $_" if ($log);
- /#(show version)$/ && delete($commands{$1}) && return("ShowVersion");
- /#(show env all)$/ && delete($commands{$1}) && return("ShowEnv");
- /#(show gsr chassis)$/ && delete($commands{$1}) && return("ShowGSR");
- /#(show boot.*)$/ && delete($commands{$1}) && return("ShowBoot");
- /#(show flash)$/ && delete($commands{$1}) &&
- (ProcessHistory("FLASH","","","!\n"),return("ShowFlash"));
- /#(dir \/all bootflash\:)$/ && delete($commands{$1}) &&
- (ProcessHistory("FLASH","","","!\n"), return("DirBootflash"));
- /#(dir \/all slot0\:)$/ && delete($commands{$1}) &&
- (ProcessHistory("FLASH","","","!\n"),return("DirSlot0"));
- /#(dir \/all slot1\:)$/ && delete($commands{$1}) &&
- (ProcessHistory("FLASH","","","!\n"),return("DirSlot1"));
- # These three generate a list of the hw.
- # There are a few variable created in ShowContCbus
- # That are printed out in ShowDiagbus.
- /#(show controllers cbus)$/ && delete($commands{$1}) && return("ShowContCbus");
- /#(show controllers)$/ && delete($commands{$1}) && return("ShowContAll");
- /#(show diagbus)$/ && delete($commands{$1}) && return("ShowDiagbus");
- /#(show diag)$/ && delete($commands{$1}) && return("ShowDiags");
- /#(show c7200)$/ && delete($commands{$1}) && return("ShowC7200");
- /#(write term)$/ && delete($commands{$1}) && return("WriteTerm");
- return "FlailHelplessly";
-}
-
# Main
-@commands=("show version","show env all","show gsr chassis",
- "show boot","show bootvar","show flash","dir /all bootflash:",
- "dir /all slot0:", "dir /all slot1:","show controllers",
- "show controllers cbus", "show diagbus","show diag","show c7200",
- "write term");
-
-foreach $c (@commands) { $commands{$c} = 1; }
+%commands=(
+ 'show version' => "ShowVersion",
+ 'show env all' => "ShowEnv",
+ 'show gsr chassis' => "ShowGSR",
+ 'show boot' => "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' => "ShowDiags",
+ '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 env all",
+ "show gsr chassis",
+ "show boot",
+ "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",
+ "write term"
+);
$cisco_cmds=join(";",@commands);
$cmds_regexp=join("|",@commands);
-$func = FlailHelplessly;
open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
-# make OUTPUT unbuffered
-select(OUTPUT); $| = 1;
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
if ($file) {
print STDERR "opening file $host\n" if ($debug);
@@ -746,9 +857,12 @@ if ($file) {
} else {
print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
- open(INPUT,"clogin -t $timeo -c\"$cisco_cmds\" $host </dev/null |") ||
- die "clogin failed for $host: $!\n";
-# open(INPUT,"-|") || exec("clogin","-c\"$cisco_cmds\"",$host);
+ if (defined($ENV{NOPIPE})) {
+ system "clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
+ }
}
ProcessHistory("COMMENTS","keysort","B0","!\n");
@@ -760,22 +874,28 @@ while(<INPUT>) {
$clean_run=1;
last;
}
- if (/^Error:/) {
+ if (/Error:/) {
+ s/^.*Error:/Error:/;
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
$clean_run=0;
last;
}
- if (/#\s*($cmds_regexp)/) {
- $func = FlailHelplessly;
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
print STDERR ("HIT COMMAND:$_") if ($debug);
- } else {
- $rval=eval $func;
+ 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;
- }
- $func=$rval if ($rval);
+ }
}
}
print STDOUT "Done $logincmd: $_\n" if ($log);
@@ -785,16 +905,20 @@ ProcessHistory("","","","");
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)) {
- print STDOUT "missed cmd(s): $commands\n";
- print STDERR "missed cmd(s): $commands[0]\n" if ($debug);
+ 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 - removing $host.new\n";
- print STDERR "End of run not found - removing $host.new\n" if ($debug);
+ 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";
+ unlink "$host.new" if (! $debug);
}
diff --git a/bin/rancid-fe b/bin/rancid-fe
index e3dc94e..8dab8a5 100755
--- a/bin/rancid-fe
+++ b/bin/rancid-fe
@@ -21,12 +21,18 @@
# usage: rancid-fe <router>:<vendor>
#
+require 5;
+
($router, $vendor) = split('\:', $ARGV[0]);
if ($vendor =~ /^cisco$/i) {
exec('rancid', $router);
} elsif ($vendor =~ /^juniper$/i) {
exec('jrancid', $router);
+} elsif ($vendor =~ /^foundry$/i) {
+ exec('francid', $router);
+} elsif ($vendor =~ /^redback$/i) {
+ exec('rrancid', $router);
}
printf(STDERR "unknown router manufacturer for $router: $vendor\n");
diff --git a/bin/rrancid b/bin/rrancid
new file mode 100755
index 0000000..40113aa
--- /dev/null
+++ b/bin/rrancid
@@ -0,0 +1,347 @@
+#!/usr/local/bin/perl
+##
+## hacked version of Hank's rancid - this one tries to deal with redbacks.
+##
+## 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 "dir /<fsys>"
+sub DirFlash {
+ print STDERR " In DirFlash: $_" if ($debug);
+
+ my($dev) = (/\/(.*)$/);
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ /^\s*$/ && next;
+
+ /(Can\'t open|No such device)/ && return;
+ ProcessHistory("FLASH","keysort",$dev,"!Flash: $dev: $_");
+ }
+ ProcessHistory("FLASH","keysort",$dev,"!\n");
+ return;
+}
+
+# This routine parses "show hardware"
+sub ShowHardware {
+ print STDERR " In ShowHardware: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+ s/\s*$/\n/;
+
+ #ProcessHistory("","","","!Chassis: $_") && next;
+ ProcessHistory("COMMENTS","keysort","B1","!Chassis: $_");
+ }
+ ProcessHistory("COMMENTS","keysort","B1","!\n");
+ return;
+}
+
+# This routine parses "show version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /(uptime|restarted|^\s*$)/ && next;
+ ProcessHistory("COMMENTS","keysort","A1","!Image: $_");
+ }
+ return;
+}
+
+# This routine parses "show slot table"
+sub ShowSlotTable {
+ print STDERR " In ShowSlotTable: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+ /(Slot Table|^$)/ && next;
+ s/^\s*//;
+ ProcessHistory("COMMENTS","keysort","D1","!Slot Table: $_");
+ }
+ ProcessHistory("COMMENTS","keysort","D1","!\n");
+ return;
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+
+# /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
+ # Dog gone Cool matches to process the rest of the config
+ /^! last updated: .*$/ && next; # kill last updated line
+ /^ length / && next; # kill length on serial lines
+ /^ width / && next; # kill width on serial lines
+ # filter out any RCS/CVS tags to avoid confusing local CVS storage
+ s/\$(Revision|Id):/ $1:/;
+ # order access-lists
+ /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
+ ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next;
+ ProcessHistory("","","","$_");
+ # end of config
+ if (/^end$/) {
+ $found_end = 1;
+ last;
+ }
+ }
+ return;
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main subroutine that splits up the work
+# All Subs return the name of the next function to use.
+# If the sub returns a new funtion name, that name will be used
+# else the main loop keeps using the current function
+sub FlailHelplessly {
+ print STDERR "Flailing: $_" if ($debug);
+ print STDOUT "Flailing: $_" if ($log);
+ /#(show hardware)$/ && delete($commands{$1}) && return("ShowHardware");
+ /#(show version)$/ && delete($commands{$1}) && return("ShowVersion");
+ /#(show slot table)$/ && delete($commands{$1}) && return("ShowSlotTable");
+ /#(show config)$/ && delete($commands{$1}) && return("WriteTerm");
+ return "FlailHelplessly";
+}
+
+# Main
+%commands=(
+ 'show version' => "ShowVersion",
+ "dir /flash" => "DirFlash",
+ "dir /pcmcia0" => "DirFlash",
+ "dir /pcmcia1" => "DirFlash",
+ 'show hardware' => "ShowHardware",
+ 'show slot table' => "ShowSlotTable",
+ 'show config' => "WriteTerm"
+);
+@commands=(
+ "show version",
+ "dir /flash",
+ "dir /pcmcia0",
+ "dir /pcmcia1",
+ "show hardware",
+ "show slot table",
+ "show config"
+);
+# dir /flash
+# dir /pcmcia0
+# dir /pcmcia1
+
+$redback_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 ($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 clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+
+ if (defined($ENV{NOPIPE})) {
+ system "clogin -t $timeo -c \"$redback_cmds\" $host </dev/null > $host.raw" || die "clogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"clogin -t $timeo -c \"$redback_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
+ }
+}
+
+ProcessHistory("COMMENTS","keysort","B0","!\n");
+ProcessHistory("COMMENTS","keysort","C0","!\n");
+ProcessHistory("COMMENTS","keysort","E0","!\n");
+while(<INPUT>) {
+ tr/\015//d;
+ if (/\#exit$/) {
+ $clean_run=1;
+ last;
+ }
+ if (/^Error:/) {
+ print STDOUT ("$host clogin error: $_");
+ print STDERR ("$host clogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/#\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {
+ $prompt = ($_ =~ /^([^#]*#)/)[0];
+ $prompt =~ s/([][])/\\$1/g; # quote the damn []'s
+ }
+ 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/run-me b/bin/run-me
deleted file mode 100755
index b17d850..0000000
--- a/bin/run-me
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-ENVFILE="`dirname $0`/env"
-
-. $ENVFILE
-
-if [ $# -lt 1 ]; then
- DOME="$LIST_OF_GROUPS"
-else
- DOME="$*"
-fi
-
-for GROUP in $DOME
-do
-
- LOCKFILE=/tmp/.$GROUP.run.lock
-
- (
- echo starting: `date`
- echo
-
- if [ -f $LOCKFILE ]
- then
- echo hourly cisco diffs failed: $LOCKFILE exists
- /bin/ls -l $LOCKFILE
- else
- /usr/bin/touch $LOCKFILE
- control_rancid $GROUP
- /bin/rm -f $LOCKFILE
- fi
-
- echo
- echo ending: `date`
- ) >$BASEDIR/logs/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1
-done
diff --git a/cloginrc.sample b/cloginrc.sample
index 71cd704..6b8f133 100644
--- a/cloginrc.sample
+++ b/cloginrc.sample
@@ -1,8 +1,34 @@
# comments are cool, as is whitespace
-# currently clogin supports three add directives; password, user, and
-# autoenable.
-# eventually, others may be added to allow other features.
-##
+# currently clogin supports a number of add directives:
+# password
+# user
+# userpassword
+# enauser
+# autoenable
+# cyphertype
+#
+# Details on each of these follows.
+#
+# add password <router name regexp> <vty passwd> <enable passwd>
+#
+# add user <router name regexp> <username>
+# The default user is $USER (i.e.: the user running clogin).
+#
+# add userpassword <router name regexp> <user password>
+# The password for user if different than the password set
+# using 'add password'.
+#
+# add enauser <router name regexp> <username>
+# This is only needed if enable asks for a username and this
+# username is different from what user is set to.
+#
+# add autoenable <router name regexp> <1/0>
+# This is used if you are automatically enabled by the login process.
+#
+# add cyphertype <router name regexp> <ssh encryption type>
+# Default is 3des.
+#
+
#add password sl-bb*-dc cow24
#add password sl-gw*-dc geeks
#add password sl* hank dog
@@ -33,3 +59,6 @@ add password *.custz.net {jive} {surely}
# all our routers, ie: everything else
add password * {clearance} {clarence}
+
+# set ssh encryption type, dflt: 3des
+add cyphertype * {3des}