package nxos; ## ## @PACKAGE@ @VERSION@ @copyright@ # # RANCID - Really Awesome New Cisco confIg Differ # # nxos.pm - Cisco NX-OS 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 $type; # device model, from ShowVersion our $C0; # output formatting control our $E0; our $H0; our $DO_SHOW_VLAN; @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 = ""; $type = undef; # device model, from ShowVersion $C0 = 0; # output formatting control $E0 = 0; $H0 = 0; $DO_SHOW_VLAN = 1; # 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; if (/[>#]\s?exit$/) { print STDERR ("$host: found exit\n") if ($debug); $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; print STDERR ("$host: $cmd failed: $rval\n") if ($debug); last TOP; } if (/[>#]\s?exit$/) { print STDERR ("$host: found exit\n") if ($debug); $clean_run = 1; last TOP; } } } } # This routine parses "show version" sub ShowVersion { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowVersion: $_" 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 )/; return(-1) if (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); if (/^Cisco (Nexus|Storage Area Networking) Operating System/) { $type = "NXOS";} if (/^Software$/) { while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^\s*$cmd\s*$/); if (/^$/) { goto EndSoftware; } /\s*([^:]*:)\s*(.*)$/ && ProcessHistory("COMMENTS","keysort","C1", "!Software: $1 $2\n") && next; } } EndSoftware: if (/^Hardware$/) { while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^\s*$cmd\s*$/); if (/^\s*cisco (Nexus[ \d]+) /) { # cisco Nexus7000 C7010 (10 Slot) Chassis ("Supervisor module-1X") # cisco Nexus7000 C7018 (18 Slot) Chassis ("Supervisor module-1X") # cisco Nexus5548 Chassis ("O2 32X10GE/Modular Supervisor") # cisco Nexus 4000 Chassis ("20x10GE/supervisor") $proc = $1; } if (/^$/) { goto EndHardware; } if (/^\s*(.*) CPU\s*with (\d*) kB(.*)$/) { my($tmp) = int($2 / 1024); ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1 CPU with $tmp MB$3\n"); next; } if (/^\s*(.*)\s*with (\d*) kB(.*)$/) { my($tmp) = int($2 / 1024); ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1with $tmp MB$3\n"); next; } /^\s*(.*)$/ && ProcessHistory("COMMENTS","keysort","A2", "!Hardware: $1\n") && next; } } EndHardware: if (/^\s+(bootflash|slot0):\s+(\d+) kB(.*)$/) { my($tmp) = int($2 / 1024); ProcessHistory("COMMENTS","keysort","B1", "!Memory: $1: $tmp MB$3\n"); next; } } print STDERR "TYPE = $type\n" if ($debug); # XXX $proc is never set ProcessHistory("COMMENTS","keysort","A1", "!Chassis type: $proc - a $type router\n"); ProcessHistory("COMMENTS","keysort","B0", "!\n"); ProcessHistory("COMMENTS","keysort","C0", "!\n"); ProcessHistory("COMMENTS","","", "!\n"); return(0); } # This routine parses "show version build-info" sub ShowVersionBuild { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowVersionBuild: $_" 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 )/; return(1) if (/\% Invalid command at /); return(1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); /^Built By / && ProcessHistory("COMMENTS","","", "!Build: $_"); /^On Date / && ProcessHistory("COMMENTS","","", "!Build: $_"); /^From Tree / && ProcessHistory("COMMENTS","","", "!Build: $_"); /^Base Tag / && ProcessHistory("COMMENTS","","", "!Build: $_"); /^Release for / && ProcessHistory("COMMENTS","","", "!Build: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show license *" sub ShowLicense { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowLicense: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); return(1) if /(Invalid input detected|Type help or )/; return(1) if (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); /^-+$/ && next; # Skip lines of all dashes. s/ Grace .+$/ Grace/; # Drop anything after Grace. ProcessHistory("COMMENTS","","", "!LIC: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show system redundancy status" sub ShowRedundancy { my($INPUT, $OUTPUT, $cmd) = @_; 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 )/; return(1) if (/\% Invalid command at /); return(1) if (/.* command is not support/i); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); s/ +$//; # Drop trailing ' ' ProcessHistory("COMMENTS","","","!Red: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show environment" sub ShowEnv { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowEnv: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); next if (/^\s*\^\s*$/); return(1) if /Line has invalid autocommand /; return(1) if /(Invalid input detected|Type help or )/; return(1) if (/\% Invalid command at /); return(1) if (/ .* command is not support/i); return(1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); s/ +$//; # Drop trailing ' ' next if (/Fan Zone Speed:/); if (/(control temperature|monitor temperature)/i) { ProcessHistory("COMMENTS","","","!Env: $_"); while (<$INPUT>) { tr/\015//d; goto EndShowEnv if (/^$prompt/); if (/(.*\s+\d+\s+\d+\s+)(\d+)(.*$)/) { $_ = sprintf("%s%-". length($2)."s%s\n", $1, "", $3); } ProcessHistory("COMMENTS","","","!Env: $_"); last if (/^\s*$/); } next; } ProcessHistory("COMMENTS","","","!Env: $_"); } EndShowEnv: ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show environment temperature" sub ShowEnvTemp { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowEnvTemp: $_" 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 )/; return(1) if (/No token match at /); # 1000v return(1) if (/\% Invalid command at /);# 1000v has no support return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); s/ +$//; # Drop trailing spaces # Cut out CurTemp - drop the 2nd to last field. #-------------------------------------------------------------------- #Module Sensor MajorThresh MinorThres CurTemp Status # (Celsius) (Celsius) (Celsius) #5 Outlet1 (s1) 125 125 33 Ok #5 QEng1Sn1(s10) 115 105 39 Ok if (/(control temperature|monitor temperature)/i) { ProcessHistory("COMMENTS","","","!Env: $_"); while (<$INPUT>) { tr/\015//d; goto EndShowEnvTemp if (/^$prompt/); if (/(.*\s+\d+\s+\d+\s+)(\d+)(.*$)/) { $_ = sprintf("%s%-". length($2)."s%s\n", $1, "", $3); } ProcessHistory("COMMENTS","","","!Env: $_"); last if (/^\s*$/); } next; } else { next if (/INTAKE/); next if (/ASIC/); s/^(.+\s)(\S+\s+)(\S+\s*)$/$1$3/; s/ +$//; # Drop trailing ' ' ProcessHistory("COMMENTS","","","!Env: $_"); } } EndShowEnvTemp: ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show environment power" sub ShowEnvPower { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowEnvPower: $_" if ($debug); while (<$INPUT>) { tr/\015//d; last if (/^$prompt/); next if (/^(\s*|\s*$cmd\s*)$/); next if (/^\s*\^\s*$/); return(1) if /Line has invalid autocommand /; return(1) if /(Invalid input detected|Type help or )/; return(1) if (/\% Invalid command at /); return(1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); # Filter Actual Output/Draw. #Power Actual Total #Supply Model Output Capacity Status # (Watts ) (Watts ) #------- ------------------- ----------- ----------- -------------- #1 ------------ 0 W 0 W Absent #3 749 W 5480 W Ok # Actual Power #Module Model Draw Allocated Status # (Watts ) (Watts ) #------- ------------------- ----------- ----------- -------------- #2 NURBURGRING N/A 573 W Powered-Up #fan1 N/A 720 W Powered-Up # # ELSE # # nexus# sh environment power # Power Supply: # Voltage: 12 Volts # Power Actual Actual Total # Supply Model Output Input Capacity Status # (Watts ) (Watts ) (Watts ) # ------- ------------------- ---------- ---------- ---------- # -------------- # 1 N9K-PAC-650W-B 65 W 76 W 649 W Ok # 2 N9K-PAC-650W-B 70 W 84 W 649 W Ok # # # Power Usage Summary: # -------------------- # Power Supply redundancy mode (configured) PS-Redundant # Power Supply redundancy mode (operational) PS-Redundant # # Total Power Capacity (based on configured mode) 649.92 W # Total Grid-A (first half of PS slots) Power Capacity 649.92 W # Total Grid-B (second half of PS slots) Power Capacity 649.92 W # Total Power of all Inputs (cumulative) 1299.84 W # Total Power Output (actual draw) 136.00 W # Total Power Input (actual draw) 161.00 W # Total Power Allocated (budget) N/A # Total Power Available for additional modules N/A # # nexus# if (/(.* +)(\d+ W +\d+ W)( +\d+ W.+)/) { $_ = sprintf("%s%-". length($2)."s%s\n", $1, "", $3); } elsif (/(.* +)(\d+(\.\d+)? W)( +\d+(\.\d+)? W.+)/) { $_ = sprintf("%s%-". length($2)."s%s\n", $1, "", $4); } /actual draw/ && next; # Drop changing total power output. s/ +$//; # Drop trailing ' ' ProcessHistory("COMMENTS","","","!Env: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show boot" sub ShowBoot { my($INPUT, $OUTPUT, $cmd) = @_; 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 (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); s/ variable = / = /; ProcessHistory("COMMENTS","","","!Variable: $_"); } ProcessHistory("COMMENTS","","","!\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($free); my($dev) = (/\s([^\s]+):/); 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 (/\% Invalid command at /); return(1) if /(No such device|Error Sending Request)/i; return(1) if /No such file or directory/; return(1) if /No space information available/; return(1) if / is either not present or not formatted/; return(-1) if /\%Error calling/; return(-1) if /(: device being squeezed|ATA_Status time out)/i; # busy return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); return(1) if /(Open device \S+ failed|Error opening \S+:)/; # Drop ee.log /\s+ee\.log(?:\..*)?$/ && next; # Drop bootvar_debug log files /\s+bootvar_debug\./ && next; # Drop accounting.log* /\s+accounting.log.*/ && next; # Drop vtp_debug.log and vtp_debug_old.log CDETS bug CSCuy87611 /\s+vtp_debug(_old)?\.log$/ && next; # Drop bcm_mem_lock_trace.log /\s+bcm_mem_lock_trace\.log$/ && next; next if (/BufferMonitor-1HourData/); if (/( debug_logs| log)\/$/) { # change # 8192 Jan 08 14:05:05 2015 log/ # to # log/ if (/(\s*\d+\s+)(\S+ \d+\s+\d+:\d+:\d+ \d+)(.*)/) { my($a, $dt, $rem) = ($1, $2, $3); my($dtl) = length($dt); my($fmt) = "%s%-". $dtl ."s%s\n"; $_ = sprintf($fmt, $a, "", $rem); } } if (/^\s*(\d+) bytes free/i) { $free = $1; next; } elsif (/^\s*(\d+) bytes used/i) { next; } elsif (/^\s*(\d+) bytes total/i) { $_ = diskszsummary($1, $free, undef) . "\n"; } ProcessHistory("COMMENTS","","","!Flash: $dev: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show module". sub ShowModule { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowModule: $_" if ($debug); while (<$INPUT>) { tr/\015//d; return if (/^\s*\^$/); last if (/online diag status/i); last if (/^$prompt/); next if (/^\s*$cmd\s*$/); return(1) if (/\% Invalid command at /); return(1) if (/\% Invalid number at /); return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); s/(.*) \*$/$1/; # Drop a trailing '*' /^\* this terminal session/ && next; s/ +$//; # Drop trailing ' ' # filter fluctuating WWNs if (/\s+World-Wide-Name.*/i) { ProcessHistory("COMMENTS","","","!Mod: $_"); while (<$INPUT>) { tr/\015//d; goto EndShowModule if (/^$prompt/); last if (/^\s*$/); if (/^(\d+\s+\S+\s+\S+)\s+.*$/) { $_ = sprintf("%s\n", $1); } ProcessHistory("COMMENTS","","","!Mod: $_"); } } ProcessHistory("COMMENTS","","","!Mod: $_"); } EndShowModule: ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show interface transceiver". sub ShowIntTransceiver { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowtTransceiver: $_" 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 (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); # filter out oscillating data from transceivers next if (/(Temperature|Current|Power|Voltage)\s+:/); ProcessHistory("COMMENTS","","","!$_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show inventory". sub ShowInventory { my($INPUT, $OUTPUT, $cmd) = @_; 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 (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); if (/^(NAME: "[^"]*",)\s+(DESCR: "[^"]+")/) { ProcessHistory("COMMENTS","","", sprintf("!%-30s %s\n", $1, $2)); next; } # split PID/VID/SN line if (/^PID: (\S*)\s*,\s+VID: (\S*)\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("COMMENTS","","", "$entries"); next; } # split broken PID/VID/SN lines. if (/^PID: (\S*)\s*,\s+VID: (\S*)\s*$/) { my($entries) = ""; $entries .= "!PID: $1\n" if ($1); $entries .= "!VID: $2\n" if ($2); <$INPUT>; tr/\015//d; /^\s*,\s+SN: (\S*)\s*$/; $entries .= "!SN: $1\n" if ($1); ProcessHistory("COMMENTS","","", "$entries"); next; } ProcessHistory("COMMENTS","","","!$_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show vtp status" sub ShowVTP { my($INPUT, $OUTPUT, $cmd) = @_; 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 (/\% Invalid command at /); return(1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); 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}//; } # Nexus 5k and 1000v do not support vtp if (!/^VTP Operating Mode\s+:\s+(Transparent|Server)/) { $DO_SHOW_VLAN = 0; } ProcessHistory("COMMENTS","","","!VTP: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show vlan" sub ShowVLAN { my($INPUT, $OUTPUT, $cmd) = @_; 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 (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(1) if /Ambiguous command/i; return(-1) if (/\% Permission denied/); 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","","","!VLAN: $_"); } ProcessHistory("COMMENTS","","","!\n"); 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*)$/); return(1) if /Line has invalid autocommand /; return(1) if /(Invalid input detected|Type help or )/; return(-1) if (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/command authorization failed/i); return(-1) if (/could not retrieve info/i); # XXX return(-1) if (/\% Permission denied/); # NX 5000 bug? "show debug" generates # "Permission denied" when using command authorization. -Per-Olof Olsson next if (/\% Permission denied/); /^No matching debug flags set$/ && next; /^No debug flags set$/ && next; ProcessHistory("COMMENTS","","","!DEBUG: $_"); $lines++; } if ($lines) { ProcessHistory("COMMENTS","","","!\n"); } return(0); } # This routine parses "show cores" sub ShowCores { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowCores: $_" 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 )/; return(1) if (/\% Invalid command at /); return(1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); ProcessHistory("COMMENTS","","","!CORES: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show fex" and "show module fex" sub ShowFex { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowFex: $_" 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 (/\% Invalid command at /); return(1) if (/% Invalid number at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); ProcessHistory("COMMENTS","","","!FEX: $_"); } ProcessHistory("COMMENTS","","","!\n"); return(0); } # This routine parses "show processes log" sub ShowProcLog { my($INPUT, $OUTPUT, $cmd) = @_; print STDERR " In ShowProcLog: $_" 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 )/; return(1) if (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); ProcessHistory("COMMENTS","","","!PROC_LOGS: $_"); } ProcessHistory("COMMENTS","","","!\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/); return(1) if /Line has invalid autocommand /; return(1) if (/(Invalid input detected|Type help or )/i); return(-1) if (/\% Invalid command at /); return(-1) if (/No token match at /); # 1000v return(-1) if (/\% Permission denied/); return(-1) if (/command authorization failed/i); return(0) if ($found_end); # Only do this routine once $linecnt++; $lineauto = 0 if (/^[^ ]/); # Dog gone Cool matches to process the rest of the config /^!Command: show running-config/ && next; # kill this junk /^!Time: / && next; # kill this junk # Sort username and delete passwords. if (/^username (\S+) password (\d) (\S+)(\s.*)$/) { if ($filter_pwds >= 2) { ProcessHistory("USER","keysort","$1", "!username $1 password $4\n"); } elsif ($filter_pwds >= 1 && $2 ne "5") { ProcessHistory("USER","keysort","$1", "!username $1 password $4\n"); } else { ProcessHistory("USER","keysort","$1","$_"); } next; } # Sort any other username info. /^username (\S+) .*$/ && ProcessHistory("USER","keysort","$1","$_") && next; if (/^\s*(.*?neighbor \S*) password / && $filter_pwds >= 1) { ProcessHistory("","","","! $1 password \n"); next; } # sort ipv{4,6} access-lists if ($aclfilterseq && /^ip(v4|v6)? access-list (\S+)\s*$/) { my($nlri, $key) = ($1, $2); my($seq, $cmd); if (length($nlri) eq 0) { $nlri = "ipv4"; # assume ip will become ipv4 at some point } ProcessHistory("ACL $nlri $key","","","$_"); while (<$INPUT>) { tr/\015//d; goto REPEAT if (/^$prompt/ || !/^\s/); if (/^\s*!/) { ProcessHistory("ACL $nlri $key !", "", "", "$_"); next; } # ip access-list copp-system-acl-bgp # 10 permit tcp any gt 1024 any eq bgp # 20 permit tcp any eq bgp any gt 1024 # ipv6 access-list copp-system-acl-bgp6 # 10 permit tcp any gt 1024 any eq bgp # 20 permit tcp any eq bgp any gt 1024 # XXX this may need more format handling; going off email with # a user. 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"); } } } # Why was this commented out? It shows up in the raw text... if (/^(snmp-server community) (\S+)/) { if ($filter_commstr) { ProcessHistory("SNMPSERVERCOMM","keysort","$_", "!$1 $'") && next; } else { ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && 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; } # Sort snmp user and delete passwords. if (/^snmp-server user (\S+) (\S+) auth md5 (\S+) priv (\S+) localizedkey$/) { if ($filter_pwds >= 2) { ProcessHistory("SNMP-USER","keysort","$1", "!snmp-server user $1 $2 auth md5 priv localizedkey\n"); } else { ProcessHistory("SNMP-USER","keysort","$1","$_"); } next; } # Sort any other snmp user info. /^snmp-server user (\S+) .*$/ && ProcessHistory("SNMP-USER","keysort","$1","$_") && next; # Delete bgp passwords. if (/^(\s*)password (\d) (\S+)(\s.*)?$/) { if ($filter_pwds >= 2) { ProcessHistory("","","","!$1password $4"); } elsif ($filter_pwds >= 1 && $2 ne "5") { ProcessHistory("","","","!$1password $4"); } else { ProcessHistory("","","","$_"); } next; } # prune tacacs/radius server keys: # tacacs-server host 196.23.0.13 key 7 "xxxxxxx" port 50 timeout 10 if (/^((tacacs|radius)-server.*?\bkey\b.*?) ".*?"(.*)/ && $filter_pwds >= 1) { ProcessHistory("","","","!$1 $3\n"); next; } # order cli alias names /^cli alias name (\S+) .*$/ && ProcessHistory("CLI-ALIAS","keysort","$1","$_") && next; # order snmp-server enable trap statements /^snmp-server enable traps (.*)$/ && ProcessHistory("SNMP-TRAPS","keysort","$1","$_") && next; # catch anything that wasnt matched above. ProcessHistory("","","","$_"); # end of config. the ": " game is for the PIX if (/^(: +)?end$/) { $found_end = 1; return(0); } } # The ContentEngine lacks a definitive "end of config" marker. If we # know that it is NXOS and we have seen at least 5 lines # of write term output, we can be reasonably sure that we got the config. if (($type eq "NXOS") && $linecnt > 5) { $found_end = 1; return(0); } return(0); } 1;