package iosxr; ## ## @PACKAGE@ @VERSION@ @copyright@ # # RANCID - Really Awesome New Cisco confIg Differ # # iosxr.pm - Cisco IOS-XR rancid procedures use 5.010; use strict 'vars'; use warnings; no warnings 'uninitialized'; require(Exporter); our @ISA = qw(Exporter); use rancid @VERSION@; our $proc; our $found_env; our $found_diag; our $found_version; our $config_register; # configuration register value our $type; # device model, from ShowVersion our $C0; # output formatting control our $E0; our $H0; our $I0; @ISA = qw(Exporter rancid main); #XXX @Exporter::EXPORT = qw($VERSION @commandtable %commands @commands); # load-time initialization sub import { 0; } # post-open(collection file) initialization sub init { $proc = ""; $found_env = 0; $found_diag = 0; $found_version = 0; $config_register = undef; # configuration register value # XXX $type = undef; # device model, from ShowVersion $C0 = 0; # output formatting control $E0 = 0; $H0 = 0; $I0 = 0; # add content lines and separators ProcessHistory("","","","!RANCID-CONTENT-TYPE: $devtype\n!\n"); ProcessHistory("COMMENTS","keysort","B0","!\n"); ProcessHistory("COMMENTS","keysort","D0","!\n"); ProcessHistory("COMMENTS","keysort","F0","!\n"); ProcessHistory("COMMENTS","keysort","G0","!\n"); 0; } # main loop of input of device output sub inloop { my($INPUT, $OUTPUT) = @_; my($cmd, $rval); TOP: while(<$INPUT>) { tr/\015//d; CMD: if (/[>#]\s?exit$/) { $clean_run = 1; last; } if (/^Error:/) { print STDOUT ("$host clogin error: $_"); print STDERR ("$host clogin error: $_") if ($debug); $clean_run = 0; last; } while (/[>#]\s*($cmds_regexp)\s*$/) { $cmd = $1; if (!defined($prompt)) { $prompt = ($_ =~ /^([^#]+#)/)[0]; $prompt =~ s/([][}{)(+\\])/\\$1/g; 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; } if (! defined(&{$commands{$cmd}})) { printf(STDERR "$host: undefined function - \"%s\"\n", $commands{$cmd}); $clean_run = 0; last TOP; } $rval = &{$commands{$cmd}}($INPUT, $OUTPUT, $cmd); delete($commands{$cmd}); if ($rval == -1) { $clean_run = 0; last TOP; } if (defined($prompt)) { if (/$prompt/) { goto CMD; } } } } } # This routine parses "admin show version" sub ShowVersion { my($INPUT, $OUTPUT, $cmd) = @_; my($slave, $slaveslot); print STDERR " In ShowVersion: $_" if ($debug); while (<$INPUT>) { tr/\015//d; if (/^$prompt/) { $found_version = 1; last}; next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(0) if ($found_version); # Only do this routine once return(-1) if (/command authorization failed/i); if (/^Slave in slot (\d+) is running/) { $slave = " Slave:"; $slaveslot = ", slot $1"; next; } /^(Cisco )?IOS .* Software,? \(([A-Za-z0-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; /^Serial Number:\s+(.*)$/ && ProcessHistory("COMMENTS","keysort","C1", "!$_") && 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+(?:\sseries)?)\s+(?:\(([^)]+)\)\s+processor|\(revision[^)]+\)).*\s+with (\S+k) bytes/i) { $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, 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 =~ /1200[48]\/(GRP|PRP)/ || $proc =~ /1201[26]\/(GRP|PRP)/) { $type = "12000"; } elsif ($proc =~ /1201[26]-8R\/(GRP|PRP)/) { $type = "12000"; } elsif ($proc =~ /1240[48]\/(GRP|PRP)/ || $proc =~ /1241[06]\/(GRP|PRP)/) { $type = "12400"; } elsif ($proc =~ /ASR9K/) { $_ = <$INPUT>; $type = $proc; if (/(ASR\S+)\s+(\SC)\s+Chassis/) { $proc = $1; } elsif (/(ASR\S+)\s+Chassis/) { $proc = $1; } elsif (/(ASR)\s+(9\d+)\s+.*\s+Chassis with/) { tr/\015//d; chomp; $proc = $_; } elsif (/(ASR)\s+(9\S+)\s+(\SC)\s+Chassis/) { $proc = "ASR-". $2; } elsif (/(ASR)\s+(9\S+)\s+Chassis/) { $proc = "ASR-". $2; } elsif (/(ASR\s+9922)/) { $proc = "ASR-9922"; } $_ = ""; } 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; } elsif (/^cisco (\S+(?:\sseries)?)\s+(?:\(([^)]*)\)\s+processor)/i) { $proc = $1; my($cpu) = $2; my($device) = "router"; print STDERR "TYPE = $type\n" if ($debug); ProcessHistory("COMMENTS","keysort","A1", "!Chassis type: $proc - a $proc $device\n"); if (defined($cpu) && length($cpu)) { ProcessHistory("COMMENTS","keysort","A3", "!CPU:$cpu\n"); } } /^(\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 (/^(\d+[kK]) bytes of (slot|disk)(\d)/i) { ProcessHistory("COMMENTS","keysort","B7", "!Memory: pcmcia $2$3 $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 (length($config_register) < 1); next; } } return(0); } # This routine parses "admin show diag". sub AdminShowDiag { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In AdminShowDiag: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); # skip blank lines /^$/ && next; # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); s/^NODE //; # wtf are these? next if (/(New Deviation|UDI_VID|Board State)/); # skip insertion time next if (/insertion time/i); # skip board h/w revision junk next if (/^(\s{2}board |\s{3,})/i); ProcessHistory("SLOT","","","!$_"); } ProcessHistory("SLOT","","","!\n"); return(0); } # This routine parses "admin show running". sub AdminShowRunning { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowRunning: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); # skip blank lines /^$/ && next; # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); /^building configuration/i && next; if (/^(\s*secret) / && $filter_pwds >= 2) { ProcessHistory("ASR","","","!$1 \n"); next; } ProcessHistory("ASR","","","!$_"); /^end$/ && last; } ProcessHistory("ASR","","","!\n"); return(0); } # This routine parses "show diag". sub ShowDiag { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowDiag: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); # skip blank lines /^$/ && next; # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); s/^NODE //; # wtf are these? next if (/(New Deviation|UDI_VID|Board State)/); ProcessHistory("SLOT","","","!$_"); } ProcessHistory("SLOT","","","!\n"); return(0); } # This routine parses "admin show hw-module fpd location all" and # "show hw-module fpd" (eXR/eXR-lite). sub ShowHWfpd { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowRunning: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); # skip blank lines /^$/ && next; # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); /^notes:/i && last; # remove trailing WS s/\s+$/\n/; ProcessHistory("FPD","","","!$_"); } ProcessHistory("FPD","","","!\n"); return(0); } # This routine parses "show redundancy" sub ShowRedundancy { my($INPUT, $OUTPUT, $cmd) = @_; my($slave, $slaveslot); print STDERR " In ShowRedundancy: $_" if ($debug); TOP: while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS # filter reload/boot info if (/^reload and boot info/i) { while (<$INPUT>) { tr/\015//d; last TOP if (/^$prompt/); last if (/^\s*$/); } } ProcessHistory("COMMENTS","keysort","F3", "!$_"); } ProcessHistory("COMMENTS","keysort","F3", "!\n"); return(0); } # This routine parses "show install active" sub ShowInstallActive { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowInstallActive: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/^\s*\^\s*$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); return(-1) if (/install director is not up or ready/i);# temp error return(-1) if (/failed to output install information /i);# temp error # FPD upgrade in progress on some hardware, reload/configuration change # on those is not recommended as it might cause HW programming failure # and result in RMA of the hardware. # FPD upgrade has ended. next if (/fpd upgrade has ended/i || /fpd upgrade in progress /i || /might cause hw programming failure/i || /result in rma of the hardware/i); # useless FPD messages ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next; } ProcessHistory("COMMENTS","keysort","F5","!\n"); return(0); } # This routine parses "show memory summary" sub ShowMemorySum { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowMemorySum: $_" if ($debug); # RP/0/RSP0/CPU0:r00.lab#show memory summary # # node: node0_RSP0_CPU0 # ------------------------------------------------------------------ # # Physical Memory: 27426M total (22146M available) # Application Memory : 27426M (21819M available) # Image: 4M (bootram: 0M) # Reserved: 0M, IOMem: 0M, flashfsys: 0M # Total shared window: 140M while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(-1) if (/command authorization failed/i); /physical memory:\s+(\d+[GMKB])\s+total/i && ProcessHistory("COMMENTS","keysort","B1", "!Memory: main $1\n") && next; } return(0); } # This routine parses "admin show env all" sub ShowEnv { my($INPUT, $OUTPUT, $cmd) = @_; # 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}; # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); next if (/^(\s*|\s*$cmd\s*)$/); next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(0) if ($found_env); # Only do this routine once return(-1) if (/command authorization failed/i); if (!defined($E0)) { $E0 = 1; ProcessHistory("COMMENTS","keysort","E0","!\n"); } if (/power budget summary for rack/i) { ProcessHistory("COMMENTS","keysort","E1","!Power: $_"); while (<$INPUT>) { tr/\015//d; goto OUT if (/^$prompt/); last if (/^altitude information/i); ProcessHistory("COMMENTS","keysort","E1","!Power: $_"); } next; } if (/power shelf \d+:/i) { my($sep) = 0; ProcessHistory("COMMENTS","keysort","E1","!Power: $_"); while (<$INPUT>) { tr/\015//d; goto OUT if (/^$prompt/); last if (/^altitude information/i); last if (/^=+$/i && ($sep > 1)); $sep++ if (/^=+$/i); if (/^(\s+\S+\s+\S+-(?:AC|DC)\s+)(\S+\s+\S+\s+\S+\s+\S+)(\s+.*)/) { $_ = sprintf("%s%-". length($2) ."s%s\n", $1, "", $3); } ProcessHistory("COMMENTS","keysort","E1","!Power: $_"); } 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; } OUT: ProcessHistory("COMMENTS","keysort","E3","!\n"); return(0); } # This routine parses "dir /all ((disk|slot)N|bootflash|nvram):" sub DirSlotN { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In DirSlotN: $_" if ($debug); my($dev) = (/\s([^\s]+):/); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if /^\s*\^\s*$/; return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/(No such device|Error Sending Request)/i); return(1) if (/: path doesnot exists/i); # NCS return(1) if (/: Path does not exist/i); # NCS return(1) if (/\%Error: No such file or directory/); return(1) if (/\%Error: No route to host/); return(1) if (/No space information available/); # Corrupt flash /\%Error calling getdents / && ProcessHistory("FLASH","","","!Flash: $dev: $_") && next; return(-1) if (/\%Error calling/); return(-1) if (/(: device being squeezed|ATA_Status time out)/i); # busy return(-1) if (/\%Error opening \S+:\S+ \(Device or resource busy\)/i); return(-1) if (/command authorization failed/i); return(1) if (/(Open device \S+ failed|Error opening \S+:)/); # Filter dhcp database if (/dhcp_[^. ]*\.txt/) { next; } # Filter debugging file dlbg.txt & dlbg.txt-1 only on ASR9k w/ XR if ($proc =~ /ASR9K/ && /dlbg\.txt/) { next; } # filter frequently changing files from IOX bootflash, hardiska, # and nvram if ($dev =~ /(bootflash|disk[0-9]|harddisk|nvram)/) { if (/\s(\.python-history|aaa|\.bash_history|.sppdc)\s*$/ || /\s(ce_switch.log\S*|cisco_support|errmsg_cont)\s*$/ || /\s(genstr_cont|temp_cont|temp_cont|temp_static_data)\s*$/ || /\s(uptime_cont|volt_cont|volt_hist)\s*$/) { # change # 57 -rw- 23100 volt_cont # 614788 drwx 4096 Fri Aug 20 12:06:25 2010 temp_cont # to # -rw- volt_cont # drwx temp_cont if (/\s*\d+\s+(\S+\s+)(\d+)(\s+)()(\s+)/) { my($a, $sz, $c, $dt, $d, $rem) = ($1, $2, $3, $4, $5, $'); my($szl) = length($sz); my($fmt) = "%s%-". $szl ."s%s%s%s%s"; $_ = sprintf($fmt, $c, $dt, $d, $rem); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $_"); next; } elsif (/\s*\d+\s+(\S+\s+\d+\s+)(\d+\s+\w+\s+\d+\s+\d+:\d+)/ || /\s*\d+\s+(\S+\s+\d+\s+)(\d+\s+\w+\s+\d+\s+\d{4})/) { # XR >= 6.3; dir disk0:, but harddisk: is diff format. wtf # drop fileno size, & date. # " 8002 drwxr-xr-x 2 4096 Jan 17 15:27 np" my($perm, $dt, $rem) = ($1, $2, $'); my($dtl) = length($dt); my($fmt) = "%s%-". $dtl ."s%s"; $_ = sprintf($fmt, $perm, "", $rem); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $_"); next; } elsif (/\s*\d+\s+(\S+\s+)(\d+)(\s+)(\w+ \w+\s+\d+ \d+:\d+:\d+ \d+)/) { my($b, $sz, $c, $dt, $rem) = ($1, $2, $3, $4, $'); my($szl, $dtl) = (length($sz), length($dt)); my($fmt) = "%s%-". $szl ."s%s%-". $dtl ."s%s"; $_ = sprintf($fmt, $b, "", $c, "", $rem); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $_"); next; } } else { if (/\s*\d+\s+(\S+\s+)(\d+)(\s+)(\s+)/) { my($sz, $c, $dt, $d, $rem) = ($1, $2, $3, $4, $'); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $sz$c$dt$d$rem"); next; } elsif (/\s*\d+\s+(\S+\s+\d+\s+)(\d+\s+\w+\s+\d+\s+\d+:\d+)/ || /\s*\d+\s+(\S+\s+\d+\s+)(\d+\s+\w+\s+\d+\s+\d{4})/) { # XR >= 6.3; dir disk0:, but harddisk: is diff format. wtf my($perm, $dt, $rem) = ($1, $2, $'); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $perm$dt$rem"); next; } elsif (/\s*\d+\s+(\S+\s+)(\d+)(\s+)(\w+ \w+\s+\d+ \d+:\d+:\d+ \d+)/) { # XR < 6.3 & etc. my($b, $sz, $c, $dt, $rem) = ($1, $2, $3, $4, $'); ProcessHistory("FLASH","keysort",$rem,"!Flash: $dev: $b$sz$c$dt$rem"); next; } } } # XR: 822083584 bytes total (821081600 bytes free) # eXR: 990484 kbytes total (813208 kbytes free) if (/^\s*(\d+ k?bytes) total\s+\((\d+ k?bytes) free\)/i) { ProcessHistory("FLASH","","","!Flash: $dev: " . diskszsummary($1, $2) . "\n"); next; } ProcessHistory("FLASH","","","!Flash: $dev: $_"); } ProcessHistory("","","","!\n"); return(0); } # This routine parses "admin show variables boot" sub ShowBootVar { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowBootVar: $_" if ($debug); while (<$INPUT>) { # delete non-ascii chars, except new line tr/ -~\n//cd; last if (/^$prompt/); next if (/\s*$cmd\s*$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/^\s*\^\s*$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/Ambiguous command/i); return(1) if (/(Open device \S+ failed|Error opening \S+:)/); return(-1) if (/command authorization failed/i); # skip blank lines next if (/^\s*$/); # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); ProcessHistory("COMMENTS", "keysort", "C30", "! $_"); } ProcessHistory("COMMENTS", "keysort", "C39", "!\n"); return(0); } # This routine parses "show controllers" sub ShowContAll { my($INPUT, $OUTPUT, $cmd) = @_; my($INT); print STDERR " In ShowContAll: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS # return(1) if ($type =~ /^(12[40]|7[05])/); return(-1) if (/command authorization failed/i); 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 debug" sub ShowDebug { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowDebug: $_" if ($debug); my($lines) = 0; while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); /^No matching debug flags set$/ && next; /^No debug flags set$/ && next; ProcessHistory("COMMENTS","keysort","J1","!DEBUG: $_"); $lines++; } if ($lines) { ProcessHistory("COMMENTS","keysort","J0","!\n"); } return(0); } # This routine parses "admin show install active" sub ShowInstallSummary { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowInstallSummary: $_" if ($debug); while (<$INPUT>) { # delete non-ascii chars, except new line tr/ -~\n//cd; last if (/^$prompt/); next if (/\s*$cmd\s*$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/^\s*\^\s*$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/Ambiguous command/i); return(1) if (/(Open device \S+ failed|Error opening \S+:)/); return(-1) if (/command authorization failed/i); return(-1) if (/inventory summary cannot be output/i); # temp error return(-1) if (/currently affected by install operation/i);# temp error return(-1) if (/install director is not up or ready/i);# temp error # skip blank lines next if (/^\s*$/); # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); ProcessHistory("COMMENTS", "keysort", "C15", "!Image: $_"); } ProcessHistory("COMMENTS", "keysort", "C10", "!\n"); ProcessHistory("COMMENTS", "keysort", "C19", "!\n"); return(0); } # This routine parses "show inventory". sub ShowInventory { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowInventory: $_" if ($debug); while (<$INPUT>) { # delete non-ascii chars, except new line tr/ -~\n//cd; return if (/^\s*\^$/); last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(-1) if (/command authorization failed/i); # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); # remove spaces after quotes s/\"\s+/\"/g; if (/^(name: "[^"]*",) (descr: "[^"]+")/i) { ProcessHistory("INVENTORY","","", sprintf("!%-30s %s\n", $1, $2)); next; } # XR flavor: # NAME: "module 0/RSP0/CPU0", DESCR: "ASR9K Route Switch Processor with 880G/slot Fabric and 32GB" # PID: A9K-RSP880-SE, VID: V01, SN: FOC1911VC2S # # eXR flavor: # NAME: "0/RSP0-Motherboard", DESCR: "Motherboard Module" # PID: N/A , VID: N/A , SN: N/A # split PID/VID/SN line if (/^ ?PID: (\S*)\s*, VID: (\S*)\s*,\s* SN: (\S*)\s*$/) { my($pid,$vid,$sn) = ($1, $2, $3); my($entries) = ""; # filter , "0x" and "N/A" lines if ($pid !~ /^(|0x|N\/A)$/) { $entries .= "!PID: $pid\n"; } if ($vid !~ /^(|0x|N\/A)$/) { $entries .= "!VID: $vid\n"; } if ($sn !~ /^(|0x|N\/A)$/) { $entries .= "!SN: $sn\n"; } ProcessHistory("INVENTORY","","", "$entries"); next; } ProcessHistory("INVENTORY","","","!$_"); } ProcessHistory("INVENTORY","","","!\n"); return(0); } # This routine parses "admin show license" & "admin show license udi" sub ShowLicense { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowLicense: $_" if ($debug); while (<$INPUT>) { tr/\015//d; # delete non-ascii chars, except new line last if (/^$prompt/); next if (/\s*$cmd\s*$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (/^\s*\^\s*$/); next if (/^-+\^$/i); # NCS cmd-line error pointer return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); next if (/^(\e\[.\d+h)?sysadmin-vm:[^#]+# /i); # NCS return(1) if (/^syntax error: element does not exist$/i); # NCS return(1) if (/^syntax error: unknown argument$/i); # NCS return(1) if (/Ambiguous command/i); return(1) if (/(Open device \S+ failed|Error opening \S+:)/); return(-1) if (/command authorization failed/i); # show lic on o/s w/o licenses s/info\s*: //; # file feature status line (ASR9k, others?) next if (/\s*status: /i); # skip blank lines next if (/^\s*$/); # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); # filter the BS from license broker next if (/(renewal attempt|communication attempt):/i); next if (/next registration attempt:/i); # timestamp next if (/(period used:|requested time:)/i); # show lic feature if (/(^\s*(evaluation )?period (left|remaining):\s*)\d+/i) { ProcessHistory("COMMENTS","keysort","LICENSE","! $1\n"); next; } # drop license counts next if (/license usage:/i); if (/(.*)count status/i) { my($hdr) = $1; my($len) = length($hdr); $hdr =~ s/\s*$//; ProcessHistory("COMMENTS", "keysort", "C20", "! $hdr\n"); while (<$INPUT>) { tr/\015//d; return(0) if (/^$prompt/); s/^(.{1,$len}).*/$1/; ProcessHistory("COMMENTS", "keysort", "C20", "! $_"); } next; } ProcessHistory("COMMENTS", "keysort", "C20", "! $_"); } ProcessHistory("COMMENTS", "keysort", "C20", "!\n"); return(0); } # This routine parses "show rpl maximum" sub ShowRPL { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowRPL: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if /^\s*\^\s*$/; return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/Ambiguous command/i); return(-1) if (/command authorization failed/i); ProcessHistory("COMMENTS","keysort","RPLMAX","! $_"); } ProcessHistory("COMMENTS","keysort","RPLMAX","!\n"); return(0); } # This routine parses "show vlan" sub ShowVLAN { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowVLAN: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if /^\s*\^\s*$/; return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/Ambiguous command/i); return(-1) if (/command authorization failed/i); ProcessHistory("COMMENTS","keysort","IO","!VLAN: $_"); } ProcessHistory("COMMENTS","keysort","IO","!\n"); return(0); } # This routine processes a "write term" sub WriteTerm { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In WriteTerm: $_" if ($debug); my($lineauto,$comment,$linecnt) = (0,0,0); while (<$INPUT>) { REPEAT: tr/\015//d; last if (/^$prompt/); # filter the bloody cmd-line timestamp next if (/^\w{3} \w{3,4} {1,3}\d{1,2} {1,2}\d{1,2}:\d+:\d+\.\d+ \S+$/); return(1) if (!$linecnt && /^\s+\^\s*$/); return(1) if (/Line has invalid autocommand /); return(1) if (/(Invalid (input|command) detected|Type help or )/i); return(1) if (/^(-+\^|syntax error: unknown argument)$/i); # NCS return(1) if (/\%Error: No such file or directory/); return(0) if ($found_end); # Only do this routine once return(-1) if (/command authorization failed/i); return(-1) if (/% ?configuration buffer full/i); /^! no configuration change since last restart/i && next; # skip emtpy lines at the beginning if (!$linecnt && /^\s*$/) { next; } if (!$linecnt && defined($config_register)) { ProcessHistory("","","", "!\nconfig-register $config_register\n"); } # NCS junk next if (/^\S+ connected from 127.0.0.1 using console /); next if (/# terminal length 0$/); /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked /% Configuration buffer full, / && return(-1); # buffer is in use $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; } tr/\015//d; } # some versions have other crap mixed in with the bits in the # block above /^! (Last configuration|NVRAM config last)/ && next; # and for the ASA /^: (Written by \S+ at|Saved)/ && next; # skip consecutive comment lines to avoid oscillating extra comment # line on some access servers. grrr. if (/^!\s*$/) { 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 \n"); next; } if (/^(enable secret) / && $filter_pwds >= 2) { ProcessHistory("ENABLE","","","!$1 \n"); next; } if (/^username (\S+)(\s.*)? secret /) { if ($filter_pwds >= 2) { ProcessHistory("USER","keysort","$1", "!username $1$2 secret \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 \n"); } elsif ($filter_pwds >= 1 && $4 ne "5"){ ProcessHistory("USER","keysort","$1", "!username $1$2 password \n"); } else { ProcessHistory("USER","keysort","$1","$_"); } next; } if (/^( set session-key (in|out)bound ah \d+ )/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1\n"); next; } if (/^( set session-key (in|out)bound esp \d+ (authenticator|cypher) )/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1\n"); next; } if (/^(\s*)password / && $filter_pwds >= 1) { ProcessHistory("LINE-PASS","","","!$1password \n"); next; } if (/^(\s*)secret / && $filter_pwds >= 2) { ProcessHistory("LINE-PASS","","","!$1secret \n"); next; } if (/^\s*neighbor (\S*) password / && $filter_pwds >= 1) { ProcessHistory("","","","! neighbor $1 password \n"); next; } if (/^(ppp .* password) 7 .*/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } if (/^(ip ftp password) / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } if (/^( ip ospf authentication-key) / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } # isis passwords appear to be completely plain-text if (/^\s+isis password (\S+)( .*)?/ && $filter_pwds >= 1) { ProcessHistory("","","","!isis password $2\n"); next; } if (/^\s+(domain-password|area-password) (\S+)( .*)?/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 $3\n"); next; } # this is reversable, despite 'md5' in the cmd if (/^( ip ospf message-digest-key \d+ md5) / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \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 \n"); next; } if (/^((crypto )?isakmp key) \S+ / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 $'"); next; } # filter HSRP passwords if (/^(\s+standby \d+ authentication) / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } # this appears in "measurement/sla" images if (/^(\s+key-string \d?)/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } if (/^( l2tp tunnel \S+ password)/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \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 \n"); } else { ProcessHistory("USER","keysort","$2","$_"); } next; } # ASA/PIX keys in more system:running-config if (/^( pre-shared-key | key |failover key ).*/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 $'"); next; } if (/(\s+ldap-login-password )\S+(.*)/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 $'"); next; } # if (/^( cable shared-secret )/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \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 (! /^(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","$aclsort","$3","$_") && next; # order extended access-lists /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next; /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next; /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && ProcessHistory("EACL $1 $2","$aclsort","0.0.0.0","$_") && next; # sort ipv{4,6} access-lists if ($aclfilterseq && /^ipv(4|6) access-list (\S+)\s*$/) { my($nlri, $key) = ($1, $2); my($seq, $cmd); ProcessHistory("ACL $nlri $key","","","$_"); while (<$INPUT>) { tr/\015//d; goto REPEAT if (/^$prompt/ || !/^(\s|\d|!)/); if (/^\s*!/) { ProcessHistory("ACL $nlri $key !", "", "", "$_"); next; } # ipv4 access-list name # remark NTP # deny ipv4 host 224.0.1.1 any # deny ipv4 239.0.0.0 0.255.255.255 any # permit udp any eq 123 any # permit ipv4 nnn.nnn.nnn.nnn/nn any # permit nnn.nnn.nnn.nnn/nn # ipv6 access-list name # permit ipv6 host 2001:nnnn::nnnn any # permit ipv6 2001:nnn::/nnn any # permit 2001:nnnn::/64 any # permit udp any eq 123 any my($seq, $cmd, $resid) = ($_ =~ /^\s*(\d+) (\w+) (.+)/); if ($cmd =~ /(permit|deny)/) { my($ip); my(@w) = ($resid =~ /(\S+) (\S+) (\S+\s)?(.+)/); for (my($i) = 0; $i < $#w; $i++) { if ($w[$i] eq "any") { if ($nlri eq "ipv4") { $ip = "255.255.255.255/32"; } else { $ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"; } last; } elsif ($w[$i] =~ /^[:0-9]/ || $2[$i] =~ /^[a-fA-F]{1,4}:/) { $ip = $w[$i]; $ip =~ s/\s+$//; # trim trailing WS last; } } ProcessHistory("ACL $nlri $key $cmd", "$aclsort", "$ip", " $cmd $resid\n"); } else { ProcessHistory("ACL $nlri $key $cmd", "", "", " $cmd $resid\n"); } } } # order arp lists /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && ProcessHistory("ARP","$aclsort","$1","$_") && next; /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(.*)/ && ProcessHistory("PACL $1 $3","$aclsort","$4","ip prefix-list $1 $3 $4$5\n") && next; if ($aclfilterseq) { /^ip(v4|v6) prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\S+)(.*)/ && ProcessHistory("PACL $2 $4","$aclsort","$5","ip$1 prefix-list $2 $4 $5$6\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 if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) { if ($filter_commstr) { 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(' ', ("", join(' ',@tokens))); last; } } ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n"); } else { ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); } next; } if (/^(snmp-server community) (\S+)/) { if ($filter_commstr) { ProcessHistory("SNMPSERVERCOMM","keysort","$_", "!$1 $'") && next; } else { ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next; } } # prune tacacs/radius server keys if (/^((tacacs|radius)-server\s(\w*[-\s(\s\S+])*\s?key) (\d )?\w+/ && $filter_pwds >= 1) { ProcessHistory("","","","!$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 - this md5 is a reversable too if (/^(ntp authentication-key \d+ md5) / && $filter_pwds >= 1) { ProcessHistory("","","","!$1 \n"); next; } # order ntp peers/servers if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { my($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 \n") && next; if (/^syscon password (\S*)/ && $filter_pwds >= 1) { ProcessHistory("","","","!syscon password \n"); next; } /^ *Cryptochecksum:/ && next; # catch anything that wasnt matched above. ProcessHistory("","","","$_"); # end of config. if (/^end$/) { $found_end = 1; return(0); } } return(0); } 1;