FreeBSD Bugzilla – Attachment 170094 Details for
Bug 209361
[patch] net-mgmt/rancid3 add Comware7 support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Comware7 support
rancid3_comware7.diff (text/plain), 53.03 KB, created by
Olli Hauer
on 2016-05-07 15:18:55 UTC
(
hide
)
Description:
Comware7 support
Filename:
MIME Type:
Creator:
Olli Hauer
Created:
2016-05-07 15:18:55 UTC
Size:
53.03 KB
patch
obsolete
>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 ^M<router>display 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<removed>$'\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<removed>$'\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("","","","! <removed>\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 <tab> 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 <SPACE> to cont\[^\r\n]*" { >+ send " " >+ # bloody ^[[2K after " " >+ expect { >+ -re "^\[^\r\n]*\r" {} >+ } >+ exp_continue >+ } >+ -re "^ *--More--\[^\n\r]*" { >+ send " " >+ exp_continue } >+ -re "^<-+ More -+>\[^\n\r]*" { >+ send_user -- "$expect_out(buffer)" >+ send " " >+ exp_continue } >+ -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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 209361
: 170094