[rancid] Re: Alcatel Omniswitch and Rancid
Alexander Bochmann
ab at lists.gxis.de
Sat Jul 19 09:14:33 UTC 2008
Hi,
...on Fri, Jul 18, 2008 at 07:55:30PM -0700, David Newman wrote:
> Per your posting:
> http://www.shrubbery.net/pipermail/rancid-discuss/2008-June/003148.html
> Yes, I'm very interesting in taking a look. Have you posted your changes
> anywhere?
No yet, but I already promised someone else to finally
send the files out yesterday, so here we go.
The files are ologin and orancid, based on the rancid 2.3.2a7
versions. There's lots of unused code in them, as I didn't
get very far beyond tweaking my changes in. A new vendor "alcatel"
is defined in rancid-fe. It's what you use in your router.db
Things that work:
Logs into an Omniswitch via ssh (I think telnet works too, but
I can't actually remember right now - I'll check on monday) and
runs the following commands:
show configuration status
show chassis
show module
show microcode
show configuration snapshot all
Output is minimally parsed, not shure if the ProcessHistory()
parameters are used in the way they were intended.
Things that should be fixed in some way:
Currently, the prompt needs to end in the characters "->"
(which is the default I think, otherwise use session config prompt).
I had a strange problem with some older AOS versions where
rancid couldn't find the prompt, a leftover from debugging
that is that you will get a line (commented out) with the
exit command at the end of your config if your system runs
a more recent software release.
I'm not shure if I did something to the autoenable code,
so set add autoenable 1 for your alcatel systems in cloginrc
to be shure.
Need to throw out all the unused code or try to merge with the
main rancid scripts.
I hope it's of any use to you, otherwise just ask back
and I'll try help getting it to work.
Alex.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: rancid-fe.diff
Type: text/x-diff
Size: 488 bytes
Desc: not available
Url : http://www.shrubbery.net/pipermail/rancid-discuss/attachments/20080719/a2d18141/attachment.bin
-------------- next part --------------
#! /usr/bin/expect --
##
## $Id: clogin.in,v 1.107 2006/12/08 21:28:25 heas Exp $
##
## rancid 2.3.2a7
## Copyright (C) 1997-2006 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
## without fee for non-commerical purposes provided that this license
## remains intact and unmodified with any RANCID distribution.
##
## 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.
##
## Except where noted otherwise, rancid was written by and is maintained by
## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
#
# The login expect scripts were based on Erik Sherk's gwtn, by permission.
#
# ologin - OmniSwitch login hacks by Alexander Bochmann <ab+rancid at st.gxis.de>
#
# Most options are intuitive for logging into a Cisco router.
# 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 \[-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 avenable 0
# The default is that you login non-enabled (tacacs can have you login already
# enabled)
set avautoenable 1
# 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
#
set send_human {.4 .4 .7 .3 5}
# 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)
} elseif {[ info exists env(LOGNAME) ]} {
set default_user $env(LOGNAME)
} 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
}
if {[ info exists env(CLOGINRC) ]} {
set password_file $env(CLOGINRC)
}
# 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* {
if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
incr i
set passwd [ lindex $argv $i ]
}
set do_passwd 0
# Version string
} -V* {
send_user "rancid 2.3.2a7\n"
exit 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 "\nError: invalid format for -E in $arg\n"
exit 1
}
# Enable Password
} -e*
{
if {! [ regexp .\[e\](.+) $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 ]
}
if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
send_user "\nError: $reason\n"
exit 1
}
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 avenable 0
# Does tacacs automatically enable us?
} -autoenable {
set avautoenable 1
set avenable 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.
# returns: 0 on success, 1 on failure, -1 if rsh was used successfully
proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
global spawn_id in_proc do_command do_script platform
global prompt u_prompt p_prompt e_prompt sshcmd
set in_proc 1
set uprompt_seen 0
# try each of the connection methods in $cmethod until one is successful
set progs [llength $cmethod]
foreach prog [lrange $cmethod 0 end] {
incr progs -1
if [string match "telnet*" $prog] {
regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
if {"$port" == ""} {
set retval [ catch {spawn telnet $router} reason ]
} else {
set retval [ catch {spawn telnet $router $port} reason ]
}
if { $retval } {
send_user "\nError: telnet failed: $reason\n"
return 1
}
} elseif [string match "ssh*" $prog] {
regexp {ssh(:([^[:space:]]+))*} $prog command suffix port
if {"$port" == ""} {
set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ]
} else {
set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason ]
}
if { $retval } {
send_user "\nError: $sshcmd failed: $reason\n"
return 1
}
} elseif ![string compare $prog "rsh"] {
global command
if { ! $do_command } {
if { [llength $cmethod] == 1 } {
send_user "\nError: rsh is an invalid method for -x and "
send_user "interactive logins\n"
}
if { $progs == 0 } {
return 1
}
continue;
}
set commands [split $command \;]
set num_commands [llength $commands]
set rshfail 0
for {set i 0} {$i < $num_commands && !$rshfail} { incr i} {
log_user 0
set retval [ catch {spawn rsh $user@$router [lindex $commands $i] } reason ]
if { $retval } {
send_user "\nError: rsh failed: $reason\n"
log_user 1; return 1
}
send_user "$router# [lindex $commands $i]\n"
# rcmd does not get a pager and no prompts, so we just have to
# look for failures & lines.
expect {
"Connection refused" { catch {close}; wait;
send_user "\nError: Connection\
Refused ($prog): $router\n"
set rshfail 1
}
-re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
catch {close}; wait;
send_user "\nError: Connection\
closed ($prog): $router\n"
set rshfail 1
}
"Host is unreachable" { catch {close}; wait;
send_user "\nError: Host Unreachable:\
$router\n"
set rshfail 1
}
"No address associated with" {
catch {close}; wait;
send_user "\nError: Unknown host\
$router\n"
set rshfail 1
}
-re "\b+" { exp_continue }
-re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
exp_continue
}
timeout { catch {close}; wait
send_user "\nError: TIMEOUT reached\n"
set rshfail 1
}
eof { catch {close}; wait }
}
log_user 1
}
if { $rshfail } {
if { !$progs } {
return 1
} else {
continue
}
}
# fake the end of the session for rancid.
send_user "$router# exit\n"
# return rsh "success"
return -1
} else {
send_user "\nError: unknown connection method: $prog\n"
return 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)" {
catch {close}; wait
if !$progs {
send_user "\nError: Connection Refused ($prog): $router\n"
return 1
}
}
-re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
catch {close}; wait
if !$progs {
send_user "\nError: Connection closed ($prog): $router\n"
return 1
}
}
eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
-nocase "unknown host\r" {
catch {close};
send_user "\nError: Unknown host $router\n"; wait; return 1
}
"Host is unreachable" {
catch {close};
send_user "\nError: Host Unreachable: $router\n"; wait; return 1
}
"No address associated with name" {
catch {close};
send_user "\nError: Unknown host $router\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 SSH known_hosts file accordingly.\n"
return 1 }
-re "Offending key for .* \(yes\/no\)\?" {
send "no\r"
send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
return 1 }
-re "(denied|Sorry)" {
send_user "\nError: Check your passwd for $router\n"
catch {close}; wait; return 1
}
"Login failed" {
send_user "\nError: Check your passwd for $router\n"
return 1
}
-re "% (Bad passwords|Authentication failed)" {
send_user "\nError: Check your passwd for $router\n"
return 1
}
"Press any key to continue." {
# send_user "Pressing the ANY key\n"
send "\r"
exp_continue
}
-re "Enter Selection: " {
# Catalyst 1900s have some lame menu. Enter
# K to reach a command-line.
send "K\r"
exp_continue
}
-re "Last login:" {
exp_continue
}
-re "@\[^\r\n]+ $p_prompt" {
# ssh pwd prompt
sleep 1
send "$userpswd\r"
exp_continue
}
-re "$u_prompt" {
send "$user\r"
set uprompt_seen 1
exp_continue
}
-re "$p_prompt" {
sleep 1
if {$uprompt_seen == 1} {
send "$userpswd\r"
} else {
send "$passwd\r"
}
exp_continue
}
-re "$prompt" { break; }
"Login invalid" {
send_user "\nError: Invalid login: $router\n";
catch {close}; wait; 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) " }
-re "(denied|Sorry|Incorrect)" {
# % Access denied - from local auth and poss. others
send_user "\nError: Check your Enable passwd\n";
return 1
}
"% Error in authentication" {
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 platform
set in_proc 1
# If the prompt is (enable), then we are on a switch and the
# command is "set length 0"; otherwise its "term length 0".
# skip if its an extreme (since the pager can not be disabled on a
# per-vty basis).
if { [ string compare "extreme" "$platform" ] } {
if [ regexp -- ".*> .*enable" "$prompt" ] {
# send "set length 0\r"
# This is ugly, but reduces code duplication, allowing the
# subsequent expects to handle everything as normal.
set command "set logging session disable;$command"
} else {
# send "term length 0\r"
send "no more\r"
}
# escape any parens in the prompt, such as "(enable)"
regsub -all {[)(]} $prompt {\\&} reprompt
# match cisco config mode prompts too, such as router(config-if)#,
# but catalyst does not change in this fashion.
regsub -all {^(.{1,11}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
expect {
-re $reprompt {}
-re "\[\n\r]+" { exp_continue }
}
} else {
regsub -all "\[)(]" $prompt {\\&} reprompt
}
# this is the only way i see to get rid of more prompts in o/p..grrrrr
log_user 0
# Is this a multi-command?
if [ string match "*\;*" "$command" ] {
set commands [split $command \;]
set num_commands [llength $commands]
# the pager can not be turned off on the PIX, so we have to look
# for the "More" prompt. the extreme is equally obnoxious, with a
# global switch in the config.
for {set i 0} {$i < $num_commands} { incr i} {
send "[subst -nocommands [lindex $commands $i]]\r"
expect {
-re "\b+" { exp_continue }
-re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
}
-re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
exp_continue }
-re "^--More--\r\n" { # specific match c1900 pager
send " "
exp_continue }
-re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
exp_continue }
-re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
send " "
# bloody ^[[2K after " "
expect {
-re "^\[^\r\n]*\r" {}
}
exp_continue
}
-re "^ *--More--\[^\n\r]*" {
send " "
exp_continue }
-re "^<-+ More -+>\[^\n\r]*" {
send_user -- "$expect_out(buffer)"
send " "
exp_continue }
}
}
} else {
# the pager can not be turned off on the PIX, so we have to look
# for the "More" prompt. the extreme is equally obnoxious, with a
# global switch in the config.
send "[subst -nocommands $command]\r"
expect {
-re "\b+" { exp_continue }
-re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)"
}
-re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)"
exp_continue }
-re "^--More--\r\n" { # specific match c1900 pager
send " "
exp_continue }
-re "\[\n\r]+" { send_user -- "$expect_out(buffer)"
exp_continue }
-re "\[^\r\n]*Press <SPACE> to cont\[^\r\n]*" {
send " "
# bloody ^[[2K after " "
expect {
-re "^\[^\r\n]*\r" {}
}
exp_continue
}
-re "^ *--More--\[^\n\r]*" {
send " "
exp_continue }
-re "^<-+ More -+>\[^\n\r]*" {
send_user -- "$expect_out(buffer)"
send " "
exp_continue }
}
}
log_user 1
if { [ string compare "extreme" "$platform" ] } {
send -h "exit\r"
} else {
send -h "quit\r"
}
expect {
-re "^\[^\n\r *]*$reprompt" {
# the Cisco CE and Jnx ERX
# return to non-enabled mode
# on exit in enabled mode.
send -h "exit\r"
exp_continue;
}
"Would you like to save them now" { # Force10
send "n\r"
exp_continue
}
"Configuration changes have occurred.*" { # Cisco CSS
send "n\r"
exp_continue
}
"Do you wish to save your configuration changes" {
send "n\r"
exp_continue
}
-re "\[\n\r]+" { exp_continue }
timeout { catch {close}; wait
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]
# attempt at platform switching.
set platform ""
send_user -- "$router\n"
# Figure out the prompt.
# 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 $avautoenable {
set autoenable 1
set enable 0
set prompt "(#| \\(enable\\))"
} else {
set ae [find autoenable $router]
if { "$ae" == "1" } {
set autoenable 1
set enable 0
set prompt "(#| \\(enable\\))"
} else {
set autoenable 0
set enable $avenable
set prompt ">"
}
}
# OmniSwitch
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 -- "\nError: no password for $router in $password_file.\n"
continue
}
if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
send_user -- "\nError: no enable password for $router in $password_file.\n"
continue
}
set passwd [join [lindex $pswd 0] ""]
set enapasswd [join [lindex $pswd 1] ""]
} else {
set passwd $userpasswd
set enapasswd $enapasswd
}
# Figure out username
if {[info exists username]} {
# command line username
set ruser $username
} else {
set ruser [join [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 [join [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 [join [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|login|user name):"
} else {
set u_prompt [join [lindex $u_prompt 0] ""]
}
set p_prompt [find passprompt $router]
if { "$p_prompt" == "" } {
set p_prompt "(\[Pp]assword|passwd)\ for.*method:"
} else {
set p_prompt [join [lindex $p_prompt 0] ""]
}
set e_prompt [find enableprompt $router]
if { "$e_prompt" == "" } {
set e_prompt "\[Pp]assword:"
} else {
set e_prompt [join [lindex $e_prompt 0] ""]
}
# 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}} }
# Figure out the SSH executable name
set sshcmd [find sshcmd $router]
if { "$sshcmd" == "" } { set sshcmd {ssh} }
# Login to the router
if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
# if login failed or rsh was unsuccessful, move on to the next device
continue
}
if { $enable } {
if {[do_enable $enauser $enapasswd]} {
if { $do_command || $do_script } {
catch {close}; catch {wait}
continue
}
}
}
# we are logged in, now figure out the full prompt
send "\r"
expect {
-re "\[\r\n]+" { exp_continue; }
-re "^(.+\[:.])1 ($prompt)" { # stoopid extreme cmd-line numbers and
# prompt based on state of config changes,
# which may have an * at the beginning.
set junk $expect_out(1,string)
regsub -all "^\\\* " $expect_out(1,string) {} junk
set prompt ".? ?$junk\[0-9]+ $expect_out(2,string)";
set platform "extreme"
}
-re "^.+$prompt" { set junk $expect_out(0,string);
regsub -all "\[\]\[]" $junk {\\&} prompt;
}
-re "^.+> \\\(enable\\\)" {
set junk $expect_out(0,string);
regsub -all "\[\]\[]" $junk {\\&} prompt;
}
-re "^.*->" { # our configured OmniSwitch prompt
set junk $expect_out(0,string);
regsub -all "\[\]\[]" $junk {\\&} prompt;
}
}
if { $do_command } {
if {[run_commands $prompt $command]} {
continue
}
} elseif { $do_script } {
# If the prompt is (enable), then we are on a switch and the
# command is "set length 0"; otherwise its "term length 0".
if [ regexp -- ".*> .*enable" "$prompt" ] {
send "set length 0\r"
send "set logging session disable\r"
} else {
send "term length 0\r"
}
expect -re $prompt {}
source $sfile
close
} else {
label $router
log_user 1
interact
}
# End of for each router
wait
sleep 0.3
}
exit 0
-------------- next part --------------
#! /usr/bin/perl
##
## $Id: rancid.in,v 1.218 2006/10/05 04:27:43 heas Exp $
##
## rancid 2.3.2a7
## Copyright (C) 1997-2006 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
## without fee for non-commerical purposes provided that this license
## remains intact and unmodified with any RANCID distribution.
##
## 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.
##
## Except where noted otherwise, rancid was written by and is maintained by
## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-dV] [-l] [-f filename | hostname]
#
# Alcatel OmniSwitch hack by Alexander Bochmann <ab+rancid at st.gxis.de>
#
use Getopt::Std;
getopts('dflV');
if ($opt_V) {
print "rancid 2.3.2a7\n";
exit(0);
}
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
$host = $ARGV[0];
$clean_run = 0;
$found_end = 0;
$found_version = 0;
$found_env = 0;
$found_diag = 0;
$timeo = 90; # ologin timeout in seconds
my(@commandtable, %commands, @commands);# command lists
my(%filter_pwds); # password filtering mode
# This routine is used to print out the router configuration
sub ProcessHistory {
my($new_hist_tag,$new_command,$command_string, at 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 routine 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 routine 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 routine 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 routine (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 configuration status"
sub ShowCfgstat {
print STDERR " In ShowCfgstat: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
# only want the "Running configuration and saved configuration..." line
if (/^Running configuration and saved configuration/) {
ProcessHistory("COMMENTS","keysort","A1","!Cfg: $_");
ProcessHistory("COMMENTS","keysort","A1","! \n");
$found_end++;
last;
}
}
return(0);
}
# This routine parses "show configuration snapshot"
sub ShowConfig {
print STDERR " In ShowConfig: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
next if (/^(\s*|\s*$cmd\s*)$/);
next if (/^$/); # drop empty lines
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
if (/^$prompt/) {
ProcessHistory("","","","!$_");
$found_end++;
last;
}
# catch all output
ProcessHistory("","","","$_");
}
return(0);
}
# This routine parses "show chassis"
sub ShowChassis {
print STDERR " In ShowChassis: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
if (/^$prompt/) {
ProcessHistory("COMMENTS","keysort","F1","! \n");
last;
}
next if (/^(\s*|\s*$cmd\s*)$/);
next if (/^$/); # drop empty lines
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
ProcessHistory("COMMENTS","keysort","F1","!Hw: $_") && next;
}
return(0);
}
# This routine parses "show module"
sub ShowModule {
print STDERR " In ShowModule: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
if (/^$prompt/) {
ProcessHistory("COMMENTS","keysort","F2","! \n");
last;
}
next if (/^(\s*|\s*$cmd\s*)$/);
next if (/^$/); # drop empty lines
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
ProcessHistory("COMMENTS","keysort","F2","!Mod: $_") && next;
}
return(0);
}
# This routine parses "show microcode"
sub ShowMicrocode {
print STDERR " In ShowMicrocode: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
if (/^$prompt/) {
ProcessHistory("COMMENTS","keysort","F3","! \n");
last;
}
next if (/^(\s*|\s*$cmd\s*)$/);
next if (/^$/); # drop empty lines
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
ProcessHistory("COMMENTS","keysort","F3","!Sw: $_") && next;
}
return(0);
}
# This routine parses "show hardware info"
sub ShowHw {
print STDERR " In ShowHw: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
ProcessHistory("COMMENTS","keysort","F5","!Hw: $_") && next;
}
return(0);
}
# This routine parses "show version"
sub ShowVersion {
print STDERR " In ShowVersion: $_" if ($debug);
my($slaveslot);
while (<INPUT>) {
tr/\015//d;
if (/^$prompt/) { $found_version=1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
return(0) if ($found_version); # Only do this routine once
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
if (/^Slave in slot (\d+) is running/) {
$slave = " Slave:";
$slaveslot = ", slot $1";
next;
}
if (/^Application and Content Networking Software/) { $type="CE"; }
/^Application and Content Networking Software Release /i &&
ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
/^Cisco Secure PIX /i &&
ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next;
# PIX 6 fail-over license, as in "This PIX has an Unrestricted (UR)
# license." PIX 7 as "his platform has ..."
/^This (PIX|platform) has an?\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","D1", "!$_") && next;
/^(Cisco )?IOS .* Software,? \(([A-Za-z-0-9_]*)\), .*Version\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","F1",
"!Image:$slave Software: $2, $3\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: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/ &&
ProcessHistory("COMMENTS","keysort","G1",
"!ROM Bootstrap: $3\n") && next;
if (/^Hardware:\s+(.*), (.* RAM), CPU (.*)$/) {
ProcessHistory("COMMENTS","keysort","A1",
"!Chassis type: $1 - a PIX\n");
ProcessHistory("COMMENTS","keysort","A2",
"!CPU: $3\n");
ProcessHistory("COMMENTS","keysort","B1", "!Memory: $2\n");
}
/^Serial Number:\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","C1", "!$_") && next;
# More PIX stuff
/^Encryption hardware device\s+:\s+(.*)/ &&
ProcessHistory("COMMENTS","keysort","A3", "!Encryption: $1\n") &&
next;
/^running activation key\s*:\s+(.*)/i &&
ProcessHistory("COMMENTS","keysort","D2", "!Key: $1\n") &&
next;
# Flash on the PIX or FWSM (FireWall Switch Module)
/^Flash(\s+\S+)+ \@ 0x\S+,\s+(\S+)/ &&
ProcessHistory("COMMENTS","keysort","B2", "!Memory: Flash $2\n") &&
next;
# CatOS 3500xl stuff
/^System serial number(:\s+.*)$/ &&
ProcessHistory("COMMENTS","keysort","C1", "!Serial Number$1\n") &&
next;
/^Model / &&
ProcessHistory("COMMENTS","keysort","C2", "!$_") && next;
/^Motherboard / &&
ProcessHistory("COMMENTS","keysort","C3", "!$_") && next;
/^Power supply / &&
ProcessHistory("COMMENTS","keysort","C4", "!$_") && next;
/^Activation Key:\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","C2", "!$_") && 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;
/^BOOTLDR: .*(Version.*)$/ &&
ProcessHistory("COMMENTS","keysort","G4","!BOOTLDR: $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") &&
next;
/^System image file is "([^\"]*)"$/ &&
ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next;
if (/(\S+)\s+(?:\((\S+)\)\s+processor|\(revision[^)]+\)).*\s+with (\S+k) bytes/i) {
my($proc) = $1;
my($cpu) = $2;
my($mem) = $3;
my($device) = "router";
# the next line ought to be the more specific cpu info, grab it.
# yet, some boards/IOS vers have a processor ID line between these
# two. grrr. make sure we dont grab the "software" junk that
# follows these lines by looking for "CPU at " or the 2600s
# "processor: " unique string. there are undoubtedly many other
# incantations. for a slave, we dont get this info and its just a
# blank line.
$_ = <INPUT>;
if (/processor board id/i) {
my($sn);
if (/processor board id (\S+)/i) {
$sn = $1;
$sn =~ s/,$//;
ProcessHistory("COMMENTS","keysort","D9",
"!Processor ID: $sn\n");
}
$_ = <INPUT>;
}
$_ = "" if (! /(cpu at |processor: |$cpu processor,)/i);
tr/\015//d;
s/implementation/impl/i;
if ($_ !~ /^\s*$/) {
chomp;
s/^/, /;
}
if ($proc eq "CSC") {
$type = "AGS";
} elsif ($proc eq "CSC4") {
$type = "AGS+";
} elsif ($proc =~ /^(AS)?25[12][12]/) {
$type = "2500";
} elsif ($proc =~ /261[01]/ || $proc =~ /262[01]/ ) {
$type = "2600";
} elsif ($proc =~ /^36[0246][0-9]/) {
$type = "3600";
} elsif ($proc =~ /^37/) {
$type = "3700";
} elsif ($proc =~ /^38/) {
$type = "3800";
} elsif ($proc eq "RSP7000") {
$type = "7500";
} elsif ($proc =~ /RSP\d/) {
$type = "7500";
} elsif ($proc eq "RP1") {
$type = "7000";
} elsif ($proc eq "RP") {
$type = "7000";
} elsif ($proc =~ /720[246]/) {
$type = "7200";
} elsif ($proc =~ /1200[48]\/GRP/ || $proc =~ /1201[26]\/GRP/) {
$type = "12000";
} elsif ($proc =~ /1201[26]-8R\/GRP/) {
$type = "12000";
} elsif ($proc =~ /WS-C29/) {
$type = "2900XL";
$device = "switch";
} elsif ($proc =~ /WS-C355/) {
$type = "3550";
$device = "switch";
} elsif ($proc =~ /WS-C35/) {
$type = "3500XL";
$device = "switch";
} elsif ($proc =~ /WS-C45/) {
$type = "4500";
$device = "switch";
} elsif ($proc =~ /6000/) {
$type = "6000";
$device = "switch";
} elsif ($proc =~ /CISCO76/) {
$type = "7600";
$device = "router";
} elsif ($proc =~ /1900/) {
$type = "1900";
$device = "switch";
} elsif ( $proc =~ /^73/) {
$type = "7300";
} else {
$type = $proc;
}
print STDERR "TYPE = $type\n" if ($debug);
ProcessHistory("COMMENTS","keysort","A1",
"!Chassis type:$slave $proc - a $type $device\n");
ProcessHistory("COMMENTS","keysort","B1",
"!Memory:$slave main $mem\n");
if (defined($cpu)) {
ProcessHistory("COMMENTS","keysort","A3",
"!CPU:$slave $cpu$_$slaveslot\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+[kK]) bytes of multibus/ &&
ProcessHistory("COMMENTS","keysort","B2",
"!Memory: multibus $1\n") && next;
/^(\d+[kK]) bytes of (non-volatile|NVRAM)/ &&
ProcessHistory("COMMENTS","keysort","B3",
"!Memory: nvram $1\n") && next;
/^(\d+[kK]) bytes of flash memory/ &&
ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") &&
next;
/^(\d+[kK]) bytes of .*flash partition/ &&
ProcessHistory("COMMENTS","keysort","B6",
"!Memory: flash partition $1\n") && next;
/^(\d+[kK]) bytes of Flash internal/ &&
ProcessHistory("COMMENTS","keysort","B4",
"!Memory: bootflash $1\n") && next;
if (/^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i) {
ProcessHistory("COMMENTS","keysort","B7",
"!Memory: pcmcia $2 $3$4 $1\n");
next;
}
if (/^WARNING/) {
if (!defined($I0)) {
$I0=1;
ProcessHistory("COMMENTS","keysort","I0","!\n");
}
ProcessHistory("COMMENTS","keysort","I1","! $_");
}
if (/^Configuration register is (.*)$/) {
$config_register=$1;
next;
}
if (/^Configuration register on node \S+ is (.*)$/) {
$config_register=$1 if $config_register eq "";
next;
}
}
return(0);
}
# This routine parses "show redundancy"
sub ShowRedundancy {
print STDERR " In ShowRedundancy: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/^IOS .* Software \(([A-Za-z-0-9_]*)\), .*Version\s+(.*)$/ &&
ProcessHistory("COMMENTS","keysort","F1",
"!Image:$slave Software: $1, $2\n") && next;
/^Compiled (.*)$/ &&
ProcessHistory("COMMENTS","keysort","F3",
"!Image:$slave Compiled: $1\n") && next;
}
return(0);
}
# This routine parses "show IDprom"
sub ShowIDprom {
my($tmp);
print STDERR " In ShowIDprom: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/FRU is .(.*)\'/ && ($tmp = $1);
/Product Number = .(.*)\'/ &&
ProcessHistory("COMMENTS","keysort","D0",
"!Catalyst Chassis type: $1, $tmp\n");
/Serial Number = .([0-9A-Za-z]+)/ &&
ProcessHistory("COMMENTS","keysort","D1",
"!Catalyst Chassis S/N: $1\n");
/Manufacturing Assembly Number = .([-0-9]+)/ && ($tmp = $1);
/Manufacturing Assembly Revision = .(.*)\'/ && ($tmp .= ", rev " . $1);
/Hardware Revision = ([0-9.]+)/ &&
ProcessHistory("COMMENTS","keysort","D2",
"!Catalyst Chassis assembly: $tmp, ver $1\n");
}
return(0);
}
# This routine parses "show install active"
sub ShowInstallActive {
print STDERR " In ShowInstallActive: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next;
}
return(0);
}
# This routine parses "show env all"
sub ShowEnv {
# Skip if this is not a 7500, 7200, or 7000.
print STDERR " In ShowEnv: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
if (/^$prompt/) { $found_env=1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
return(0) if ($found_env); # Only do this routine once
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
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;
}
/^Power Supply Information$/ && next;
/^\s*Power Module\s+Voltage\s+Current$/ && next;
/^\s*(Power [^:\n]+)$/ &&
ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next;
/^\s*(Lower Power .*)/i &&
ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
/^\s*(redundant .*)/i &&
ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
/^\s*(RPS is .*)/i &&
ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next;
}
ProcessHistory("COMMENTS","","","!\n");
return(0);
}
# This routine parses "show rsp chassis-info" for the rsp
# This will create arrays for hw info.
sub ShowRSP {
print STDERR " In ShowRSP: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
# return(1) if ($type !~ /^12[40]/);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/^$/ && next;
/^\s+Chassis model: (\S+)/ &&
ProcessHistory("COMMENTS","keysort","D1",
"!RSP Chassis model: $1\n") &&
next;
/^\s+Chassis S\/N: (.*)$/ &&
ProcessHistory("COMMENTS","keysort","D2",
"!RSP Chassis S/N: $1\n") &&
next;
}
return(0);
}
# This routine parses "show gsr chassis-info" for the gsr
# This will create arrays for hw info.
sub ShowGSR {
# Skip if this is not a 1200n.
print STDERR " In ShowGSR: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(-1) if (/command authorization failed/i);
# return(1) if ($type !~ /^12[40]/);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/^$/ && next;
/^\s+Chassis: type (\S+) Fab Ver: (\S+)/ &&
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/7200/7500/12000/2900/3500;
# otherwise pick up bootflash.
print STDERR " In ShowBoot: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(1) if /Ambiguous command/i;
return(1) if /(Open device \S+ failed|Error opening \S+:)/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
next if /CONFGEN variable/;
if (!defined($H0)) {
$H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n");
}
if ($type !~ /^(12[04]|7)/) {
if ($type !~ /^(29|35)00/) {
ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_");
} else {
ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
}
} elsif (/variable/) {
ProcessHistory("COMMENTS","keysort","H1","!Variable: $_");
}
}
ProcessHistory("COMMENTS","","","!\n");
return(0);
}
# This routine parses "show flash"
sub ShowFlash {
# skip if this is 7000, 7200, 7500, or 12000; else we end up with
# redundant data from dir /all slot0:
print STDERR " In ShowFlash: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if ($type =~ /^(12[40]|7)/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/\s+(multiple-fs|nv_hdr|vlan\.dat)$/ && next;
ProcessHistory("FLASH","","","!Flash: $_");
}
ProcessHistory("","","","!\n");
return;
}
# This routine parses "dir /all ((disk|slot)N|bootflash|nvram):"
sub DirSlotN {
# Skip if this is not a 3600, 7000, 7200, 7500, or 12000.
print STDERR " In DirSlotN: $_" if ($debug);
my($dev) = (/\s([^\s]+):/);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|7|36)/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(1) if /(No such device|Error Sending Request)/i;
return(1) if /\%Error: No such file or directory/;
return(1) if /No space information available/;
return(-1) if /\%Error calling/;
return(-1) if /(: device being squeezed|ATA_Status time out)/i; # busy
return(-1) if (/command authorization failed/i);
return(1) if /(Open device \S+ failed|Error opening \S+:)/;
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
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);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type =~ /^(12[40]|7[05])/);
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
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 $_");
}
if (/^(\S+) : 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"
# Some of this is printed out in ShowDiagbus.
sub ShowContCbus {
# Skip if this is not a 7000 or 7500.
print STDERR " In ShowContCbus: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7[05]0/);
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
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(0);
}
# This routine parses "show debug"
sub ShowDebug {
print STDERR " In ShowDebug: $_" if ($debug);
my($lines) = 0;
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/^No matching debug flags set$/ && next;
ProcessHistory("COMMENTS","keysort","J1","!DEBUG: $_");
$lines++;
}
if ($lines) {
ProcessHistory("COMMENTS","keysort","J0","!\n");
}
return(0);
}
# This routine parses "show diagbus"
# This will create arrarys for hw info.
sub ShowDiagbus {
# Skip if this is not a 7000, 70[01]0, or 7500.
print STDERR " In ShowDiagbus: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^7[05]/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
if (/^\s*Slot (\d+):/i) {
$slot = $1;
next;
} elsif (/^\s*Slot (\d+) \(virtual\):/i) {
$slot = $1;
next;
} elsif (/^\s*(.*Processor.*|.*controller|.*controler|.*Chassis Interface)(, FRU\s?:.*)?, HW rev (\S+), board revision (\S+)/i) {
$board = $1;
$hwver = $3;
$boardrev = $4;
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});
next;
}
/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+(.*) (IP|PA), (\d) ports?,( \S+,)? (FRU\s?: )?(\S+)/ &&
ProcessHistory("SLOT","","","!Slot $slot/$board: type $6, $3 ports\n") &&
next;
/\s+(.*) (IP|PA)( \(\S+\))?, (\d) ports?/ &&
ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$3, $4 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 diag" for the gsr, 7200, 3700, 3600, 2600.
# This will create arrarys for hw info.
sub ShowDiag {
# Skip if this is not a 12000.
print STDERR " In ShowDiag: $_" if ($debug);
while (<INPUT>) {
REDUX: tr/\015//d;
if (/^$prompt/) { $found_diag=1; last};
next if (/^(\s*|\s*$cmd\s*)$/);
# return(1) if ($type !~ /^(12[40]|720|36|26)/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
return(0) if ($found_diag); # Only do this routine once
/^$/ && next;
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
s/Port Packet Over SONET/POS/;
if (/^\s*SLOT\s+(\d+)\s+\((.*)\): (.*)/) {
$slot = $1;
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: $3\n");
next;
}
if (/^\s*NODE\s+(\S+) : (.*)/) {
$slot = $1;
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
next;
}
if (/^\s*PLIM\s+(\S+) : (.*)/) {
$slot = $1 . " PLIM";
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
next;
}
if (/^\s*RACK\s+(\S+) : (.*)/) {
$slot = "Rack/" . $1;
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: $2\n");
next;
}
if (/^\s+MAIN:\s* type \S+,\s+(.*)/) {
local($part) = $1;
$_ = <INPUT>;
if (/^\s+(HW version|Design Release) (\S+)\s+S\/N (\S+)/i) {
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, serial $3\n");
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: hvers $2\n");
} else {
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part\n");
goto REDUX;
}
next;
}
if (/^\s+MAIN:\s* board type \S+$/) {
$_ = <INPUT>;
tr/\015//d;
if (/^\s+(.+)$/) {
local($part) = $1;
$_ = <INPUT>;
tr/\015//d;
if (/^\s+dev (.*)$/) {
local($dev) = $1;
$_ = <INPUT>;
if (/^\s+S\/N (\S+)/) {
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, dev $dev, serial $1\n");
} else {
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part, dev $dev\n");
goto REDUX;
}
} else {
ProcessHistory("SLOT","keysort","AM","!Slot $slot/MAIN: part $part\n");
goto REDUX;
}
} else {
goto REDUX;
}
next;
}
if (/^c3700\s+(io-board|mid-plane)/i) {
$slot=$1;
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","A","!Slot $slot: part $1\n");
next;
}
if (/ Engine:\s+(.*)/) {
ProcessHistory("SLOT","keysort","AE","!Slot $slot/Engine: $1\n");
}
if (/FRU:\s+Linecard\/Module:\s+(\S+)/) {
ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Linecard/Module: $1\n");
next;
}
if (/\s+Processor Memory:\s+(\S+)/) {
ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Processor Memory: $1\n");
next;
}
if (/\s+Packet Memory:\s+(\S+)/) {
ProcessHistory("SLOT","keysort","AF","!Slot $slot/FRU: Packet Memory: $1\n");
next;
}
if (/^\s+PCA:\s+(.*)/) {
local($part) = $1;
$_ = <INPUT>;
if (/^\s+(HW version|design release) (\S+)\s+S\/N (\S+)/i) {
ProcessHistory("SLOT","keysort","C1","!Slot $slot/PCA: part $part, serial $3\n");
ProcessHistory("SLOT","keysort","C2","!Slot $slot/PCA: hvers $2\n");
} else {
ProcessHistory("SLOT","keysort","C1","!Slot $slot/PCA: part $part\n");
goto REDUX;
}
next;
}
if (/^\s+MBUS: .*\)\s+(.*)/) {
local($tmp) = "!Slot $slot/MBUS: part $1";
$_ = <INPUT>;
/^\s+HW version (\S+)\s+S\/N (\S+)/ &&
ProcessHistory("SLOT","keysort","MB1","$tmp, serial $2\n") &&
ProcessHistory("SLOT","keysort","MB2","!Slot $slot/MBUS: hvers $1\n");
next;
}
if (/^\s+MBUS Agent Software version (.*)/) {
ProcessHistory("SLOT","keysort","MB3","!Slot $slot/MBUS: software $1\n");
next;
}
if (/^\s+PLD: (.*)/) {
ProcessHistory("SLOT","keysort","P","!Slot $slot/PLD: $1\n");
next;
}
if (/^\s+MONLIB: (.*)/) {
ProcessHistory("SLOT","keysort","Q","!Slot $slot/MONLIB: $1\n");
next;
}
if (/^\s+ROM Monitor version (.*)/) {
ProcessHistory("SLOT","keysort","R","!Slot $slot/ROM Monitor: version $1\n");
next;
}
if (/^\s+ROMMON: Version (.*)/) {
ProcessHistory("SLOT","keysort","R","!Slot $slot/ROMMON: version $1\n");
next;
}
if (/^\s+Fabric Downloader version used (.*)/) {
ProcessHistory("SLOT","keysort","Z","!Slot $slot/Fabric Downloader: version $1\n");
next;
}
if (/^\s+DRAM size: (\d+)/) {
local($dram) = $1 / 1048576;
$_ = <INPUT>;
if (/^\s+FrFab SDRAM size: (\d+)/) {
ProcessHistory("SLOT","keysort","MB4","!Slot $slot/MBUS: $dram Mbytes DRAM, "
. $1 / 1024 . " Kbytes SDRAM\n");
} else {
ProcessHistory("SLOT","keysort","MB4","!Slot $slot/MBUS: $dram Mbytes DRAM\n");
goto REDUX;
}
next;
}
# 7200, 3600, 2600, and 1700 stuff
if (/^(Slot)\s+(\d+(\/\d+)?):/
|| /^\s+(WIC|VIC|WIC\/VIC) Slot (\d):/
|| /^(Encryption AIM) (\d):/) {
if ($1 eq "WIC") {
$WIC = "/$2";
} elsif ($1 eq "VIC") {
$WIC = "/$2";
} elsif ($1 eq "WIC/VIC") {
$WIC = "/$2";
} elsif ($1 eq "DSP") {
$WIC = "/$2";
} elsif ($1 eq "Encryption AIM") {
$slot = "$2";
undef($WIC);
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1\n");
next;
} else {
$slot = $2;
undef($WIC);
}
$_ = <INPUT>; tr/\015//d;
# clean up hideous 7200/etc formats 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/intermediate reach/IR/i;
ProcessHistory("SLOT","","","!\n");
/\s+(.*) port adapter,?\s+(\d+)\s+/i &&
ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1, $2 ports\n") && next;
# I/O controller with no interfaces
/\s+(.*)\s+port adapter\s*$/i &&
ProcessHistory("SLOT","keysort","B","!Slot $slot: type $1, 0 ports\n") && next;
/\s+(.*)\s+daughter card(.*)$/ &&
ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $1$2\n") && next;
/\s+(FT1)$/ &&
ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $1\n") && next;
# handle WICs lacking "daughter card" in the 2nd line of their
# show diag o/p
if (defined($WIC)) {
s/^\s+//;
ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: type $_");
}
next;
} elsif (/^\s+(.* (DSP) Module) Slot (\d):/) {
# The 1760 (at least) has yet another format...where it has two
# dedicated DSP slots, and thus two slot 0s.
my($TYPE) = $1;
$WIC = "/$3";
ProcessHistory("SLOT","","","!\n");
ProcessHistory("SLOT","keysort","B",
"!Slot $slot$WIC: type $TYPE\n");
next;
}
# yet another format. seen on 2600s w/ 12.1, but appears to be all
# 12.1, including 7200s & 3700s. Sometimes the PCB serial appears
# before the hardware revision.
if (/(pcb serial number|hardware revision)\s+:\s+(\S+)$/i) {
my($hw, $pn, $rev, $sn);
if ($1 =~ /^pcb/i) {
$sn = $2;
} else {
$hw = $2;
}
while (<INPUT>) {
tr/\015//d;
if (/0x..: / || /^$/) {
# no effing idea why break does not work there
goto PerlSucks;
}
if (/hardware revision\s+:\s+(\S+)/i) { $hw = $1; }
if (/part number\s+:\s+(\S+)/i) { $pn = $1; }
if (/board revision\s+:\s+(\S+)/i) { $rev = $1; }
if (/pcb serial number\s+:\s+(\S+)/i) { $sn = $1; }
}
PerlSucks:
ProcessHistory("SLOT","keysort","B","!Slot $slot$WIC: hvers $hw rev $rev\n");
ProcessHistory("SLOT","keysort","C","!Slot $slot$WIC: part $pn, serial $sn\n");
}
/revision\s+(\S+).*revision\s+(\S+)/ &&
ProcessHistory("SLOT","keysort","C","!Slot $slot$WIC: hvers $1 rev $2\n") &&
next;
/number\s+(\S+)\s+Part number\s+(\S+)/ &&
ProcessHistory("SLOT","keysort","D","!Slot $slot$WIC: part $2, serial $1\n") &&
next;
}
ProcessHistory("SLOT","","","!\n");
return(0);
}
# This routine parses "show inventory".
sub ShowInventory {
print STDERR " In ShowInventory: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
return if (/^\s*\^$/);
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
if (/^(NAME: "[^"]*",) (DESCR: "[^"]+")/) {
ProcessHistory("INVENTORY","","", sprintf("!%-30s %s\n", $1, $2));
next;
}
# split PID/VID/SN line
if (/^PID: (\S*)\s*, VID: (\S*)\s*, SN: (\S*)\s*$/) {
my($entries) = "";
$entries .= "!PID: $1\n" if ($1);
$entries .= "!VID: $2\n" if ($2);
$entries .= "!SN: $3\n" if ($3);
ProcessHistory("INVENTORY","","", "$entries");
next;
}
ProcessHistory("INVENTORY","","","!$_");
}
ProcessHistory("INVENTORY","","","!\n");
return(0);
}
# This routine parses "show module".
#sub ShowModule {
# print STDERR " In ShowModule: $_" if ($debug);
#
# my(@lines);
# my($slot, $pa);
#
# while (<INPUT>) {
# tr/\015//d;
# return if (/^\s*\^$/);
# last if (/online diag status/i);
# last if (/^$prompt/);
# next if (/^(\s*|\s*$cmd\s*)$/);
# return(-1) if (/command authorization failed/i);
# # the pager can not be disabled per-session on the PIX
# if (/^(<-+ More -+>)/) {
# my($len) = length($1);
# s/^$1\s{$len}//;
# }
#
# # match slot/card info line
# if (/^ *(\d+)\s+(\d+)\s+(.*)\s+(\S+)\s+(\S+)\s*$/) {
# $lines[$1 * 1000] .= "!Slot $1: type $3, $2 ports\n!Slot $1: part $4, serial $5\n";
# $lines[$1 * 1000] =~ s/\s+,/,/g;
# next;
# }
# # now match the Revs in the second paragraph of o/p and stick it in
# # the array with the previous bits...grumble.
# if (/^ *(\d+)\s+\S+\s+to\s+\S+\s+(\S+)\s+(\S*)\s+(\S+)(\s+\S+)?\s*$/) {
# $lines[$1 * 1000] .= "!Slot $1: hvers $2, firmware $3, sw $4\n";
# $lines[$1 * 1000] =~ s/\s+,/,/g;
# next;
# }
# # grab the sub-modules, if any
# if (/^\s+(\d+)\s(.*)\s+(\S+)\s+(\S+)\s+(\S+)\s+\S+\s*$/) {
# my($idx);
# $pa = 0 if ($1 != $slot);
# $slot = $1;
# $idx = $1 * 1000 + $1 * 10 + $pa;
# $lines[$idx] .= "!Slot $1/$pa: type $2\n";
# $lines[$idx] .= "!Slot $slot/$pa: part $3, serial $4\n";
# $lines[$idx] .= "!Slot $slot/$pa: hvers $5\n";
# $pa++;
# }
# }
# foreach $slot (@lines) {
# next if ($slot =~ /^\s*$/);
# ProcessHistory("Module","","","$slot!\n");
# }
#
# return(0);
#}
# This routine parses "show spe version".
sub ShowSpeVersion {
print STDERR " In ShowSpeVersion: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(-1) if (/command authorization failed/i);
ProcessHistory("MODEM","","","!Modem: $_") && next;
}
ProcessHistory("MODEM","","","!\n");
return(0);
}
# This routine parses "show c7200" for the 7200
# This will create arrays for hw info.
sub ShowC7200 {
# Skip if this is not a 7200.
print STDERR " In ShowC7200: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
#return(1) if ($type !~ /^72/);
return(-1) if (/command authorization failed/i);
/^$/ && next;
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
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 (/C720\d(VXR)? CPU EEPROM:/) {
my ($hvers,$rev,$part,$serial);
# npe400s report their cpu eeprom info differently w/ 12.0.21S
while (<INPUT>) {
/Hardware Revision\s+: (\S+)/ && ($hvers = $1) && next;
/Board Revision\s+: (\S+)/ && ($rev = $1) && next;
/Part Number\s+: (\S+)/ && ($part = $1) && next;
/Serial Number\s+: (\S+)/ && ($serial = $1) && next;
/revision\s+(\S+).*revision\s+(\S+)/ &&
($hvers = $1, $rev = $2) && next;
/number\s+(\S+)\s+Part number\s+(\S+)/ &&
($serial = $1, $part = $2) && next;
/^\s*$/ && last;
}
ProcessHistory("SLOT","","","!Slot CPU: hvers $hvers rev $rev\n");
ProcessHistory("SLOT","","","!Slot CPU: part $part, serial $serial\n!\n");
next;
}
}
return(0);
}
# This routine parses "show vtp status"
sub ShowVTP {
print STDERR " In ShowVTP: $_" if ($debug);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
#return(1) if ($type !~ /^(2900XL|3500XL|6000)$/);
return(-1) if (/command authorization failed/i);
next if (/^Configuration last modified by/);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
if (/^VTP Operating Mode\s+:\s+(Transparent|Server)/) {
$DO_SHOW_VLAN = 1;
}
ProcessHistory("COMMENTS","keysort","I0","!VTP: $_");
}
ProcessHistory("COMMENTS","keysort","I0","!\n");
return(0);
}
# This routine parses "show vlan"
sub ShowVLAN {
print STDERR " In ShowVLAN: $_" if ($debug);
($_=<INPUT>,return(1)) if (!$DO_SHOW_VLAN);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
return(1) if /^\s*\^\s*$/;
return(1) if /Line has invalid autocommand /;
return(1) if /(Invalid input detected|Type help or )/;
return(1) if /Ambiguous command/i;
# newer releases (~12.1(9)) place the vlan config in the normal
# configuration (write term).
return(1) if ($type =~ /^(3550|4500|7600)$/);
#return(1) if ($type !~ /^(2900XL|3500XL|6000)$/);
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
ProcessHistory("COMMENTS","keysort","IO","!VLAN: $_");
}
ProcessHistory("COMMENTS","keysort","IO","!\n");
return(0);
}
# This routine processes a "write term"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
my($lineauto,$comment,$linecnt) = (0,0,0);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
return(1) if /Line has invalid autocommand /;
return(1) if (/(Invalid input detected|Type help or )/i);
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
/Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
return(0) if ($found_end); # Only do this routine once
$linecnt++;
$lineauto = 0 if (/^[^ ]/);
# skip the crap
if (/^(##+$|(Building|Current) configuration)/i) {
while (<INPUT>) {
next if (/^Current configuration\s*:/i);
next if (/^:/);
next if (/^([%!].*|\s*)$/);
next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S
last;
}
if (defined($config_register)) {
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;
# skip consecutive comment lines to avoid oscillating extra comment
# line on some access servers. grrr.
if (/^!/) {
next if ($comment);
ProcessHistory("","","",$_);
$comment++;
next;
}
$comment = 0;
# 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
$lineauto = 1 if /^ modem auto/;
/^ speed / && $lineauto && next; # kill speed on serial lines
/^ clockrate / && next; # kill clockrate on serial interfaces
if (/^(enable )?(password|passwd)( level \d+)? / && $filter_pwds >= 1) {
ProcessHistory("ENABLE","","","!$1$2$3 <removed>\n");
next;
}
if (/^(enable secret) / && $filter_pwds >= 2) {
ProcessHistory("ENABLE","","","!$1 <removed>\n");
next;
}
if (/^username (\S+)(\s.*)? secret /) {
if ($filter_pwds >= 2) {
ProcessHistory("USER","keysort","$1","!username $1$2 secret <removed>\n");
} else {
ProcessHistory("USER","keysort","$1","$_");
}
next;
}
if (/^username (\S+)(\s.*)? password ((\d) \S+|\S+)/) {
if ($filter_pwds >= 2) {
ProcessHistory("USER","keysort","$1","!username $1$2 password <removed>\n");
} elsif ($filter_pwds >= 1 && $4 ne "5"){
ProcessHistory("USER","keysort","$1","!username $1$2 password <removed>\n");
} else {
ProcessHistory("USER","keysort","$1","$_");
}
next;
}
# cisco AP w/ IOS
if (/^(wlccp \S+ username (\S+)(\s.*)? password) (\d \S+|\S+)/) {
if ($filter_pwds >= 1) {
ProcessHistory("USER","keysort","$2","!$1 <removed>\n");
} else {
ProcessHistory("USER","keysort","$2","$_");
}
next;
}
if (/^( set session-key (in|out)bound ah \d+ )/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1<removed>\n");
next;
}
if (/^( set session-key (in|out)bound esp \d+ (authenticator|cypher) )/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1<removed>\n");
next;
}
if (/^(\s*)password / && $filter_pwds >= 1) {
ProcessHistory("LINE-PASS","","","!$1password <removed>\n");
next;
}
if (/^(\s*)secret / && $filter_pwds >= 2) {
ProcessHistory("LINE-PASS","","","!$1secret <removed>\n");
next;
}
if (/^\s*neighbor (\S*) password / && $filter_pwds >= 1) {
ProcessHistory("","","","! neighbor $1 password <removed>\n");
next;
}
if (/^(ppp .* password) 7 .*/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
if (/^(ip ftp password) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
# isis passwords appear to be completely plain-text
if (/^\s+isis password (\S+)( .*)?/ && $filter_pwds >= 1) {
ProcessHistory("","","","!isis password <removed>$2\n"); next;
}
if (/^\s+(domain-password|area-password) (\S+)( .*)?/
&& $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>$3\n"); next;
}
# this is reversable, despite 'md5' in the cmd
if (/^( ip ospf message-digest-key \d+ md5) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
# this is also reversable, despite 'md5 encrypted' in the cmd
if (/^( message-digest-key \d+ md5 (7|encrypted)) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed> $'"); next;
}
# filter HSRP passwords
if (/^(\s+standby \d+ authentication) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
# this appears in "measurement/sla" images
if (/^(\s+key-string \d?)/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
if (/^( l2tp tunnel \S+ password)/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n"); next;
}
# i am told these are plain-text on the PIX
if (/^(vpdn username (\S+) password)/) {
if ($filter_pwds >= 1) {
ProcessHistory("USER","keysort","$2","!$1 <removed>\n");
} else {
ProcessHistory("USER","keysort","$2","$_");
}
next;
}
if (/^( cable shared-secret )/ && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>\n");
next;
}
/fair-queue individual-limit/ && next;
# sort ip explicit-paths.
if (/^ip explicit-path name (\S+)/) {
my($key) = $1;
my($expath) = $_;
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/);
if (/^ip explicit-path name (\S+)/) {
ProcessHistory("EXPATH","keysort","$key","$expath");
$key = $1;
$expath = $_;
} else {
$expath .= $_;
}
}
ProcessHistory("EXPATH","keysort","$key","$expath");
}
# sort route-maps
if (/^route-map (\S+)/) {
my($key) = $1;
my($routemap) = $_;
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/ || ! /^(route-map |[ !])/);
if (/^route-map (\S+)/) {
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/prune snmp-server host statements
# we only prune lines of the form
# snmp-server host a.b.c.d <community>
if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) {
if (defined($ENV{'NOCOMMSTR'})) {
my($ip) = $1;
my($line) = "snmp-server host $ip";
my(@tokens) = split(' ', $');
my($token);
while ($token = shift(@tokens)) {
if ($token eq 'version') {
$line .= " " . join(' ', ($token, shift(@tokens)));
if ($token eq '3') {
$line .= " " . join(' ', ($token, shift(@tokens)));
}
} elsif ($token eq 'vrf') {
$line .= " " . join(' ', ($token, shift(@tokens)));
} elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
$line .= " " . $token;
} else {
$line = "!$line " . join(' ', ("<removed>", join(' ', at tokens)));
last;
}
}
ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n");
} else {
ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
}
next;
}
if (/^(snmp-server community) (\S+)/) {
if (defined($ENV{'NOCOMMSTR'})) {
ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 <removed>$'") && next;
} else {
ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
}
}
# prune tacacs/radius server keys
if (/^((tacacs-server|radius-server)\s(\w*[-\s(\s\S+])*\s?key) \d \w+/
&& $filter_pwds >= 1) {
ProcessHistory("","","","!$1 <removed>$'"); 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 - this md5 is a reversable too
if (/^(ntp authentication-key \d+ md5) / && $filter_pwds >= 1) {
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 statements
/^ip host (\S+) / &&
ProcessHistory("IPHOST","keysort","$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;
# system controller
/^syscon address (\S*) (\S*)/ &&
ProcessHistory("","","","!syscon address $1 <removed>\n") &&
next;
if (/^syscon password (\S*)/ && $filter_pwds >= 1) {
ProcessHistory("","","","!syscon password <removed>\n");
next;
}
# catch anything that wasnt matched above.
ProcessHistory("","","","$_");
# end of config. the ": " game is for the PIX
if (/^(: +)?end$/) {
$found_end = 1;
return(1);
}
}
# The ContentEngine lacks a definitive "end of config" marker. If we
# know that it is a CE and we have seen at least 5 lines of write term
# o/p, we can be reasonably sure that we got the config.
if ($type =~ /^CE$/ && $linecnt > 5) {
$found_end = 1;
return(1);
}
return(0);
}
# dummy function
sub DoNothing {print STDOUT;}
# Main
@commandtable = (
# {'show hardware info' => 'ShowHw'},
{'show configuration status' => 'ShowCfgstat'},
{'show chassis' => 'ShowChassis'},
{'show module' => 'ShowModule'},
{'show microcode' => 'ShowMicrocode'},
{'show configuration snapshot all' => 'ShowConfig'},
# {'admin show version' => 'ShowVersion'},
# {'show version' => 'ShowVersion'},
# {'show redundancy secondary' => 'ShowRedundancy'},
# {'show idprom backplane', => 'ShowIDprom'},
# {'show install active' => 'ShowInstallActive'},
# {'admin show env all' => 'ShowEnv'},
# {'show env all' => 'ShowEnv'},
# {'show rsp chassis-info', => 'ShowRSP'},
# {'show gsr chassis' => 'ShowGSR'},
# {'show diag chassis-info' => 'ShowGSR'},
# {'show boot' => 'ShowBoot'},
# {'show bootvar' => 'ShowBoot'},
# {'admin show variables boot' => 'ShowBoot'},
# {'show variables boot' => 'ShowBoot'},
# {'show flash' => 'ShowFlash'},
# {'dir /all nvram:' => 'DirSlotN'},
# {'dir /all bootflash:' => 'DirSlotN'},
# {'dir /all slot0:' => 'DirSlotN'},
# {'dir /all disk0:' => 'DirSlotN'},
# {'dir /all slot1:' => 'DirSlotN'},
# {'dir /all disk1:' => 'DirSlotN'},
# {'dir /all slot2:' => 'DirSlotN'},
# {'dir /all disk2:' => 'DirSlotN'},
# {'dir /all harddisk:' => 'DirSlotN'},
# {'dir /all harddiska:' => 'DirSlotN'},
# {'dir /all harddiskb:' => 'DirSlotN'},
# {'dir /all sup-bootflash:' => 'DirSlotN'}, # cat 6500-ios
# {'dir /all sup-microcode:' => 'DirSlotN'}, # cat 6500-ios
# {'dir /all slavenvram:' => 'DirSlotN'},
# {'dir /all slavebootflash:' => 'DirSlotN'},
# {'dir /all slaveslot0:' => 'DirSlotN'},
# {'dir /all slavedisk0:' => 'DirSlotN'},
# {'dir /all slaveslot1:' => 'DirSlotN'},
# {'dir /all slavedisk1:' => 'DirSlotN'},
# {'dir /all slaveslot2:' => 'DirSlotN'},
# {'dir /all slavedisk2:' => 'DirSlotN'},
# {'dir /all slavesup-bootflash:' => 'DirSlotN'}, # cat 7609
# {'dir /all sec-nvram:' => 'DirSlotN'},
# {'dir /all sec-bootflash:' => 'DirSlotN'},
# {'dir /all sec-slot0:' => 'DirSlotN'},
# {'dir /all sec-disk0:' => 'DirSlotN'},
# {'dir /all sec-slot1:' => 'DirSlotN'},
# {'dir /all sec-disk1:' => 'DirSlotN'},
# {'dir /all sec-slot2:' => 'DirSlotN'},
# {'dir /all sec-disk2:' => 'DirSlotN'},
# {'show controllers' => 'ShowContAll'},
# {'show controllers cbus' => 'ShowContCbus'},
# {'show diagbus' => 'ShowDiagbus'},
# {'admin show diag' => 'ShowDiag'},
# {'show diag' => 'ShowDiag'},
# {'show module' => 'ShowModule'}, # cat 6500-ios
# {'show spe version' => 'ShowSpeVersion'},
# {'show c7200' => 'ShowC7200'},
# {'show inventory raw' => 'ShowInventory'},
# {'show vtp status' => 'ShowVTP'},
# {'show vlan' => 'ShowVLAN'},
# {'show vlan-switch' => 'ShowVLAN'},
# {'show debug' => 'ShowDebug'},
# {'show running-config' => 'WriteTerm'},
# {'write term' => 'WriteTerm'},
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
$cisco_cmds=join(";", at commands);
$cmds_regexp=join("|", at commands);
if (length($host) == 0) {
if ($file) {
print(STDERR "Too few arguments: file name required\n");
exit(1);
} else {
print(STDERR "Too few arguments: host name required\n");
exit(1);
}
}
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 ologin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
print STDOUT "executing ologin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
if (defined($ENV{NOPIPE})) {
system "ologin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "ologin failed for $host: $!\n";
open(INPUT, "< $host.raw") || die "ologin failed for $host: $!\n";
} else {
open(INPUT,"ologin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "ologin failed for $host: $!\n";
}
}
# determine password filtering mode
if ($ENV{"FILTER_PWDS"} =~ /no/i) {
$filter_pwds = 0;
} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
$filter_pwds = 2;
} else {
$filter_pwds = 1;
}
ProcessHistory("","","","!RANCID-CONTENT-TYPE: alcatel\n!\n");
ProcessHistory("COMMENTS","keysort","B0","!\n");
ProcessHistory("COMMENTS","keysort","D0","!\n");
ProcessHistory("COMMENTS","keysort","F0","!\n");
ProcessHistory("COMMENTS","keysort","G0","!\n");
TOP: while(<INPUT>) {
tr/\015//d;
if (/^Error:/) {
print STDOUT ("$host ologin error: $_");
print STDERR ("$host ologin error: $_") if ($debug);
$clean_run=0;
last;
}
while (/->\s*($cmds_regexp)\s*$/) {
$cmd = $1;
if (!defined($prompt)) {
# $prompt = ($_ =~ /^([^#]+#)/)[0];
$prompt = ($_ =~ /^([^>]+->)/)[0];
$prompt =~ s/([][}{)(\\])/\\$1/g;
print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
print STDERR "$host: found unexpected command - \"$cmd\"\n";
$clean_run = 0;
last TOP;
}
$rval = &{$commands{$cmd}};
delete($commands{$cmd});
if ($rval == -1) {
$clean_run = 0;
last TOP;
}
}
if (/([>#]\s?exit|->exit|Connection\ closed\ by\ CliShell)$/) {
$clean_run=1;
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 "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
}
print STDERR "clean $clean_run end $found_end\n";
if (!$clean_run || !$found_end) {
print STDOUT "$host: End of run not found\n";
print STDERR "$host: End of run not found\n" if ($debug);
system("/usr/bin/tail -1 $host.new");
}
unlink "$host.new" if (! $debug);
}
More information about the Rancid-discuss
mailing list