summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTar Committer <tar@ocjtech.us>2001-08-10 18:35:12 +0000
committerTar Committer <tar@ocjtech.us>2001-08-10 18:35:12 +0000
commitd19de03be4d4ad086ab9446e4196afdd6891fb79 (patch)
tree0c0ea9ff28ccfb48d0b7bc58ff8b379cd2c56a2a
parentaf496d2efa0969f29a22a4236c620f513eb90287 (diff)
downloadrancid-d19de03be4d4ad086ab9446e4196afdd6891fb79.tar.gz
rancid-d19de03be4d4ad086ab9446e4196afdd6891fb79.tar.xz
rancid-d19de03be4d4ad086ab9446e4196afdd6891fb79.zip
Imported from rancid-2.2b6.tar.gz.rancid-2.2b6
-rw-r--r--CHANGES3
-rw-r--r--README6
-rw-r--r--Todo5
-rwxr-xr-xbin/blogin.in585
-rwxr-xr-xbin/brancid.in264
-rwxr-xr-xbin/rancid-fe.in4
-rwxr-xr-xconfigure4
-rw-r--r--configure.in4
-rw-r--r--man/Makefile.am4
-rw-r--r--man/Makefile.in2
-rw-r--r--man/blogin.11
-rw-r--r--man/clogin.14
-rw-r--r--man/rancid.14
-rw-r--r--man/rancid_intro.15
-rw-r--r--man/router.db.53
15 files changed, 884 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 0c577ae..2d3ae2f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+2.2b6
+ baynetworks/nortel support from Mark Cooper. thanks mark!
+
2.2b5
fix regex error in clogin affecting catalysts
diff --git a/README b/README
index e95d60a..b05a335 100644
--- a/README
+++ b/README
@@ -18,6 +18,7 @@ erancid.in Runs commands on ADC EZ-T3 muxes and processes the output.
francid.in Runs commands on foundry switches and processes the output.
jrancid.in Runs commands on juniper routers and processes the output.
rrancid.in Runs commands on redback routers and processes the output.
+xancid.in Runs commands on extreme switches and processes the output.
cat5rancid.in Runs commands on cisco cat5 switches and processes the output.
clogin.in Expect script that logs into routers either interactively,
runs a set of commands, or runs another expect script.
@@ -123,8 +124,8 @@ Quick Installation Guide (an example):
8) 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|ezt3|foundry|juniper|redback|cat5), and "state"
- is either up or down. Each router listed as "up" will have the
+ from the set of (cisco|ezt3|extreme|foundry|juniper|redback|cat5), and
+ "state" is either up or down. Each router listed as "up" will have the
configuration grabbed. Note: manufacturer cat5 is intended only for
catalyst switches running catalyst (not IOS) code.
@@ -134,6 +135,7 @@ Quick Installation Guide (an example):
foundry-switch-router.domain.com:foundry:up
juniper-router.domain.com:juniper:up
redback-dsl-router.domain.com:redback:down
+ extreme-switch.domain.com:extreme:down
9) For first-time users or new installations, run bin/do-diffs (with no
arguments) and check the resulting log file(s) (in logs/*) for errors.
diff --git a/Todo b/Todo
index 0e09c91..e10c311 100644
--- a/Todo
+++ b/Todo
@@ -1,3 +1,8 @@
+- extreme (xrancid)
+ - collect show switch
+ - filter ssh host private key
+ - ??? separate module p/n and s/n or collect from sh ver instead of
+ show slot?
- rancid should filter pap pwds, as in:
ppp pap sent-username AS3727 password 7 10581C17581043
- need to make sure the following patch was applied to the lookingglass
diff --git a/bin/blogin.in b/bin/blogin.in
new file mode 100755
index 0000000..0c353d0
--- /dev/null
+++ b/bin/blogin.in
@@ -0,0 +1,585 @@
+#!@EXPECT_PATH@ --
+##
+##
+## 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.
+##
+##
+#
+# blogin - Bay Networks(Nortel) login
+#
+# Unlike the Cisco's, there is no enable function on the Bay's.
+# Instead there are seperate User and Manager accounts.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \
+\[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
+\[-s script-file\] \[-t timeout\] \[-u username\] \
+\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
+\[-y ssh_cypher_type\] router \[router...\]\n"
+
+# env(CLOGIN) may contain:
+# x == do not set xterm banner or name
+
+# Password file
+set password_file $env(HOME)/.cloginrc
+# Default is to login to the router
+set do_command 0
+set do_script 0
+# The default is to automatically enable
+set enable 0
+# 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 0
+
+# Find the user in the ENV, or use the unix userid.
+if {[ info exists env(CISCO_USER) ] } {
+ set default_user $env(CISCO_USER)
+} elseif {[ info exists env(USER) ]} {
+ set default_user $env(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.
+ if [ catch {exec id} reason ] {
+ send_error "\nError: could not exec id: $reason\n"
+ exit 1
+ }
+ regexp {\(([^)]*)} "$reason" 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 ]
+ }
+ # Environment variable to pass to -s scripts
+ } -E*
+ {
+ if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
+ set E$varname $varvalue
+ } else {
+ send_user "Error: invalid format for -E in $arg\n"
+ exit 1
+ }
+ # Enable Password
+ } -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 "\nError: Can't read $sfile\n"
+ exit 1
+ }
+ set do_script 1
+ # 'ssh -c' cypher type
+ } -y* -
+ -Y* {
+ if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ incr i
+ set cypher [ lindex $argv $i ]
+ }
+ # alternate cloginrc file
+ } -f* -
+ -F* {
+ if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr i
+ set password_file [ lindex $argv $i ]
+ }
+ # Timeout
+ } -t* -
+ -T* {
+ if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
+ incr i
+ set timeout [ lindex $argv $i ]
+ }
+ # Command file
+ } -x* -
+ -X {
+ if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ incr i
+ set cmd_file [ lindex $argv $i ]
+ }
+ set cmd_fd [open $cmd_file r]
+ set cmd_text [read $cmd_fd]
+ close $cmd_fd
+ set command [join [split $cmd_text \n] \;]
+ set do_command 1
+ # Do we enable?
+ } -noenable {
+ set enable 0
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ set autoenable 1
+ set enable 0
+ } -* {
+ send_user "\nError: Unknown argument! $arg\n"
+ send_user $usage
+ exit 1
+ } default {
+ break
+ }
+ }
+}
+# Process routers...no routers listed is an error.
+if { $i == $argc } {
+ send_user "\nError: $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 int_$var ; lappend int_$var $args}
+proc include {args} {
+ global env
+ regsub -all "(^{|}$)" $args {} args
+ if { [ regexp "^/" $args ignore ] == 0 } {
+ set args $env(HOME)/$args
+ }
+ source_password_file $args
+}
+
+proc find {var router} {
+ upvar int_$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 { password_file } {
+ global env
+ if { ! [file exists $password_file] } {
+ send_user "\nError: password file ($password_file) does not exist\n"
+ exit 1
+ }
+ file stat $password_file fileinfo
+ if { [expr ($fileinfo(mode) & 007)] != 0000 } {
+ send_user "\nError: $password_file must not be world readable/writable\n"
+ exit 1
+ }
+ if [ catch {source $password_file} reason ] {
+ send_user "\nError: $reason\n"
+ exit 1
+ }
+}
+
+# Log into the router.
+proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } {
+ global spawn_id in_proc do_command do_script
+ global u_prompt p_prompt e_prompt
+ set in_proc 1
+
+ # try each of the connection methods in $cmethod until one is successful
+ set progs [llength $cmethod]
+ foreach prog [lrange $cmethod 0 end] {
+ if ![string compare $prog "telnet"] {
+ if [ catch {spawn telnet $router} reason ] {
+ send_user "\nError: telnet failed: $reason\n"
+ exit 1
+ }
+ } elseif ![string compare $prog "ssh"] {
+ if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] {
+ send_user "\nError: ssh failed: $reason\n"
+ exit 1
+ }
+ } elseif ![string compare $prog "rsh"] {
+ if [ catch {spawn rsh -l $user $router} reason ] {
+ send_user "\nError: rsh failed: $reason\n"
+ exit 1
+ }
+ } else {
+ puts "\nError: unknown connection method: $prog"
+ return 1
+ }
+ incr progs -1
+ sleep 0.3
+
+ # This helps cleanup each expect clause.
+ expect_after {
+ timeout {
+ send_user "\nError: TIMEOUT reached\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ } eof {
+ send_user "\nError: EOF received\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ }
+ }
+
+ # 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 {
+ -re "(Connection refused|Secure connection \[^\n\r]+ refused|Connection closed by)" {
+ catch {close}; wait
+ if !$progs {
+ send_user "\nError: Connection Refused ($prog)\n"; return 1
+ }
+ } eof { send_user "\nError: Couldn't login\n"; wait; return 1
+ } -nocase "unknown host\r" {
+ catch {close};
+ send_user "\nError: Unknown host\n"; wait; return 1
+ } "Host is unreachable" {
+ catch {close};
+ send_user "\nError: Host Unreachable!\n"; wait; return 1
+ } "No address associated with name" {
+ catch {close};
+ send_user "\nError: Unknown host\n"; wait; return 1
+ }
+ -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
+ send "yes\r"
+ send_user "\nHost $router added to the list of known hosts.\n"
+ exp_continue }
+ -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
+ send "no\r"
+ send_user "\nError: The host key for $router has changed. update the known_hosts file accordingly.\n"
+ return 1 }
+ -re "$u_prompt" { send "$user\r"
+ expect {
+ eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
+ "Login invalid" { send_user "\nError: Invalid login\n"; vatch {close}; wait; return 1 }
+ -re "$p_prompt" { send "$userpswd\r" }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ -re "$p_prompt" {
+ if ![string compare $prog "ssh"] {
+ send "$userpswd\r"
+ } else {
+ send "$passwd\r"
+ }
+ expect {
+ eof { send_user "\nError: Couldn't login\n"; wait; return 1 }
+ -re "$e_prompt" { send "$enapasswd\r" }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ "$prompt" { break; }
+ denied { send_user "\nError: Check your passwd for $router\n"
+ if { $do_command || $do_script } {
+ send "logout\r"
+ wait
+ return 1
+ } else {
+ return 1
+ }
+ }
+ "% Bad passwords" {send_user "\nError: Check your passwd for $router\n"; return 1 }
+ }
+}
+ set in_proc 0
+ return 0
+}
+
+# Enable
+proc do_enable { enauser enapasswd } {
+ global prompt in_proc
+ global u_prompt e_prompt
+ set in_proc 1
+
+ send "enable\r"
+ expect {
+ -re "$u_prompt" { send "$enauser\r"; exp_continue}
+ -re "$e_prompt" { send "$enapasswd\r"; exp_continue}
+ "#" { set prompt "#" }
+ "(enable)" { set prompt "> (enable) " }
+ denied { send_user "\nError: Check your Enable passwd\n"; return 1}
+ "% Bad passwords" { send_user "\nError: Check your Enable passwd\n"
+ return 1
+ }
+ }
+ # We set the prompt variable (above) so script files don't need
+ # to know what it is.
+ 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 "more off\r"
+
+ expect $prompt {}
+
+ regsub -all "\[)(]" $prompt {\\&} reprompt
+
+ # Is this a multi-command?
+ if [ string match "*\;*" "$command" ] {
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "^\[^\n\r *]*$reprompt" {}
+ -re "^\[^\n\r]*$reprompt." { exp_continue }
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ } else {
+ send "[subst -nocommands $command]\r"
+ expect {
+ -re "^\[^\n\r *]*$reprompt" {}
+ -re "^\[^\n\r]*$reprompt." { exp_continue }
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ send "logout\r"
+ expect {
+ "\n" { exp_continue }
+ timeout { return 0 }
+ eof { return 0 }
+ }
+ set in_proc 0
+}
+
+#
+# For each router... (this is main loop)
+#
+source_password_file $password_file
+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 ">"
+ }
+ }
+
+ # look for noenable option in .cloginrc
+ if { [find noenable $router] != "" } {
+ set enable 0
+ }
+
+ # 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 prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } { set u_prompt "(Username|login|user name):" }
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } { set p_prompt "(\[Pp]assword|passwd):" }
+ set e_prompt [find enableprompt $router]
+ if { "$e_prompt" == "" } { set e_prompt "\[Pp]assword:" }
+
+ # Figure out cypher type
+ if {[info exists cypher]} {
+ # command line cypher type
+ set cyphertype $cypher
+ } else {
+ set cyphertype [find cyphertype $router]
+ if { "$cyphertype" == "" } { set cyphertype "3des" }
+ }
+
+ # Figure out connection method
+ set cmethod [find method $router]
+ if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }
+
+ # Login to the router
+ if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cmethod $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 } {
+ send "more off\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/brancid.in b/bin/brancid.in
new file mode 100755
index 0000000..5614ccc
--- /dev/null
+++ b/bin/brancid.in
@@ -0,0 +1,264 @@
+#!@PERLV_PATH@
+##
+## hacked version of Hank's rancid - this one tries to deal with Bay's.
+##
+## 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; # blogin 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 config"
+sub ShowConfig {
+ print STDERR " In ShowConfig: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ next if (/^Reading configuration information/);
+ return(1) if /(Invalid input detected|Type help or )/;
+ return(-1) if (/command authorization failed/i);
+ ProcessHistory("","","","$_");
+ }
+ # ProcessHistory("","","","!$_");
+ if (/exit$/) {
+ $found_end = 1;
+ return(1);
+ }
+ return(0);
+}
+
+# This routine parses single command's that return no required info
+sub RunCommand {
+ print STDERR " In RunCommand: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ # prompt may have changed
+ if (/\>/) {
+ $prompt = ($_ =~ /^([^>]+>)/)[0];
+ last;
+ }
+ }
+ return(0)
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'bcc' => "RunCommand",
+ 'show config' => "ShowConfig",
+ 'exit' => "RunCommand"
+);
+# 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=(
+ "bcc",
+ "show config",
+ "exit"
+);
+$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 blogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing blogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "blogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "blogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "blogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"blogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "blogin failed for $host: $!\n";
+ }
+}
+
+ProcessHistory("","","","!RANCID-CONTENT-TYPE: Bay Networks\n!\n");
+TOP: while(<INPUT>) {
+ tr/\015//d;
+ if ( (/\>\s?logout$/) || $found_end ) {
+ $clean_run=1;
+ last;
+ }
+ if (/^Error:/) {
+ print STDOUT ("$host blogin error: $_");
+ print STDERR ("$host blogin 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 TOP;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ last TOP;
+ }
+ }
+}
+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/rancid-fe.in b/bin/rancid-fe.in
index b452f0f..a00915f 100755
--- a/bin/rancid-fe.in
+++ b/bin/rancid-fe.in
@@ -25,7 +25,9 @@ require 5;
($router, $vendor) = split('\:', $ARGV[0]);
-if ($vendor =~ /^cisco$/i) {
+if ($vendor =~ /^baynet$/i) {
+ exec('brancid', $router);
+} elsif ($vendor =~ /^cisco$/i) {
exec('rancid', $router);
} elsif ($vendor =~ /^cat5$/i) {
exec('cat5rancid', $router);
diff --git a/configure b/configure
index 90666b9..7ca73af 100755
--- a/configure
+++ b/configure
@@ -792,7 +792,7 @@ PACKAGE=rancid
# VERSION needs to be updated such that 'make dist' uses the correct
# filename for the directory name and tarball.
-VERSION=2.2b5
+VERSION=2.2b6
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
echo "configure:799: checking whether to enable maintainer-specific portions of Makefiles" >&5
@@ -1419,7 +1419,7 @@ rd_cv_rd_bin_datas=$RD_BIN_DATAS
# RD_BIN_PROGS are bin/ .in's that need to be installed with execute perms.
RD_BIN_PROGS="cat5rancid control_rancid \
-alogin arancid clogin create_cvs do-diffs elogin erancid \
+alogin arancid clogin create_cvs blogin brancid do-diffs elogin erancid \
flogin francid jlogin jrancid par rancid-fe \
rancid rename rrancid xrancid"
diff --git a/configure.in b/configure.in
index c15d907..8fa0c3c 100644
--- a/configure.in
+++ b/configure.in
@@ -14,7 +14,7 @@ PACKAGE=rancid
# VERSION needs to be updated such that 'make dist' uses the correct
# filename for the directory name and tarball.
AC_SUBST(VERSION)
-VERSION=2.2b5
+VERSION=2.2b6
AM_MAINTAINER_MODE()
@@ -145,7 +145,7 @@ rd_cv_rd_bin_datas=$RD_BIN_DATAS
# RD_BIN_PROGS are bin/ .in's that need to be installed with execute perms.
RD_BIN_PROGS="cat5rancid control_rancid \
-alogin arancid clogin create_cvs do-diffs elogin erancid \
+alogin arancid clogin create_cvs blogin brancid do-diffs elogin erancid \
flogin francid jlogin jrancid par rancid-fe \
rancid rename rrancid xrancid"
AC_SUBST(RD_BIN_PROGS)
diff --git a/man/Makefile.am b/man/Makefile.am
index 354b290..845cba6 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -6,8 +6,8 @@ AUTOMAKE_OPTIONS=foreign no-dependencies
@SET_MAKE@
man_gen_MANS = env.5 lg.conf.5 lg_intro.1
-man_nogen_MANS = do-diffs.1 alogin.1 clogin.1 control_rancid.1 create_cvs.1 \
- rancid.1 \
+man_nogen_MANS = do-diffs.1 alogin.1 blogin.1 clogin.1 control_rancid.1 \
+ create_cvs.1 rancid.1 \
rancid_intro.1 cloginrc.5 router.db.5 \
elogin.1 flogin.1 jlogin.1 \
jrancid.1 francid.1 cat5rancid.1 erancid.1 xrancid.1
diff --git a/man/Makefile.in b/man/Makefile.in
index a18c361..598e4f7 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -95,7 +95,7 @@ VERSION = @VERSION@
AUTOMAKE_OPTIONS = foreign no-dependencies
man_gen_MANS = env.5 lg.conf.5 lg_intro.1
-man_nogen_MANS = do-diffs.1 alogin.1 clogin.1 control_rancid.1 create_cvs.1 rancid.1 rancid_intro.1 cloginrc.5 router.db.5 elogin.1 flogin.1 jlogin.1 jrancid.1 francid.1 cat5rancid.1 erancid.1 xrancid.1
+man_nogen_MANS = do-diffs.1 alogin.1 blogin.1 clogin.1 control_rancid.1 create_cvs.1 rancid.1 rancid_intro.1 cloginrc.5 router.db.5 elogin.1 flogin.1 jlogin.1 jrancid.1 francid.1 cat5rancid.1 erancid.1 xrancid.1
man_MANS = $(man_gen_MANS) $(man_nogen_MANS)
diff --git a/man/blogin.1 b/man/blogin.1
new file mode 100644
index 0000000..4c83247
--- /dev/null
+++ b/man/blogin.1
@@ -0,0 +1 @@
+.so man1/clogin.1
diff --git a/man/clogin.1 b/man/clogin.1
index cbc6a65..d257a5f 100644
--- a/man/clogin.1
+++ b/man/clogin.1
@@ -51,8 +51,10 @@ is an
.BR expect (1)
script to automate the process of logging into a Cisco router, catalyst
switch, Extreme switch, or Redback router. There are complementary scripts
-for Alteon, Juniper, Foundry, and ADC-kentrox EZ-T3 mux named
+for Alteon, Bay Networks (nortel), Juniper, Foundry, and ADC-kentrox EZ-T3 mux
+named
.B alogin,
+.B blogin,
.B jlogin,
.B flogin,
and
diff --git a/man/rancid.1 b/man/rancid.1
index b74e412..bcccd26 100644
--- a/man/rancid.1
+++ b/man/rancid.1
@@ -24,8 +24,10 @@ product is a file with the name of it's last argument plus the suffix .new.
For example, hostname.new.
.PP
There are complementary scripts for Alteon WebOS switches, Cisco catalyst
-switch, Juniper, Foundry, Extreme, and ADC-kentrox EZ-T3 mux named
+switch, Bay Networks (nortel), Juniper, Foundry, Extreme, and ADC-kentrox EZ-T3
+mux named
.B arancid,
+.B brancid,
.B cat5rancid,
.B jrancid,
.B francid,
diff --git a/man/rancid_intro.1 b/man/rancid_intro.1
index 82837e9..e238637 100644
--- a/man/rancid_intro.1
+++ b/man/rancid_intro.1
@@ -6,8 +6,9 @@ rancid_intro \- introduction to the Really Awesome New Cisco confIg Differ
.SH INTRODUCTION
.B rancid
is really more than just a Cisco configuration differ. It handles several
-different device's configurations; currently including Alteon, Cisco, Extreme,
-Foundry, Juniper, Redback, and the ADC-Kentrox EZ-T3 mux.
+different device's configurations; currently including Alteon, Bay Networks
+(nortel), Cisco, Extreme, Foundry, Juniper, Redback, and the ADC-Kentrox
+EZ-T3 mux.
.PP
.B rancid
uses an expect script to login to a list of devices and run a set of
diff --git a/man/router.db.5 b/man/router.db.5
index 4b25b70..2139d99 100644
--- a/man/router.db.5
+++ b/man/router.db.5
@@ -51,6 +51,9 @@ The type of device from the set:
.B alteon
An Alteon WebOS switches.
.TP
+.B baynet
+A Bay Networks router.
+.TP
.B cat5
A cisco catalyst switch (ie: running the catalyst OS, not IOS).
.TP