diff options
Diffstat (limited to 'bin/cat5rancid.in')
-rwxr-xr-x | bin/cat5rancid.in | 1079 |
1 files changed, 1079 insertions, 0 deletions
diff --git a/bin/cat5rancid.in b/bin/cat5rancid.in new file mode 100755 index 0000000..8eb529b --- /dev/null +++ b/bin/cat5rancid.in @@ -0,0 +1,1079 @@ +#!@PERLV_PATH@ +## +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # clogin timeout in seconds + +my(%modules); # module info (part from sh ver, part from sh module) + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + while (<INPUT>) { + tr/\015//d; + last if(/^$prompt/); + next if(/^(\s*|\s*$cmd\s*)$/); + /^(\S+) Software, Version\s+(.*)$/ && + ProcessHistory("COMMENTS","keysort","F1", + "!Image: Software: $2\n") && next; + /^(\S+) S\/W compiled on (.*)$/ && + ProcessHistory("COMMENTS","keysort","F3", + "!Image: Compiled: $1 on $2\n") && next; + /^System Bootstrap (Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G1", + "!Bootstrap: $1\n") && next; + if (/^Hardware Version: (\S+) Model: (\S+) Serial #: (\S+)/) { + my($proc) = $2; + # Really should figure out types of switches here. + $type = $2; + ProcessHistory("COMMENTS","keysort","A1", + "!Chassis type: $proc - a $type switch\n"); + ProcessHistory("COMMENTS","keysort","C1", "!Serial Number: $3\n"); + ProcessHistory("COMMENTS","keysort","C2", "!Hardware Version: $1\n"); + next; + } + # stuff module h/w, s/w, ports, etc into %module + if (/^Mod\s+Port\s+Model/) { + <INPUT>; + my($slot); + while (<INPUT>) { + tr/\015//d; + last if (/^\s*$/); + if (/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s?:\s+(\S+)/) { + $slot = $1; + $modules{$slot}->{ports} = $2; + $modules{$slot}->{model} = $3; + $modules{$slot}->{serial} = $4; + $modules{$slot}->{$5} = $6; # revision info + } + /^\s+(\S+)\s?:\s+(\S+)/ && + ($modules{$slot}->{$1} = $2); + } + next; + } + # stuff module h/w, s/w, ports, etc into %module - yet another format + if (/^Module\s+Ports\s+Model/) { + <INPUT>; + my($slot); + while (<INPUT>) { + tr/\015//d; + last if (/^\s*$/); + if (/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+\s+)?(\S+)\s*$/) { + $slot = $1; + $modules{$slot}->{ports} = $2; + $modules{$slot}->{model} = $3; + $modules{$slot}->{serial} = $4; + $modules{$slot}->{Hw} = $5; + $modules{$slot}->{Fw} = $6; + $modules{$slot}->{Sw} = $8; + $modules{$slot}->{Fw1} = $7; + $modules{$slot}->{Fw1} =~ s/\s*$//; + if ($modules{$slot}->{Fw1} =~ /^$/) {delete($modules{$slot}->{Fw1});} + } + } + next; + } + if (/^ DRAM/) { + # Eat 2 lines & then get the total dram, flash, & nvram. + $_ = <INPUT>; $_ = <INPUT>; + $_ = <INPUT>; tr/\015//d; + /\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)/ && + ProcessHistory("COMMENTS","keysort","B1", + "!Memory: dram $1\n") && + ProcessHistory("COMMENTS","keysort","B5", + "!Memory: flash $2\n") && + ProcessHistory("COMMENTS","keysort","B2", + "!Memory: nvram $3\n"); + next; + } + if (/^Module DRAM/) { + # Eat a line & then get the total dram, flash, & nvram. + $_ = <INPUT>; + $_ = <INPUT>; tr/\015//d; + /\S+\s+(\S+)\s+(\S+)\s+(\S+)/ && + ProcessHistory("COMMENTS","keysort","B1", + "!Memory: dram $1\n") && + ProcessHistory("COMMENTS","keysort","B5", + "!Memory: flash $2\n") && + ProcessHistory("COMMENTS","keysort","B2", + "!Memory: nvram $3\n"); + next; + } + } + 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 /Invalid input detected/; + return(1) if /Unknown command/; + 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; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7/); + if (!defined($E0)) { + $E0=1; + ProcessHistory("COMMENTS","keysort","E0","!\n"); + } + if (/^Arbiter type (\d), backplane type (\S+)/) { + if (!defined($C0)) { + $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); + } + ProcessHistory("COMMENTS","keysort","C1", + "!Enviromental Arbiter Type: $1\n"); + ProcessHistory("COMMENTS","keysort","A2", + "!Chassis type: $2 backplane\n"); + next; + } + /^\s*(Power .*)/ && + ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next; + /^\s*(Lower Power .*)/i && + ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show gsr chassis-info" for the gsr +# This will create arrarys 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 ($type !~ /^120/); + /^$/ && next; + /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ && + ProcessHistory("COMMENTS","keysort","D0","!\n") && + ProcessHistory("COMMENTS","keysort","D1", + "!GSR Chassis type: $1 Fab Ver: $2\n") && + next; + /^\s+Chassis S\/N: (.*)$/ && + ProcessHistory("COMMENTS","keysort","D2", + "!GSR Chassis S/N: $1\n") && + next; + /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D3", + "!GSR Backplane PCA: $1, rev $2, ver $3\n") && + next; + /^\s+Backplane S\/N: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D4", + "!GSR Backplane S/N: $1\n") && + next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show boot" +sub ShowBoot { + 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 /Ambiguous command/i; + return(1) if /Invalid input detected/; + return(1) if /Unknown command/; + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + next if /CONFGEN variable/; + if (!defined($H0)) { + $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n"); + } + /^(\S+) variable (.*)$/ && + ProcessHistory("COMMENTS","keysort","H1","!Variable: $1 $2\n") && + next; + if (/^Configuration register is (.*)$/) { + $config_register=$1; + next; + } + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show flash" +sub ShowFlash { + # skip if this is 7000, 7200, 7500, or 12000. + print STDERR " In ShowFlash: $_" if ($debug); + + while (<INPUT>) { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7)/); + return(1) if /^\s*\^\s*$/; + return(1) if /Invalid input detected/; + ProcessHistory("FLASH","","","!Flash: $_"); + } + ProcessHistory("","","","!\n"); + return; +} + +# This routine parses "dir /all ((disk|slot)N|bootflash):" +sub DirSlotN { + # Skip if this is not a 3600, 7000, 7200, 7500, or 12000. + print STDERR " In 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 !~ /^(120|7|36)/); + return(1) if /^\s*\^\s*$/; + return(1) if /Invalid input detected/; + 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/; # Flash is busy + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + ProcessHistory("FLASH","","","!Flash: $dev: $_"); + } + ProcessHistory("","","","!\n"); + return(0); +} + +# This routine parses "show controllers" +sub ShowContAll { + # Skip if this is a 70[01]0, 7500, or 12000. + print STDERR " In ShowContAll: $_" if ($debug); + + while (<INPUT>) { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7[05])/); + if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; } + /^(BRI unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /^LANCE unit \d, NIM/ && + ProcessHistory("INT","","","!Interface: $_") && next; + /^(LANCE unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /(Media Type is \S+),/ && + ProcessHistory("INT","","","!\t$1\n"); + if (/(M\dT:) show controller:$/) { + my($ctlr) = $1; + $_ = <INPUT>; tr/\015//d; s/ subunit \d,//; + ProcessHistory("INT","","","!Interface: $ctlr $_"); + } + 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/); + 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 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]/); + if (/^\s*Slot (\d+):/i) { + $slot = $1; + next; + } elsif (/^\s*Slot (\d+) \(virtual\):/i) { + $slot = $1; + next; + } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) { + $board = $1; + $hwver = $2; + $boardrev = $3; + if ($board =~ /Processor/) { + if ($board =~ /7000 Route\/Switch/) { + $board = "RSP7000"; + } elsif ($board =~ /Route\/Switch Processor (\d)/) { + $board = "RSP$1"; + } elsif ($board =~ /Route/) { + $board = "RP"; + } elsif ($board =~ /Silicon Switch/) { + $board = "SSP"; + } elsif ($board =~ /Switch/) { + $board = "SP"; + $board = "SSP $sspmem" if $ssp; + } elsif ($board =~ /ATM/) { + $board = "AIP"; + } + } elsif ($board =~ /(.*) controller/i) { + $board = $1; + } + # hwucode{$slot} defined in ShowContCbus + if (defined $hwucode{$slot}) { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n"); + } else { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n"); + } + # These are also from the ShowContCbus + ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot}); + ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n") + if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot})); + ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot}); + 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+(.*) PA, (\d) ports?, (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && + next; + /\s+(.*) PA( \(\S+\))?, (\d) ports?/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && + next; + /^\s*HW rev (\S+), Board revision (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && + next; + /Serial number: (\S+)\s*Part number: (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next; + } + return(0); +} + +# This routine parses "show diag" for the gsr, 7200, 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>) { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^(120|720|36|26)/); + /^$/ && next; + if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");} + s/Port Packet Over SONET/POS/; + if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) { + $slot = $1; + ProcessHistory("SLOT","","","!Slot $slot: $2\n"); + $board = "RP" if (/Route Processor/); + $board = "CLK" if (/Clock Scheduler Card/); + next; + } + if (/^\s+PCA:\s+(.*)/){ + local($part) = $1; + $_ = <INPUT>; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n"); + next; + } + + if (/^\s+MBUS: .*\)\s+(.*)/) { + local($tmp) = "!Slot $slot/MBUS: part $1"; + $_ = <INPUT>; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","$tmp, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n"); + next; + } + if (/^\s+MBUS Agent Software version (.*)/) { + local($sw) = $1; + local($tail) = "!\n" if ($board =~ /(CLK|RP)/); + ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail"); + next; + } + if (/^\s+DRAM size: (\d+)/) { + local($dram) = $1 / 1048576; + $_ = <INPUT>; + /^\s+FrFab SDRAM size: (\d+)/ && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, " + . $1 / 1024 . " Kbytes SDRAM\n!\n"); + next; + } + # 7200 and 3600 stuff + if (/^(Slot)\s+(\d+):/ || /^\s+(WIC|VIC) Slot (\d):/) { + if ($1 eq "WIC") { + $WIC = "/$2"; + } elsif ($1 eq "VIC") { + $WIC = "/$2"; + } else { + $slot = $2; + undef($WIC); + } + $_ = <INPUT>; tr/\015//d; + + # clean up hideous 7200 format to look more like 7500 output + s/Fast-ethernet on C7200 I\/O card/FE-IO/; + s/ with MII or RJ45/-TX/; + s/Fast-ethernet /100Base/; s/[)(]//g; + + /\s+(.*) port adapter,?\s+(\d+)\s+/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n"); + # I/O controller with no interfaces + /\s+(.*)\s+port adapter\s*$/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, 0 ports\n"); + /\s+(.*)\s+daughter card(.*)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n"); + /\s+(FT1)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n"); + next; + } + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && + next; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && + next; +} + return(0); +} + +# This routine parses "show module" +sub ShowModule { + my($slot); + print STDERR " In ShowModule: $_" if ($debug); + +OUTER:while (<INPUT>) { + tr/\015//d; + last if(/^$prompt/); + # stuff module type into %module + if (/^Mod\s+Slot\s+Ports/) { + <INPUT>; + while (<INPUT>) { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^Module .*mismatch/) { + ProcessHistory("MODWARN","","","!\n! WARNING: $_"); + while (<INPUT>) { + tr/\015//d; + last OUTER if (/^\s*$/); + last if (/^\d/); + ProcessHistory("MODWARN","","","! $_"); + } + } + if (/^(\d+)\s+\d+\s+\d+\s+(.*)\s+\S+\s+\S+\s*$/) { + $modules{$1}->{type} = $2; + $modules{$1}->{type} =~ s/\s{2,}.*$//; + } + } + next; + } + # one does it one way... pita + if (/^Mod\s+Module-Name\s+Ports/) { + <INPUT>; + #my($slot); + while (<INPUT>) { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^(\d+)\s+(\S+\s+)?\d+\s+(.*)\s+\S+\s+(\S+)\s+\S+\s*$/) { + $modules{$1}->{serial} = $4; + $modules{$1}->{type} = $3; + #$modules{$1}->{type} =~ s/\s{2,}.*$//; + $modules{$1}->{type} =~ s/\s*$//; + } + } + next; + } + # daughter boards + if (/^Mod\s+Sub-Type/) { + <INPUT>; + my($slot, $board); + while (<INPUT>) { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^(\d+)\s+(\S+.*\s+)?(\S+)\s+(\S+)\s+(\S+)\s*$/) { + $board = 0 if ($slot != $1); + $slot = $1; + $modules{$1}->{daughter}->{$board}->{model} = $3; + $modules{$1}->{daughter}->{$board}->{serial} = $4; + $modules{$1}->{daughter}->{$board}->{Hw} = $5; + $modules{$1}->{daughter}->{$board}->{type} = $2; + $modules{$1}->{daughter}->{$board}->{type} =~ s/\s*$//; + $board++; + } + } + next; + } + } + + # dump the module info + foreach $slot (sort numerically keys(%modules)) { + my($dboards); + ProcessHistory("MODS","","","!\n"); + ProcessHistory("MODS","","",sprintf("!Slot $slot: type %s, %d ports\n", $modules{$slot}->{type}, $modules{$slot}->{ports})); + delete($modules{$slot}->{ports}); + delete($modules{$slot}->{type}); + my($model) = sprintf("!Slot $slot: part %s, serial %s\n", $modules{$slot}->{model}, $modules{$slot}->{serial}); + delete($modules{$slot}->{model}); + delete($modules{$slot}->{serial}); + # deal with daughter boards before slot versions + if (defined($modules{$slot}->{daughter})) { + my($board); + foreach $board (sort numerically keys(%{$modules{$slot}->{daughter}})) { + $dboards .= sprintf("!Slot $slot/$board: type %s\n", $modules{$slot}->{daughter}->{$board}->{type}); + $dboards .= sprintf("!Slot $slot/$board: hvers %s\n", $modules{$slot}->{daughter}->{$board}->{Hw}); + $dboards .= sprintf("!Slot $slot/$board: part %s, serial %s\n", $modules{$slot}->{daughter}->{$board}->{model}, $modules{$slot}->{daughter}->{$board}->{serial}); + } + delete($modules{$slot}->{daughter}); + } + my($ver); my($i) = 0; + ProcessHistory("MODS","","","!Slot $slot:"); + foreach $ver (sort keys(%{$modules{$slot}})) { + if ($i) {ProcessHistory("MODS","","",",");} + ProcessHistory("MODS","","",sprintf(" %s: %s", $ver, $modules{$slot}->{$ver})); + $i++; + } + ProcessHistory("MODS","","","\n"); + ProcessHistory("MODS","","",$model); + if ($dboards) {ProcessHistory("MODS","","",$dboards);} + } +} + +# This routine parses "show c7200" for the 7200 +# This will create arrarys 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/); + /^$/ && next; + if (/C7200 Midplane EEPROM:/) { + $_ = <INPUT>; + /revision\s+(\S+).*revision\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n"); + $_ = <INPUT>; + /number\s+(\S+)\s+Part number\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n"); + next; + } + if (/C720\d(VXR)? CPU EEPROM:/) { + $_ = <INPUT>; + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n"); + $_ = <INPUT>; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n"); + next; + } + } + return(0); +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + ProcessHistory("","","","!\n"); + while (<INPUT>) { + tr/\015//d; + last if (/^$prompt/); + next if (/^\.+$/ | /^$/); + /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked + # skip the crap + next if (/^This command shows non-default configurations only./i); + next if (/^Use 'write terminal all' to show both default and non/i); + if (/^(\.\.+$|##+$|Building configuration...)/i) { + while (<INPUT>) { + tr/\015//d; + next if (/^Current configuration:/i); + next if (/^(\.+|[%!].*|\s*)$/); + next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S + last; + } + ProcessHistory("","","","!\n"); + if (defined($config_register)) { + ProcessHistory("","","","config-register $config_register\n"); + } + tr/\015//d; + } + # some versions have other crap mixed in with the bits in the + # block above + /^! (Last configuration|NVRAM config last)/ && next; + + # Dog gone Cool matches to process the rest of the config + /^#time: / && next; # kill time: + /^tftp-server flash / && next; # kill any tftp remains + /^ntp clock-period / && next; # kill ntp clock-period + /^ length / && next; # kill length on serial lines + /^ width / && next; # kill width on serial lines + /^enable password / && + ProcessHistory("ENABLE","","","!enable password <removed>\n") && + next; + /^(username .*) password /&& + ProcessHistory("USER","","","!$1 password <removed>\n") && next; + /^\s*password / && + ProcessHistory("LINE-PASS","","","! password <removed>\n") && next; + /^\s*neighbor (\S*) password / && + ProcessHistory("","","","! neighbor $1 password <removed>\n") && + next; + /^(ip ftp password) / && + ProcessHistory("","","","!$1 <removed>\n") && next; + /^( ip ospf authentication-key) / && + ProcessHistory("","","","!$1 <removed>\n") && next; + /^( ip ospf message-digest-key \d+ md5) / && + 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 + /^set arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && + ProcessHistory("ARP","ipsort","$1","$_") && next; + /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ && + ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n") + && next; + # order logging statements + /^set logging server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("LOGGING","ipsort","$1","$_") && next; + # order name-server statements + /^set ip dns server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("NAMESERVER","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 (/^set snmp trap (\d+\.\d+\.\d+\.\d+) /) { + if (defined($ENV{'NOCOMMSTR'})) { + ProcessHistory("SNMPSERVERHOST","ipsort","$1","!set snmp trap $1 <removed>\n"); + } else { + ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); + } + next; + } + if (/^(set snmp community) (\S+) (\S+)/) { + if (defined($ENV{'NOCOMMSTR'})) { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 $2 <removed>\n"); + } else { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") + } + next; + } + # order tacacs server statements + /^set (tacacs) key / && + ProcessHistory("","","","!set $1 key <removed>\n") && next; + /^set tacacs server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("TAC","ipsort","$1","$_") && next; + # order clns host statements + /^clns host \S+ (\S+)/ && + ProcessHistory("CLNS","keysort","$1","$_") && next; + # order alias statements + /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next; + # delete ntp auth password + /^(ntp authentication-key \d+ md5) / && + ProcessHistory("","","","!$1 <removed>\n") && next; + # order ntp peers/servers + if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { + $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); + ProcessHistory("NTP","keysort",$sortkey,"$_"); + next; + } + # order ip host line statements + /^ip host line(\d+)/ && + ProcessHistory("IPHOST","numsort","$1","$_") && next; + # order ip nat source static statements + /^ip nat (\S+) source static (\S+)/ && + ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; + # order atm map-list statements + /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ && + ProcessHistory("ATM map-list","ipsort","$1","$_") && next; + # order ip rcmd lines + /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next; + + ProcessHistory("","","","$_"); + # end of config + if (/^end$/) { + $found_end = 1; + return(1); + } + } + return(0); +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + 'show version' => "ShowVersion", + 'show boot' => "ShowBoot", + 'show flash' => "ShowFlash", + 'dir bootflash:' => "DirSlotN", + 'dir slot0:' => "DirSlotN", + 'dir slot1:' => "DirSlotN", + 'show module' => "ShowModule", + 'write term' => "WriteTerm" +); +# keys() doesnt return things in the order entered and the order of the +# cmds is important (show version first and write term last). pita +@commands=( + "show version", + "show boot", + "show flash", + "dir bootflash:", + "dir slot0:", + "dir slot1:", + "show module", + "write term" +); +$cisco_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered if debugging +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + if (defined($ENV{NOPIPE})) { + system "clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; + } else { + open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n"; + } +} + +ProcessHistory("COMMENTS","keysort","B0","!\n"); +ProcessHistory("COMMENTS","keysort","F0","!\n"); +ProcessHistory("COMMENTS","keysort","G0","!\n"); +TOP: while(<INPUT>) { + tr/\015//d; + if (/> \(enable\) exit$/) { + $clean_run=1; + last; + } + if (/Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host clogin error: $_"); + print STDERR ("$host clogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/> \(enable\)\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); +} |