Index: Makefile =================================================================== --- Makefile (revision 414774) +++ Makefile (working copy) @@ -3,7 +3,7 @@ PORTNAME= rancid PORTVERSION= 3.4.1 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= net-mgmt MASTER_SITES= ftp://ftp.shrubbery.net/pub/rancid/ PKGNAMESUFFIX= 3 @@ -59,8 +59,14 @@ post-patch: ${REINPLACE_CMD} "s|par.1|rancid-par.1|" ${WRKSRC}/man/Makefile.in ${MV} ${WRKSRC}/man/par.1 ${WRKSRC}/man/rancid-par.1 + ${CAT} ${FILESDIR}/comware7_types.conf >> ${WRKSRC}/etc/rancid.types.base post-install: +# Comware7 support +# https://sites.google.com/site/jrbinks/code/rancid/cmwrancid + ${INSTALL_DATA} ${FILESDIR}/cmw.pm ${STAGEDIR}/${PREFIX}/lib/rancid + ${INSTALL_SCRIPT} ${FILESDIR}/cmwlogin ${STAGEDIR}/${PREFIX}/libexec/rancid + ${LN} -s ${PREFIX}/libexec/${PORTNAME}/rancid-cvs ${STAGEDIR}${PREFIX}/bin ${LN} -s ${PREFIX}/libexec/${PORTNAME}/rancid-run ${STAGEDIR}${PREFIX}/bin .for file in ${NEWCONFIG_FILES} Index: files/cmw.pm =================================================================== --- files/cmw.pm (revision 0) +++ files/cmw.pm (working copy) @@ -0,0 +1,522 @@ +package cmw; +## +## $Id: cmw.pm.in 3000 2015-01-06 18:47:49Z heas $ +## +## rancid 3.1.99 +## Copyright (c) 1997-2015 by Terrapin Communications, Inc. +## All rights reserved. +## +## This code is derived from software contributed to and maintained by +## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan, +## Pete Whiting, Austin Schutz, and Andrew Fort. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. All advertising materials mentioning features or use of this software +## must display the following acknowledgement: +## This product includes software developed by Terrapin Communications, +## Inc. and its contributors for RANCID. +## 4. Neither the name of Terrapin Communications, Inc. nor the names of its +## contributors may be used to endorse or promote products derived from +## this software without specific prior written permission. +## 5. It is requested that non-binding fixes and modifications be contributed +## back to Terrapin Communications, Inc. +## +## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS +## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS +## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +## POSSIBILITY OF SUCH DAMAGE. +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# cmw.pm - Comware (Huawei/H3C/3com/HP) rancid procedures +# +# https://sites.google.com/site/jrbinks/code/rancid/cmwrancid + +use 5.010; +use strict 'vars'; +use warnings; +no warnings 'uninitialized'; +require(Exporter); +our @ISA = qw(Exporter); + +use rancid; + +our $login; + +@ISA = qw(Exporter rancid main); +#XXX @Exporter::EXPORT = qw($VERSION @commandtable %commands @commands); + +# XXX +#our @EXPORT = qw(iproutesort iprouteval); + +# load-time initialization +sub import { + 0; +} + +# post-open(collection file) initialization +sub init { + $login = "cmwlogin"; + # add content lines and separators + ProcessHistory("","","","!RANCID-CONTENT-TYPE: $devtype\n!\n"); + + 0; +} + +# main loop of input of device output +sub inloop { + my($INPUT, $OUTPUT) = @_; + my($cmd, $rval); + +TOP: while(<$INPUT>) { + tr/\015//d; + if (/[\]>#]\a?\s*quit/) { + #if (/[>#]\s?exit$/) { + $clean_run = 1; + last; + } + if (/^Error:/) { + print STDOUT ("$host $login error: $_"); + print STDERR ("$host $login error: $_") if ($debug); + $clean_run = 0; + last; + } + while (/[\]>#]\a?\s*($cmds_regexp)\s*$/) { + $cmd = $1; + + if (!defined($prompt)) { + # Extract the prompt: look for something not [ or < at the start + # of the line, until either ] or > or # is reached: + $prompt = ($_ =~ /^([^\]>#]+[\]>]\a?)/)[0]; + $prompt =~ s/([][}{)(\\])/\\$1/g; + print STDERR ("PROMPT MATCH: $prompt\n") if ($debug); + } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "$host: found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last TOP; + } + $rval = &{$commands{$cmd}}($INPUT, $OUTPUT, $cmd); + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last TOP; + } + } + } +} + +# dummy function +sub DoNothing {print STDOUT;} + +# This is a sort routine that will sort on the +# ip route when the ip route is anywhere in +# the strings. +sub iproutesort { + my(%lines) = @_; + my($i) = 0; + my(@sorted_lines); + foreach my $iproute (sort sortbyiproute keys %lines) { + $sorted_lines[$i] = $lines{$iproute}; + $i++; + } + @sorted_lines; +} + +## XXX Re-evaluate based on new routines, and consider IPv6: +# These two routines will sort based upon IP route +sub iprouteval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)$#); + $a[4] + ($a[3] + 256 * ($a[2] + 256 * ($a[1] + 256 * $a[0]))); +} + +sub sortbyiproute { + &iprouteval($a) <=> &iprouteval($b); +} + +# Clean up lines on input, particularly ANSI characters as a result +# of us not being able to turn off per-session terminal paging +sub filter_lines { + my ($l) = (@_); + + #s/^\033\[42D +\033\[42D(.+)$/$1/; + #s/\033\133\064\062\104\s*\033\133\064\062\104//g; + $l =~ s/\033\133\064\062\104\s+\033\133\064\062\104//g; + $l =~ s/\033\133\061\066\104\s+\033\133\061\066\104//g; + $l =~ s/\033\133\064\062\104//g; + $l =~ s/\033\133\061\062\104//g; + $l =~ s/.*\[37D(.*)/$1/g; # MA5600 + # Probably not needed: + $l =~ s/\s*---- More ----\s*//; + $l =~ s/^ //; # Comware7 + $l =~ s/Synchronization is finished.//g; + return $l; +} + +# Some commands are not supported on some models or versions +# of code. +# Remove the associated error messages, and rancid will ensure that +# these are not treated as "missed" commands +sub command_not_valid { + my ($l) = (@_); + + if ( $l =~ + /% Too many parameters found at '\^' position/ || + /% Unrecognized command found at '\^' position/ || + /% Incomplete command found at '\^' position./ || + /(% )?Wrong parameter found at '\^' position/ || + /% Wrong device .+/ + ) { + return(1); + } else { + return(0); + } +} + +# Some commands are not authorized under the current +# user's permissions +sub command_not_auth { + my ($l) = (@_); + + if ( $l =~ + /Permission denied\./ + ) { + return(1); + } else { + return(0); + } +} + +# Some output lines are always skipped +sub skip_pattern { + my ($l) = (@_); + + if ( $l =~ + /^\s+\^$/ || + /^$/ + ) { + return(1); + } else { + return(0); + } +} + +sub DisplayFib { + + my($INPUT, $OUTPUT, $cmd) = @_; + my($dest, $nexthop, $flag, $outint, $label); + print STDERR " In DisplayFib: $_" if ($debug); + + chomp; + + # Display the command we're processing in the output: + ProcessHistory("FIB","","","!\n! '$cmd':\n!\n"); + + while (<$INPUT>) { + tr/\015//d; + last if(/^\s*$prompt/); + chomp; + $_ = filter_lines($_); + + return(1) if command_not_valid($_); + return(-1) if command_not_auth($_); + next if skip_pattern($_); + + next if /^Destination count: \d+ FIB entry count: \d+/; + + # Chop out some detail that changes over time (Comware 3): + s/(\s+)TimeStamp\s+/$1/; # TimeStamp column heading + + ProcessHistory("FIB","","","! $_\n"); + + if ( m,Destination/Mask, ) { + while (<$INPUT>) { + tr/\015//d; + last if(/^\s*$prompt/); + chomp; + $_ = filter_lines($_); + + # Chop out some detail that changes over time (Comware 3): + s/(\s+)t\[\d+\]\s+/$1/; # TimeStamp data + + # "display fib" on comware7 shows host entries for things + # learned via arp too. For a distribution router, that's all + # the devices on subnets routed by it! + # If we filter out all "UH" entries that are NOT InLoop, we + # get acceptable output. + # + # So we want to keep: + # + # 0.0.0.0/32 127.0.0.1 UH InLoop0 Null + # + # but reject: + # + # 130.159.44.161/32 130.159.44.161 UH Vlan44 Null + # + # However I've a feeling that this is a problematic + # solution, and some object to the notion that rancid + # should be representing such potentially dynamic data in + # the first place, which is why we created the + # $display_fib flag for rancid 2, and in rancid 3 one + # can modify the command table in rancid.types.conf + + ($dest, $nexthop, $flag, $outint, $label) = split; + next if ( $flag eq 'UH' && $outint !~ /InLoop/ ); + #ProcessHistory("FIB", "cmw::iproutesort", "$dest", "! $_\n"); + ProcessHistory("FIB", "ipsort", "$dest", "! $_\n"); + } + + ProcessHistory("FIB", "", "", "!\n"); + + # return here to ensure that we don't keep swallowing the + # next command's output by returning to the surrounding + # while loop + return(0); + } + } + return(0); +} + +sub DisplayIPRoutes { + my($INPUT, $OUTPUT, $cmd) = @_; + my($key,$line,$spaces); + print STDERR " In DisplayIPRoutes: $_" if ($debug); + + chomp; + + # Display the command we're processing in the output: + ProcessHistory("IPR","","","!\n! '$cmd':\n!\n"); + + while (<$INPUT>) { + tr/\015//d; + last if(/^\s*$prompt/); + chomp; + + $_ = filter_lines($_); + return(1) if command_not_valid($_); + return(-1) if command_not_auth($_); + next if skip_pattern($_); + + ProcessHistory("IPR","","","! $_\n"); + + if ( m,Destination/Mask, ) { + my $lastkey = ""; + my $lastspaces = ""; + while (<$INPUT>) { + tr/\015//d; + last if(/^\s*$prompt/); + chomp; + $_ = filter_lines($_); + + # If the key is blank, indicating multiple nexthops for + # a particular route, then we use the previous one + if ( m/^\s+(.+)/ ) { + $key = $lastkey; + $line = $key . $lastspaces . $1; + #ProcessHistory("IPR", "cmw::iproutesort", "$key", "! $line\n"); + ProcessHistory("IPR", "ipsort", "$key", "! $line\n"); + } + if ( m/^(\S+)(\s+).+/ ) { + $key = $1; + $line = $_; + $spaces = $2; + #ProcessHistory("IPR", "cmw::iproutesort", "$key", "! $line\n"); + ProcessHistory("IPR", "ipsort", "$key", "! $line\n"); + + # Remember these, we may need them on the next pass + $lastkey = $key; + $lastspaces = $spaces; + } + } + + ProcessHistory("IPR", "", "", "!\n"); + + # return here to ensure that we don't keep swallowing the + # next command's output by returning to the surrounding + # while loop + return(0); + } + } + return(0); +} + +## This routine processes general output of "display" commands +sub CommentOutput { + my($INPUT, $OUTPUT, $cmd) = @_; + print STDERR " In CommentOutput: $_" if ($debug); + + chomp; + + # Display the command we're processing in the output: + ProcessHistory("COMMENTS", "", "", "!\n! '$cmd':\n!\n"); + + while (<$INPUT>) { + tr/\015//d; + + # If we find the prompt, we're done + # Ordinarily this matches from the start of the line, however + # we've seen circumstances at least in Comware7 where the + # prompt is preceded by whitespace, like so: + # ^M^M ^Mdisplay boot-loader^M + last if(/^\s*$prompt/); + chomp; + + # filter out some junk + $_ = filter_lines($_); + return(1) if command_not_valid($_); + return(-1) if command_not_auth($_); + next if skip_pattern($_); + + # Now we skip or modify some lines from various commands to + # remove irrelevant content, or to avoid insignificant diffs + + # 'display local-user': + s/\s+Current AccessNum:.+$//; + + # 'display version': + next if (/^(Uptime is \d|.+ [Uu]ptime is \d).+$/); + # No longer necessary since skipping the whole Uptime line: + # Mangle these lines: + #s/(.*)[Uu]ptime.*.weeks.*.days*.*hours*.*minutes*(.*)/$1 $2/; + #s/(.*)[Uu]ptime.*days*.*hours*.*minutes*(.*)/$1 $2/; + + # MSRs display a 'last reboot' time, but sometimes the seconds + # vary by one or two (presumably internal rounding), so simply make + # the last digit a fixed '0'. It would probably be safer to make + # the last two digits a fixed '00'. + # (Thx Alexander Belokopytov) + s/(^Last reboot.+)\d$/${1}0/; + + # 'dir ' commands + if ( $cmd =~ /^dir / ) { + # First field is just an index number, chop it out + s/^\s+\d+\s+(.+)/ $1/; + # Remove filenames that are updated frequently + next if ( + /logfile\.log$/ || + /lauth\.dat$/ || + /ifindex\.dat$/ || + /startup\.mdb$/ || + /private-data\.txt$/ || + /.+ KB total \(.+ KB free/ || + /.+ KB total \(.+ KB free/ || + /\.trash/ + ); + } + + # 'display ospf brief'/'display ospf' + if ( $cmd =~ 'display ospf( brief)?' ) { + #next if (/^(Ospf is not enabled yet|Info: OSPF routing process is not enabled|The feature OSPF has not been enabled.).+$/); + next if (/^\s+SPF (Computation|Scheduled|calculation) Count:.+$/i); + } + + if ( $cmd eq 'display power' ) { + next if (/^(\s+Input Power).+$/); + } + + if ( $cmd eq 'display poe powersupply' ) { + next if (/^(PSE Total Power Consumption|PSE Available Power|PSE Peak Value|PSE Average Value).+$/); + } + + if ( $cmd eq 'display ntp-service status' ) { + next unless m/(Clock status|Clock stratum|Reference clock ID)/i; + } + + if ( $cmd eq 'display transceiver interface' ) { + s/^(\S+ transceiver information:).+$/$1/; # filter random garbage + s/^Error: The transceiver is absent.$/ No transceiver present./; + s/^Error: The combo port is inactive.$/ Inactive combo port./; + } + + # Add the processed lines to the output buffer: + ProcessHistory("COMMENTS","","","! $_\n"); + } + + # Add a blank comment line to the output buffer + ProcessHistory("COMMENTS", "", "", "!\n"); + return(0); +} + +## This routine processes a "display current" +sub DisplayCurrent { + my($INPUT, $OUTPUT, $cmd) = @_; + print STDERR " In DisplayCurrent: $_" if ($debug); + + + while (<$INPUT>) { + tr/\015//d; + last if(/^\s*$prompt/); + chomp; + + $_ = filter_lines($_); + return(1) if command_not_valid($_); + return(-1) if command_not_auth($_); + next if skip_pattern($_); + + return(0) if ($found_end); + + # Filter out some sensitive data: + if ( $filter_commstr && + /^ ?(snmp-agent (target-host.+securityname|usm-user|community (read|write)) )(\S+)/ + ) { + ProcessHistory("","","","! $1$'\n"); + next; + } + if ( $filter_pwds >= 1 && + /^ ?(password (?:simple|cipher|hash) )(\S+)/ || + /^ ?(super password( role level-\d)( level \d)? (cipher|simple|hash) )(\S+)/ || + /^ ?(set authentication password (cipher|simple|hash) )(\S+)/ || + /^ ?(key (?:authentication|accounting) )(\S+)/ + ) { + ProcessHistory("","","","! $1$'\n"); + next; + } + + # filter ssh public keys of devices connected to from this device + if (/^ ?(public-key-code begin)/ && + $filter_pwds >= 2) { + ProcessHistory("","","","!$1\n"); + ProcessHistory("","","","! \n"); + while (<$INPUT>) { + tr/\015//d; + next if /^$/; + next if /^\s+[[:xdigit:]]$/; + if (/(^ public-key-code end)/) { + ProcessHistory("","","","!$1\n"); + last; + } + } + next; + } + + # Filter mac addresses dynamically added to config + next if (/^ ?mac-address security.+$/); + + ProcessHistory("", "", "", "$_\n"); + + # end of config + if (/^return/) { + $found_end = 1; + return(0); + } + } + return(0); +} + +1; + Property changes on: files/cmw.pm ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: files/cmwlogin =================================================================== --- files/cmwlogin (revision 0) +++ files/cmwlogin (working copy) @@ -0,0 +1,1043 @@ +#! /usr/local/bin/expect -- +## +## $Id: cmwlogin 3022 2015-01-13 20:00:00Z heas $ +## +## rancid 3.4.1 +## Copyright (c) 1997-2015 by Terrapin Communications, Inc. +## All rights reserved. +## +## This code is derived from software contributed to and maintained by +## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan, +## Pete Whiting, Austin Schutz, and Andrew Fort. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. All advertising materials mentioning features or use of this software +## must display the following acknowledgement: +## This product includes software developed by Terrapin Communications, +## Inc. and its contributors for RANCID. +## 4. Neither the name of Terrapin Communications, Inc. nor the names of its +## contributors may be used to endorse or promote products derived from +## this software without specific prior written permission. +## 5. It is requested that non-binding fixes and modifications be contributed +## back to Terrapin Communications, Inc. +## +## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS +## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS +## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +## POSSIBILITY OF SUCH DAMAGE. +# +# The expect login scripts were based on Erik Sherk's gwtn, by permission. +# +# cwlogin - Comware login +# +# Most options are intuitive for logging into a Comware device. +# The default is to enable (thus -noenable). Some folks have +# setup tacacs to have a user login at priv-lvl = 3 (enabled) +# so the -autoenable flag was added for this case (don't go through +# the process of enabling and the prompt will be the "#" prompt. +# The default username password is the same as the vty password. +# + +# Usage line +set usage "Usage: $argv0 \[-dSV\] \[-autoenable\] \[-noenable\] \[-c command\] \ +\[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \ +\[-r passphrase\] \[-s script-file\] \[-t timeout\] \[-u username\] \ +\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \[-P platform\] \ +\[-y ssh_cypher_type\] router \[router...\]\n" + +# env(CLOGIN) may contain: +# x == do not set xterm banner or name + +# Password file +set password_file $env(HOME)/.cloginrc +# Default is to login to the router +set do_command 0 +set do_script 0 +# The default is to automatically enable +set avenable 1 +# The default is that you login non-enabled (tacacs can have you login already +# enabled) +set avautoenable 0 +# The default is to look in the password file to find the passwords. This +# tracks if we receive them on the command line. +set do_passwd 1 +set do_enapasswd 1 +# Save config, if prompted +set do_saveconfig 0 +# Sometimes routers take awhile to answer (the default is 10 sec) +set timeoutdflt 45 +# Some CLIs having problems if we write too fast (Extreme, PIX, Cat) +set send_human {.2 .1 .4 .2 1} + +# Find the user in the ENV, or use the unix userid. +if {[info exists env(CISCO_USER)]} { + set default_user $env(CISCO_USER) +} elseif {[info exists env(USER)]} { + set default_user $env(USER) +} elseif {[info exists env(LOGNAME)]} { + set default_user $env(LOGNAME) +} else { + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + if [catch {exec id} reason] { + send_error "\nError: could not exec id: $reason\n" + exit 1 + } + regexp {\(([^)]*)} "$reason" junk default_user +} +if {[info exists env(CLOGINRC)]} { + set password_file $env(CLOGINRC) +} + +# Process the command line +for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + + switch -glob -- $arg { + # Expect debug mode + -d* { + exp_internal 1 + # Username + } -u* { + if {! [regexp .\[uU\](.+) $arg ignore user]} { + incr i + set username [lindex $argv $i] + } + # VTY Password + } -p* { + if {! [regexp .\[pP\](.+) $arg ignore userpasswd]} { + incr i + set userpasswd [lindex $argv $i] + } + set do_passwd 0 + # ssh passphrase + } -r* { + if {! [regexp .\[rR\](.+) $arg ignore passphrase]} { + incr i + set vapassphrase [lindex $argv $i] + } + # VTY Password + } -v* { + if {! [regexp .\[vV\](.+) $arg ignore passwd]} { + incr i + set passwd [lindex $argv $i] + } + set do_passwd 0 + # Version string + } -V* { + send_user "rancid 3.4.1\n" + exit 0 + # Enable Username + } -w* { + if {! [regexp .\[wW\](.+) $arg ignore enauser]} { + incr i + set enausername [lindex $argv $i] + } + # Environment variable to pass to -s scripts + } -E* { + if {[regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} { + set E$varname $varvalue + } else { + send_user "\nError: invalid format for -E in $arg\n" + exit 1 + } + # Enable Password + } -e* { + if {! [regexp .\[e\](.+) $arg ignore enapasswd]} { + incr i + set enapasswd [lindex $argv $i] + } + set do_enapasswd 0 + # Platform + } -P* { + if {! [regexp .\[P\](.+) $arg ignore platform]} { + incr i + set plat [lindex $argv $P] + } + # Command to run. + } -c* { + if {! [regexp .\[cC\](.+) $arg ignore command]} { + incr i + set command [lindex $argv $i] + } + set do_command 1 + # Expect script to run. + } -s* { + if {! [regexp .\[sS\](.+) $arg ignore sfile]} { + incr i + set sfile [lindex $argv $i] + } + if { ! [file readable $sfile] } { + send_user "\nError: Can't read $sfile\n" + exit 1 + } + set do_script 1 + # save config on exit + } -S* { + set do_saveconfig 1 + # 'ssh -c' cypher type + } -y* { + if {! [regexp .\[eE\](.+) $arg ignore cypher]} { + incr i + set cypher [lindex $argv $i] + } + # alternate cloginrc file + } -f* { + if {! [regexp .\[fF\](.+) $arg ignore password_file]} { + incr i + set password_file [lindex $argv $i] + } + # Timeout + } -t* { + if {! [regexp .\[tT\](.+) $arg ignore timeout]} { + incr i + set timeoutdflt [lindex $argv $i] + } + # Command file + } -x* { + if {! [regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr i + set cmd_file [lindex $argv $i] + } + if [catch {set cmd_fd [open $cmd_file r]} reason] { + send_user "\nError: $reason\n" + exit 1 + } + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + # Do we enable? + } -noenable { + set avenable 0 + # Does tacacs automatically enable us? + } -autoenable { + set avautoenable 1 + set avenable 0 + } -* { + send_user "\nError: Unknown argument! $arg\n" + send_user $usage + exit 1 + } default { + break + } + } +} +# Process routers...no routers listed is an error. +if { $i == $argc } { + send_user "\nError: $usage" +} + +# Only be quiet if we are running a script (it can log its output +# on its own) +if { $do_script } { + log_user 0 +} else { + log_user 1 +} + +# +# Done configuration/variable setting. Now run with it... +# + +# Sets Xterm title if interactive...if its an xterm and the user cares +proc label { host } { + global env + # if CLOGIN has an 'x' in it, don't set the xterm name/banner + if [info exists env(CLOGIN)] { + if {[string first "x" $env(CLOGIN)] != -1} { return } + } + # take host from ENV(TERM) + if [info exists env(TERM)] { + if [regexp \^(xterm|vs) $env(TERM) ignore] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } + } +} + +# This is a helper function to make the password file easier to +# maintain. Using this the password file has the form: +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie +proc add {var args} { global int_$var ; lappend int_$var $args} +proc include {args} { + global env + regsub -all "(^{|}$)" $args {} args + if { [regexp "^/" $args ignore] == 0 } { + set args $env(HOME)/$args + } + source_password_file $args +} + +proc find {var router} { + upvar int_$var list + if { [info exists list] } { + foreach line $list { + if { [string match -nocase [lindex $line 0] $router] } { + return [lrange $line 1 end] + } + } + } + return {} +} + +# Loads the password file. Note that as this file is tcl, and that +# it is sourced, the user better know what to put in there, as it +# could install more than just password info... I will assume however, +# that a "bad guy" could just as easy put such code in the clogin +# script, so I will leave .cloginrc as just an extention of that script +proc source_password_file { password_file } { + global env + if { ! [file exists $password_file] } { + send_user "\nError: password file ($password_file) does not exist\n" + exit 1 + } + file stat $password_file fileinfo + if { [expr ($fileinfo(mode) & 007)] != 0000 } { + send_user "\nError: $password_file must not be world readable/writable\n" + exit 1 + } + if [catch {source $password_file} reason] { + send_user "\nError: $reason\n" + exit 1 + } +} + +# Log into the router. +# returns: 0 on success, 1 on failure, -1 if rsh was used successfully +proc login { router user userpswd passwd enapasswd cmethod cyphertype identfile } { + global command spawn_id in_proc do_command do_script platform passphrase + global prompt prompt_match u_prompt p_prompt e_prompt sshcmd + set in_proc 1 + set uprompt_seen 0 + + # try each of the connection methods in $cmethod until one is successful + set progs [llength $cmethod] + foreach prog [lrange $cmethod 0 end] { + incr progs -1 + if [string match "telnet*" $prog] { + regexp {telnet(:([^[:space:]]+))*} $prog methcmd suffix port + if {"$port" == ""} { + set retval [catch {spawn telnet $router} reason] + } else { + set retval [catch {spawn telnet $router $port} reason] + } + if { $retval } { + send_user "\nError: telnet failed: $reason\n" + return 1 + } + } elseif [string match "ssh*" $prog] { + # ssh to the router & try to login with or without an identfile. + regexp {ssh(:([^[:space:]]+))*} $prog methcmd suffix port + set cmd $sshcmd + if {"$port" != ""} { + set cmd "$cmd -p $port" + } + if {"$identfile" != ""} { + set cmd "$cmd -i $identfile" + } + set retval [catch {eval spawn [split "$cmd -c $cyphertype -x -l $user $router" { }]} reason] + if { $retval } { + send_user "\nError: $cmd failed: $reason\n" + return 1 + } + } elseif ![string compare $prog "rsh"] { + if { ! $do_command } { + if { [llength $cmethod] == 1 } { + send_user "\nError: rsh is an invalid method for -x and " + send_user "interactive logins\n" + } + if { $progs == 0 } { + return 1 + } + continue; + } + + # handle escaped ;s in commands, and ;; and ^; + regsub -all {([^\\]);;} $command "\\1;\u002;" esccommand + regsub {^;} $esccommand "\u002;" command + set sep "\\1\u001" + regsub -all {([^\\])\;} $command "$sep" esccommand + set sep "\u001" + set commands [split $esccommand $sep] + set num_commands [llength $commands] + set rshfail 0 + for {set i 0} {$i < $num_commands && !$rshfail} { incr i} { + log_user 0 + set retval [catch {spawn rsh $user@$router [lindex $commands $i] } reason] + if { $retval } { + send_user "\nError: rsh failed: $reason\n" + log_user 1; return 1 + } + send_user "$router# [lindex $commands $i]\n" + + # rcmd does not get a pager and no prompts, so we just have to + # look for failures & lines. + expect { + "Connection refused" { catch {close}; catch {wait}; + send_user "\nError: Connection\ + Refused ($prog): $router\n" + set rshfail 1 + } + -re "(Connection closed by|Connection to \[^\n\r]+ closed)" { + catch {close}; catch {wait}; + send_user "\nError: Connection\ + closed ($prog): $router\n" + set rshfail 1 + } + "Host is unreachable" { catch {close}; catch {wait}; + send_user "\nError: Host Unreachable:\ + $router\n" + set rshfail 1 + } + "No address associated with" { + catch {close}; catch {wait}; + send_user "\nError: Unknown host\ + $router\n" + set rshfail 1 + } + -re "\b+" { exp_continue } + -re "\[\n\r]+" { send_user -- "$expect_out(buffer)" + exp_continue + } + timeout { catch {close}; catch {wait}; + send_user "\nError: TIMEOUT reached\n" + set rshfail 1 + } + eof { catch {close}; catch {wait}; } + } + log_user 1 + } + if { $rshfail } { + if { !$progs } { + return 1 + } else { + continue + } + } + # fake the end of the session for rancid. + send_user "$router# exit\n" + # return rsh "success" + return -1 + } else { + send_user "\nError: unknown connection method: $prog\n" + return 1 + } + sleep 0.3 + + # This helps cleanup each expect clause. + expect_after { + timeout { + send_user "\nError: TIMEOUT reached\n" + catch {close}; catch {wait}; + if { $in_proc} { + return 1 + } else { + continue + } + } eof { + send_user "\nError: EOF received\n" + catch {close}; catch {wait}; + if { $in_proc} { + return 1 + } else { + continue + } + } + } + + # Here we get a little tricky. There are several possibilities: + # the router can ask for a username and passwd and then + # talk to the TACACS server to authenticate you, or if the + # TACACS server is not working, then it will use the enable + # passwd. Or, the router might not have TACACS turned on, + # then it will just send the passwd. + # if telnet fails with connection refused, try ssh + expect { + -re "^<-+ More -+>\[^\n\r]*" { + # ASA will use the pager for long banners + send " "; + exp_continue + } + -re "(Connection refused|Secure connection \[^\n\r]+ refused)" { + catch {close}; catch {wait}; + if !$progs { + send_user "\nError: Connection Refused ($prog): $router\n" + return 1 + } + } + -re "(Connection closed by|Connection to \[^\n\r]+ closed)" { + catch {close}; catch {wait}; + if !$progs { + send_user "\nError: Connection closed ($prog): $router\n" + return 1 + } + } + eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 } + -nocase "unknown host\r" { + send_user "\nError: Unknown host $router\n"; + catch {close}; catch {wait}; + return 1 + } + "Host is unreachable" { + send_user "\nError: Host Unreachable: $router\n"; + catch {close}; catch {wait}; + return 1 + } + "No address associated with name" { + send_user "\nError: Unknown host $router\n"; + catch {close}; catch {wait}; + return 1 + } + -re "(Host key not found |The authenticity of host .* be established).* \\(yes/no\\)\\?" { + send "yes\r" + send_user "\nHost $router added to the list of known hosts.\n" + exp_continue + } + -re "HOST IDENTIFICATION HAS CHANGED.* \\(yes/no\\)\\?" { + send "no\r" + send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n" + catch {close}; catch {wait}; + return 1 + } + -re "HOST IDENTIFICATION HAS CHANGED\[^\n\r]+" { + send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n" + return 1 + } + -re "Offending key for .* \\(yes/no\\)\\?" { + send "no\r" + send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n" + catch {close}; catch {wait}; + return 1 + } + -re "(denied|Sorry)" { + send_user "\nError: Check your passwd for $router\n" + catch {close}; catch {wait}; return 1 + } + "Login failed" { + send_user "\nError: Check your passwd for $router\n" + catch {close}; catch {wait}; return 1 + } + -re "% (Bad passwords|Authentication failed)" { + send_user "\nError: Check your passwd for $router\n" + catch {close}; catch {wait}; return 1 + } + "Press any key to continue" { + # send_user "Pressing the ANY key\n" + send "\r" + exp_continue + } + -re "Enter Selection: " { + # Catalyst 1900s have some lame menu. Enter + # K to reach a command-line. + send "K\r" + exp_continue + } + -re "Last login:" { + exp_continue + } + -re "Press the key \[^\r\n]+\[\r\n]+" { + exp_continue + } + -re "@\[^\r\n]+ $p_prompt" { + # ssh pwd prompt + sleep 1 + send -- "$userpswd\r" + exp_continue + } + -re "Enter passphrase.*: " { + # sleep briefly to allow time for stty -echo + sleep .3 + send -- "$passphrase\r" + exp_continue + } + -re "$u_prompt" { + send -- "$user\r" + set uprompt_seen 1 + exp_continue + } + -re "$p_prompt" { + sleep 1 + if {$uprompt_seen == 1} { + send -- "$userpswd\r" + } else { + send -- "$passwd\r" + } + exp_continue + } + -re "$prompt" { + set prompt_match $expect_out(0,string); + break; + } + "Login invalid" { + send_user "\nError: Invalid login: $router\n"; + catch {close}; catch {wait}; return 1 + } + -re "\[^\r\n]*\[\r\n]+" { exp_continue; } + } + } + + set in_proc 0 + return 0 +} + +# Enable +proc do_enable { enauser enapasswd } { + global do_saveconfig in_proc + global prompt u_prompt e_prompt enacmd + set in_proc 1 + + send "$enacmd\r" + expect { + -re "$u_prompt" { send -- "$enauser\r"; exp_continue} + -re "$e_prompt" { send -- "$enapasswd\r"; exp_continue} + ">" { set prompt ">" } + "#" { set prompt "#" } + "(enable)" { set prompt "> \\(enable\\) " } + "% Invalid input" { + send_user "\nError: Unrecognized command, check your enable command\n"; + return 1 + } + -re "(denied|Sorry|Incorrect)" { + # % Access denied - from local auth and poss. others + send_user "\nError: Check your Enable passwd\n"; + return 1 + } + "% Error in authentication" { + send_user "\nError: Check your Enable passwd\n" + return 1 + } + "% Bad passwords" { + send_user "\nError: Check your Enable passwd\n" + return 1 + } + "% Password is not set." { # Comware + send_user "\nError: No '$enacmd' password set for devide\n" + return 1 + } + "% Authenticate failed." { # Comware + send_user "\nError: Check your enable password for '$enacmd'\n + return 1 + } + } + # We set the prompt variable (above) so script files don't need + # to know what it is. + set in_proc 0 + return 0 +} + +# Run commands given on the command line. +proc run_commands { prompt command } { + global do_saveconfig in_proc platform exitcmd + set in_proc 1 + + # If the prompt is (enable), then we are on a switch and the + # command is "set length 0"; otherwise its "terminal length 0". + # skip if its an extreme (since the pager can not be disabled on a + # per-vty basis). + if { [string compare "extreme" "$platform"] } { + # match cisco config mode prompts too, such as router(config-if)#, + # but catalyst does not change in this fashion. + regsub -all {^(.{1,11}).*([#>])$} $prompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt + } else { + set reprompt $prompt + } + + # this is the only way i see to get rid of more prompts in o/p..grrrrr + log_user 0 + + # handle escaped ;s in commands, and ;; and ^; + regsub -all {([^\\]);;} $command "\\1;\u002;" esccommand + regsub {^;} $esccommand "\u002;" command + set sep "\\1\u001" + regsub -all {([^\\]);} $command "$sep" esccommand + set sep "\u001" + set commands [split $esccommand $sep] + set num_commands [llength $commands] + # the pager can not be turned off on the PIX, so we have to look + # for the "More" prompt. the extreme is equally obnoxious in pre-12.3 XOS, + # with a global switch in the config. + for {set i 0} {$i < $num_commands} { incr i} { + if { [lindex $commands $i] == "\u002" } { + send -- "\r" + } else { + send -- "[subst -nocommands [lindex $commands $i]]\r" + } + expect { + -re "\b+" { exp_continue } + -re "^\[^\n\r *]*$reprompt" { send_user -- "$expect_out(buffer)" + } + -re "^\[^\n\r]*$reprompt." { send_user -- "$expect_out(buffer)" + exp_continue + } + -re "^--More--\[\r\n]+" { # specific match c1900 pager + send " " + exp_continue + } + -re "\[^\r\n]*\[\n\r]+" { send_user -- "$expect_out(buffer)" + exp_continue + } + -re "\[^\r\n]*Press to cont\[^\r\n]*" { + send " " + # bloody ^[[2K after " " + expect { + -re "^\[^\r\n]*\r" {} + } + exp_continue + } + -re "^ *--More--\[^\n\r]*" { + send " " + exp_continue } + -re "^<-+ More -+>\[^\n\r]*" { + send_user -- "$expect_out(buffer)" + send " " + exp_continue } + -re "^ {0,2}-+ More .*-+.*\[^\n\r]*" { + # Comware 3/5 pager prompt + sleep 0.1 + send " " + exp_continue } + -re "^---- More ----\[^\n\r]*" { + # Comware 7 pager prompt + sleep 0.1 + send " " + exp_continue } + } + } + log_user 1 + + if { [string compare "extreme" "$platform"] } { + send -h "exit\r" + } else { + send -h "quit\r" + } + expect { + -re "^\[^\n\r *]*$reprompt" { + # the Cisco CE and Jnx ERX + # return to non-enabled mode + # on exit in enabled mode. + send -h "$exitcmd\r" + exp_continue; + } + "The system has unsaved changes" { # Force10 SFTOS + if {$do_saveconfig} { + catch {send "y\r"} + } else { + catch {send "n\r"} + } + exp_continue + } + "Would you like to save them now" { # Force10 + if {$do_saveconfig} { + catch {send "y\r"} + } else { + catch {send "n\r"} + } + exp_continue + } + -re "(Profile|Configuration) changes have occurred.*" { + # Cisco CSS + if {$do_saveconfig} { + catch {send "y\r"} + } else { + catch {send "n\r"} + } + exp_continue + } + "Do you wish to save your configuration changes" { + if {$do_saveconfig} { + catch {send "y\r"} + } else { + catch {send "n\r"} + } + exp_continue + } + -re "\[\n\r]+" { exp_continue } + -re "\[^\n\r *]Note:" { return 0 } + timeout { catch {close}; catch {wait}; + return 0 + } + eof { return 0 } + } + set in_proc 0 +} + +# +# For each router... (this is main loop) +# +source_password_file $password_file +set in_proc 0 +set exitval 0 +set prompt_match "" +foreach router [lrange $argv $i end] { + set router [string tolower $router] + # attempt at platform switching. + set platform "" + send_user -- "$router\n" + + # Figure out the platform + if {[info exists plat]} { + # command line platform + set platform $plat + } else { + set plat [find platform $router] + if { "$plat" == "" } { set platform "" } + } + + # Based on the platform, set some other defaults + # These can get overridden by other explicit settings + # Note that MA5600 wants enacmd "enable" + # Note that later versions of Coomware want cyphertype "aes128-cbc" + if { [string compare "cmw" "$platform"] } { + set enacmd "super" + set exitcmd "quit" + set cyphertype "3des" + } else { + set exitcmd "exit" + } + + # device timeout + set timeout [find timeout $router] + if { [llength $timeout] == 0 } { + set timeout $timeoutdflt + } + + # Default prompt. + set prompt [join [find prompt $router] ""] + if { [llength $prompt] == 0 } { + set prompt "(>\a?|#| \\(enable\\))" + } + + # look for autoenable option in .cloginrc & cmd-line + set ae [find autoenable $router] + if { "$ae" == "1" || $avautoenable } { + set autoenable 1 + } else { + set autoenable 0 + } + # look for enable options in .cloginrc & cmd-line + if { $avenable == 0 } { + set enable 0 + } else { + set ne [find noenable $router] + if { "$ne" == "1" || "$autoenable" == "1" } { + set enable 0 + } else { + set enable 1 + } + } + + # Figure out passwords + if { $do_passwd || $do_enapasswd } { + set pswd [find password $router] + if { [llength $pswd] == 0 } { + send_user -- "\nError: no password for $router in $password_file.\n" + continue + } + if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } { + send_user -- "\nError: no enable password for $router in $password_file.\n" + continue + } + set passwd [join [lindex $pswd 0] ""] + set enapasswd [join [lindex $pswd 1] ""] + } else { + set passwd $userpasswd + set enapasswd $enapasswd + } + + # Figure out username + if {[info exists username]} { + # command line username + set ruser $username + } else { + set ruser [join [find user $router] ""] + if { "$ruser" == "" } { set ruser $default_user } + } + + # Figure out username's password (if different from the vty password) + if {[info exists userpasswd]} { + # command line username + set userpswd $userpasswd + } else { + set userpswd [join [find userpassword $router] ""] + if { "$userpswd" == "" } { set userpswd $passwd } + } + + # Figure out enable username + if {[info exists enausername]} { + # command line enausername + set enauser $enausername + } else { + set enauser [join [find enauser $router] ""] + if { "$enauser" == "" } { set enauser $ruser } + } + + # Figure out enable command + set enacmd [join [find enablecmd $router] ""] + if { "$enacmd" == "" } { set enacmd "enable" } + + # Figure out prompts + set u_prompt [find userprompt $router] + if { "$u_prompt" == "" } { + set u_prompt "(\[Uu]sername|Login|login|user name|User|User name):" + } else { + set u_prompt [join [lindex $u_prompt 0] ""] + } + set p_prompt [find passprompt $router] + if { "$p_prompt" == "" } { + set p_prompt "(\[Pp]assword|passwd|Enter password for \[^ :]+):" + } else { + set p_prompt [join [lindex $p_prompt 0] ""] + } + set e_prompt [find enableprompt $router] + if { "$e_prompt" == "" } { + set e_prompt "\[Pp]assword:" + } else { + set e_prompt [join [lindex $e_prompt 0] ""] + } + + # Figure out identity file to use + set identfile [join [lindex [find identity $router] 0] ""] + + # Figure out passphrase to use + if {[info exists avpassphrase]} { + set passphrase $avpassphrase + } else { + set passphrase [join [lindex [find passphrase $router] 0] ""] + } + if { ! [string length "$passphrase"]} { + set passphrase $passwd + } + + # Figure out cypher type + if {[info exists cypher]} { + # command line cypher type + set cyphertype $cypher + } else { + set cyphertype [find cyphertype $router] + if { "$cyphertype" == "" } { set cyphertype "3des" } + } + + # Figure out connection method + set cmethod [find method $router] + if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} } + + # Figure out the SSH executable name + set sshcmd [join [lindex [find sshcmd $router] 0] ""] + if { "$sshcmd" == "" } { set sshcmd {ssh} } + + + # Login to the router + if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype $identfile]} { + incr exitval + # if login failed or rsh was unsuccessful, move on to the next device + continue + } + # Figure out the prompt. + if { [regexp -- "(#| \\(enable\\))" $prompt_match junk] == 1 } { + set enable 0 + } + + # Disable smart and interactive before send other commands + # (MA5600 and similar only?) + # Also disable log junk being sent to terminal + if { [string compare "cmw" "$platform"] } { + send -h "undo smart\r" + expect -re $prompt {} + send -h "undo interactive\r" + expect -re $prompt {} + send -h "undo terminal monitor\r" + expect -re $prompt {} + } + + if { $enable } { + if {[do_enable $enauser $enapasswd]} { + if { $do_command || $do_script } { + incr exitval + catch {close}; catch {wait}; + continue + } + } + } + # we are logged in, now figure out the full prompt + send "\r" + regsub -all {^(\^*)(.*)} $prompt {\2} reprompt + expect { + -re "\[\r\n]+" { exp_continue; } + -re "^(.+\[:.])1 ($reprompt)" { # stoopid extreme cmd-line numbers and + # prompt based on state of config changes, + # which may have an * at the beginning. + set junk $expect_out(1,string) + regsub -all "^\\\* " $expect_out(1,string) {} junk + regsub -all "\[\]\[\(\)]" $junk {\\&} junk; + set prompt ".? ?$junk\[0-9]+ $expect_out(2,string)"; + set platform "extreme" + } + -re "^.+$reprompt" { set junk $expect_out(0,string); + regsub -all "\[\]\[\(\)+]" $junk {\\&} prompt; + } + } + if { $do_command || $do_script } { + if { [string compare "extreme" "$platform"] } { + # If the prompt is (enable), then we are on a switch and the + # command is "set length 0"; otherwise its "terminal length 0". + if [regexp -- ".*> .*enable" "$prompt"] { + send "set length 0\r" + expect -re $prompt {} + send "set width 132\r" + expect -re $prompt {} + send "set logging session disable\r" + } else { + send "terminal length 0\r" + expect -re $prompt {} + send "terminal width 132\r" + } + expect -re $prompt {} + } elseif { [string compare "cmw" "$platform"] } { + # Turn session paging off + # Comware 5/7 only. + # Comware 3 models have a screen-length command that only works on + # a vty basis + send -h "screen-length disable\r" + expect -re $prompt {} + } else { + send "disable clipaging\r" + expect -re $prompt {} + } + } + if { $do_command } { + if {[run_commands $prompt $command]} { + incr exitval + continue + } + } elseif { $do_script } { + source $sfile + catch {close}; + } else { + label $router + log_user 1 + interact + } + + # End of for each router + catch {wait}; + sleep 0.3 +} +exit $exitval Property changes on: files/cmwlogin ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: files/comware7_types.conf =================================================================== --- files/comware7_types.conf (revision 0) +++ files/comware7_types.conf (working copy) @@ -0,0 +1,58 @@ +# +# Comware devices v3.11 +# source: https://sites.google.com/site/jrbinks/code/rancid/cmwrancid +cmw;script;rancid -t cmw +cmw;login;cmwlogin +cmw;module;cmw +cmw;inloop;cmw::inloop +cmw;command;cmw::CommentOutput;display version +cmw;command;cmw::CommentOutput;display boot-loader +cmw;command;cmw::CommentOutput;display startup +cmw;command;cmw::CommentOutput;dir /all +cmw;command;cmw::CommentOutput;dir /all unit2>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot2#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit3>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot3#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit4>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot4#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit5>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot5#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit6>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot6#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit7>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot7#flash:/ +cmw;command;cmw::CommentOutput;dir /all unit8>flash:/ +cmw;command;cmw::CommentOutput;dir /all slot8#flash:/ +# Commands relating to the hardware: +cmw;command;cmw::CommentOutput;display device +cmw;command;cmw::CommentOutput;display device manuinfo +cmw;command;cmw::CommentOutput;display fan +cmw;command;cmw::CommentOutput;display power +cmw;command;cmw::CommentOutput;display poe powersupply +cmw;command;cmw::CommentOutput;display poe temperature-protection +cmw;command;cmw::CommentOutput;display transceiver interface +# Commands relating to authentication: +cmw;command;cmw::CommentOutput;display cluster +cmw;command;cmw::CommentOutput;display domain +cmw;command;cmw::CommentOutput;display local-user +cmw;command;cmw::CommentOutput;display password-control +cmw;command;cmw::CommentOutput;display password-control super +cmw;command;cmw::CommentOutput;display ssh server status +# Commands relating to system state: +cmw;command;cmw::CommentOutput;display irf +cmw;command;cmw::CommentOutput;display xrn-fabric +cmw;command;cmw::CommentOutput;display ftm topology-database +cmw;command;cmw::DisplayFib;display fib +cmw;command;cmw::DisplayIPRoutes;display ip routing-table +cmw;command;cmw::CommentOutput;display ospf +cmw;command;cmw::CommentOutput;display ospf brief +cmw;command;cmw::CommentOutput;display vlan all +cmw;command;cmw::CommentOutput;display lacp sys +cmw;command;cmw::CommentOutput;display link-aggregation summary +cmw;command;cmw::CommentOutput;display link-aggregation verbose +cmw;command;cmw::CommentOutput;display loopback-detection +cmw;command;cmw::CommentOutput;display mirror all +cmw;command;cmw::CommentOutput;display ntp-service status +cmw;command;cmw::CommentOutput;display stp root +# And the system config itself: +cmw;command;cmw::DisplayCurrent;display current-configuration Property changes on: files/comware7_types.conf ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: pkg-plist =================================================================== --- pkg-plist (revision 414774) +++ pkg-plist (working copy) @@ -3,6 +3,7 @@ lib/rancid/acos.pm lib/rancid/arbor.pm lib/rancid/ciscowlc.pm +lib/rancid/cmw.pm lib/rancid/dell.pm lib/rancid/eos.pm lib/rancid/foundry.pm @@ -27,6 +28,7 @@ libexec/rancid/brancid libexec/rancid/cat5rancid libexec/rancid/clogin +libexec/rancid/cmwlogin libexec/rancid/complogin libexec/rancid/control_rancid libexec/rancid/cssrancid