Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43920
  • 博文数量: 9
  • 博客积分: 237
  • 博客等级: 二等列兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-07 17:49
文章分类

全部博文(9)

文章存档

2015年(1)

2014年(1)

2012年(2)

2011年(5)

我的朋友

分类: 网络与安全

2015-01-08 16:32:54

rancid暂时用北电的刀片交换机用alteon的alogin脚本测试,登录不了。
h3c的脚本从google group上下载一份下来先。
出处:https://sites.google.com/site/jrbinks/code/rancid/h3c
h3crancid

点击(此处)折叠或打开

  1. #! /usr/bin/perl5
  2. ##
  3. ## $Id: $
  4. ##
  5. ## @PACKAGE@ @VERSION@
  6. ## Copyright (c) 1997-2009 by Terrapin Communications, Inc.
  7. ## All rights reserved.
  8. ##
  9. ## This code is derived from software contributed to and maintained by
  10. ## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
  11. ## Pete Whiting, Austin Schutz, and Andrew Fort.
  12. ##
  13. ## Redistribution and use in source and binary forms, with or without
  14. ## modification, are permitted provided that the following conditions
  15. ## are met:
  16. ## 1. Redistributions of source code must retain the above copyright
  17. ## notice, this list of conditions and the following disclaimer.
  18. ## 2. Redistributions in binary form must reproduce the above copyright
  19. ## notice, this list of conditions and the following disclaimer in the
  20. ## documentation and/or other materials provided with the distribution.
  21. ## 3. All advertising materials mentioning features or use of this software
  22. ## must display the following acknowledgement:
  23. ## This product includes software developed by Terrapin Communications,
  24. ## Inc. and its contributors for RANCID.
  25. ## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
  26. ## contributors may be used to endorse or promote products derived from
  27. ## this software without specific prior written permission.
  28. ## 5. It is requested that non-binding fixes and modifications be contributed
  29. ## back to Terrapin Communications, Inc.
  30. ##
  31. ## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
  32. ## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  33. ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34. ## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
  35. ## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  36. ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  37. ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  38. ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  39. ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41. ## POSSIBILITY OF SUCH DAMAGE.
  42. #
  43. # RANCID - Really Awesome New Cisco confIg Differ
  44. #

  45. #
  46. # h3crancid
  47. #
  48. # h3clogin/h3crancid covers the following product ranges:
  49. #
  50. # * 3Com SuperStack 4 (post-joint venture with Huawei)
  51. # * H3C
  52. # * HP Networking ('A' & some 'E' portfolio, post 2010 3Com acquitision)
  53. #
  54. # They may also work with some Huawei equipment.
  55. #
  56. # https://sites.google.com/site/jrbinks/code/rancid/h3c
  57. #

  58. #
  59. # Usage: h3crancid [-dV] [-l] [-f filename | hostname]
  60. #

  61. # Notable changes from standard *rancid programs:
  62. #
  63. # * abstracted to path to the 'tail' utility
  64. # * altered "cisco_cmds" to be "device_cmds"
  65. # * define and use $logincmd
  66. #

  67. # TODO:
  68. #
  69. # It may be useful to pull common subroutines like the sorting ones into
  70. # a library for use by all the *rancid programs.
  71. #

  72. ############################################################################
  73. # END-USER TWEAKS

  74. # The login program to use. If no path is given, $PATH is searched:
  75. #my $logincmd = "h3clogin99";
  76. my $logincmd = "h3clogin";
  77. #my $logincmd = "/usr/local/libexec/h3clogin";
  78. #
  79. # Enable display of the FIB:
  80. my $display_fib = 1;
  81. #
  82. # Enable display of the routing table:
  83. # (no-op)
  84. #my $display_iproutes = 1;

  85. # END OF END-USER TWEAKS
  86. #############################################################################

  87. use Getopt::Std;
  88. getopts('dflV');
  89. if ($opt_V) {
  90.     print "@PACKAGE@ @VERSION@\n";
  91.     exit(0);
  92. }
  93. $log = $opt_l;
  94. $debug = $opt_d;
  95. $file = $opt_f;
  96. $host = $ARGV[0];
  97. $clean_run = 0;
  98. $found_end = 0;
  99. #$timeo = 90;            # login command timeout in seconds
  100. $timeo = 20;            # login command timeout in seconds

  101. my $TAIL = "/usr/bin/tail";

  102. my(@commandtable, %commands, @commands);# command lists
  103. my($aclsort) = ("ipsort");        # ACL sorting mode
  104. my($filter_commstr);            # SNMP community string filtering
  105. my($filter_pwds);            # password filtering mode

  106. # This routine is used to print out the router configuration
  107. sub ProcessHistory {
  108.     my($new_hist_tag,$new_command,$command_string,@string)=(@_);
  109.     if((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
  110.        && defined %history) {
  111.     print eval "$command \%history";
  112.     undef %history;
  113.     }
  114.     if (($new_hist_tag) && ($new_command) && ($command_string)) {
  115.     if ($history{$command_string}) {
  116.         $history{$command_string} = "$history{$command_string}@string";
  117.     } else {
  118.         $history{$command_string} = "@string";
  119.     }
  120.     } elsif (($new_hist_tag) && ($new_command)) {
  121.     $history{++$#history} = "@string";
  122.     } else {
  123.     print "@string";
  124.     }
  125.     $hist_tag = $new_hist_tag;
  126.     $command = $new_command;
  127.     1;
  128. }

  129. sub numerically { $a <=> $b; }

  130. # This is a sort routine that will sort numerically on the
  131. # keys of a hash as if it were a normal array.
  132. sub keynsort {
  133.     local(%lines)=@_;
  134.     local($i) = 0;
  135.     local(@sorted_lines);
  136.     foreach $key (sort numerically keys(%lines)) {
  137.     $sorted_lines[$i] = $lines{$key};
  138.     $i++;
  139.     }
  140.     @sorted_lines;
  141. }

  142. # This is a sort routine that will sort on the
  143. # keys of a hash as if it were a normal array.
  144. sub keysort {
  145.     local(%lines)=@_;
  146.     local($i) = 0;
  147.     local(@sorted_lines);
  148.     foreach $key (sort keys(%lines)) {
  149.     $sorted_lines[$i] = $lines{$key};
  150.     $i++;
  151.     }
  152.     @sorted_lines;
  153. }

  154. # This is a sort routine that will sort on the
  155. # values of a hash as if it were a normal array.
  156. sub valsort{
  157.     local(%lines)=@_;
  158.     local($i) = 0;
  159.     local(@sorted_lines);
  160.     foreach $key (sort values %lines) {
  161.         $sorted_lines[$i] = $key;
  162.         $i++;
  163.     }
  164.     @sorted_lines;
  165. }

  166. # This is a numerical sort routine (ascending).
  167. sub numsort {
  168.     local(%lines)=@_;
  169.     local($i) = 0;
  170.     local(@sorted_lines);
  171.     foreach $num (sort {$a <=> $b} keys %lines) {
  172.     $sorted_lines[$i] = $lines{$num};
  173.     $i++;
  174.     }
  175.     @sorted_lines;
  176. }

  177. # This is a sort routine that will sort on the
  178. # ip address when the ip address is anywhere in
  179. # the strings.
  180. sub ipsort {
  181.     local(%lines)=@_;
  182.     local($i) = 0;
  183.     local(@sorted_lines);
  184.     foreach $addr (sort sortbyipaddr keys %lines) {
  185.     $sorted_lines[$i] = $lines{$addr};
  186.     $i++;
  187.     }
  188.     @sorted_lines;
  189. }

  190. # These two routines will sort based upon IP addresses
  191. sub ipaddrval {
  192.     my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
  193.     $a[3]+256*($a[2]+256*($a[1]+256*$a[0]));
  194. }
  195. sub sortbyipaddr {
  196.     &ipaddrval($a) <=> &ipaddrval($b);
  197. }

  198. sub filter_lines {
  199.     my ($l) = (@_);
  200. # print STDERR " In filterlines: $l\n" if ($debug);

  201.     # Filter out some ANSI crud as a result of us not being able to turn
  202.     # off per-session terminal paging:
  203.     # h3c:
  204.     #s/^\033\[42D +\033\[42D(.+)$/$1/;
  205.     # hwlogin+mods:
  206.     #s/\033\133\064\062\104\s*\033\133\064\062\104//g;
  207.     $l =~ s/\033\133\064\062\104\s+\033\133\064\062\104//g;
  208.     $l =~ s/\033\133\061\066\104\s+\033\133\061\066\104//g;
  209.     $l =~ s/\033\133\064\062\104//g;
  210.     $l =~ s/\033\133\061\062\104//g;
  211.     # Probably not needed:
  212.     $l =~ s/\s*---- More ----\s*//;
  213. # print STDERR "out: $l\n" if ($debug);
  214.     return $l;
  215. }

  216. sub DisplayFib {
  217.     ## We should probably guarantee that the FIB is sorted properly
  218.     print STDERR " In DisplayFib: $_" if ($debug);

  219.     return(1) if $display_fib == 0;
  220.     chomp;

  221.     # Display the command we're processing in the output:
  222.     s/^[\[<].*?[\]>]\a?\s?(.*)/\'$1\':/g;
  223.     ProcessHistory("COMMENTS","keysort","A0","! $_\n!\n");

  224.     while () {
  225.         tr/\015//d;
  226.         last if(/^$prompt/);
  227.         chomp;
  228.         # skip blank lines
  229.         return(1) if /^\s+\^$/;
  230.         $_ = filter_lines($_);

  231.         # make this a subroutine:
  232.         return(1) if /% Too many parameters found at '\^' position/;
  233.         return(1) if /% Unrecognized command found at '\^' position/;
  234.         return(1) if /% Wrong parameter found at '\^' position/;
  235.         return(1) if /% Wrong device .+/;

  236.         # Chop out some detail that changes over time:
  237.         s/(\s+)TimeStamp\s+/$1/;
  238.         s/(\s+)t\[\d+\]\s+/$1/;

  239.         ProcessHistory("COMMENTS","ipsort","A0","! $_\n");
  240.         #ProcessHistory("COMMENTS","keysort","A0","! $_\n");
  241.     }
  242.     ProcessHistory("COMMENTS","keysort","A0","! \n");
  243.     return(0);
  244. }


  245. # This routine processes general output of "display" commands
  246. sub CommentOutput {
  247.     print STDERR " In CommentOutput: $_" if ($debug);

  248.     chomp;

  249.     # Display the command we're processing in the output:
  250.     s/^[\[<].*?[\]>]\a?\s?(.*)/\'$1\':/g;
  251.     ProcessHistory("","","","! $_\n!\n");

  252.     # eat the header line
  253. # $junk = ;
  254.     # now just copy it mostly verbatim to the history file
  255.     while () {
  256.         tr/\015//d;

  257.         # If we find the prompt, we're done
  258.         #last if(/^<.*>/);
  259.         last if(/^$prompt/);
  260.         chomp;

  261.         # skip blank lines
  262.         return(1) if /^\s+\^$/;

  263.         $_ = filter_lines($_);

  264.     # Filter out some ANSI crud as a result of us not being able to turn
  265.     # off per-session terminal paging:
  266.     # h3c:
  267.     #s/^\033\[42D +\033\[42D(.+)$/$1/;
  268.     # hwlogin+mods:
  269.         #s/\033\133\064\062\104\s*\033\133\064\062\104//g;
  270. # s/\033\133\064\062\104\s+\033\133\064\062\104//g;
  271. # s/\033\133\061\066\104\s+\033\133\061\066\104//g;
  272.     #s/\033\133\064\062\104//g;
  273.     # Probably not needed:
  274. # s/\s*---- More ----\s*//;

  275.         # make this a subroutine:
  276.         # Some commands are not supported on some models or versions
  277.         # of code. These lines simply remove the associated error
  278.         # messages:
  279.         return(1) if /% Too many parameters found at '\^' position/;
  280.         return(1) if /% Unrecognized command found at '\^' position/;
  281.         return(1) if /% Wrong parameter found at '\^' position/;
  282.         return(1) if /% Wrong device .+/;

  283.         # Parts of the output of some commands changes over time, but we don't
  284.         # want these changes to trigger a rancid notification, so we
  285.         # filter them out:

  286.         # This is part of one line, just cut it out:
  287.         s/\s+Current AccessNum:.+$//;

  288.         if (/^(PSE Total Power Consumption|PSE Available Power|PSE Peak Value|PSE Average Value).+$/) {
  289.             next;
  290.         }

  291.         s/(.*)uptime.*days*.*hours*.*minutes*(.*)/$1 $2/;

  292.         ProcessHistory("","","","! $_\n");
  293.     }

  294.     ProcessHistory("","","","! \n");
  295.     return(0);
  296. }

  297. ## This routine processes a "display current"
  298. sub DisplayCurrent {
  299.     print STDERR " In DisplayCurrent: $_" if ($debug);

  300.     while () {
  301.     tr/\015//d;
  302.     last if(/^$prompt/);

  303.         $_ = filter_lines($_);

  304.     # Filter out some ANSI crud as a result of us not being able to turn
  305.     # off per-session terminal paging:
  306.     # h3c:
  307.     #s/^\033\[42D +\033\[42D(.+)$/$1/;
  308.     # hwlogin+mods:
  309.     #s/\033\133\064\062\104\s*\033\133\064\062\104//g;
  310. # s/\033\133\064\062\104\s+\033\133\064\062\104//g;
  311. # s/\033\133\061\066\104\s+\033\133\061\066\104//g;
  312. # s/\033\133\064\062\104//g;
  313.     # Probably not needed:
  314. # s/\s*---- More ----\s*//;

  315.     # Filter out some sensitive data:
  316.     if (/^( ?snmp-agent community (read|write) )(\S+)/ &&
  317.         $filter_commstr == 0) {
  318.         ProcessHistory("","","","!$1$'");
  319.         next;
  320.     }

  321.     ProcessHistory("","","","$_");

  322.     # end of config
  323.     
  324.     if (/^return/) {
  325.         $found_end = 1;
  326.         return(0);
  327.     }
  328.     }
  329.     return(0);
  330. }

  331. # dummy function
  332. sub DoNothing {print STDOUT;}

  333. # Main
  334. ## Not all commands are supported on all models and code versions
  335. ## Not all of these should necessarily be included
  336. @commandtable = (
  337.     {'display version'            => 'CommentOutput'},
  338.     {'display boot-loader'        => 'CommentOutput'},
  339.     {'dir /all unit1>flash:/'        => 'CommentOutput'},
  340.     {'dir /all unit2>flash:/'        => 'CommentOutput'},
  341.     {'dir /all unit3>flash:/'        => 'CommentOutput'},
  342.     {'dir /all unit4>flash:/'        => 'CommentOutput'},
  343.     {'dir /all unit5>flash:/'        => 'CommentOutput'},
  344.     {'dir /all unit6>flash:/'        => 'CommentOutput'},
  345.     {'dir /all unit7>flash:/'        => 'CommentOutput'},
  346.     {'dir /all unit8>flash:/'        => 'CommentOutput'},
  347.     {'display device'            => 'CommentOutput'},
  348.     {'display device manuinfo'        => 'CommentOutput'},
  349.     {'display irf'            => 'CommentOutput'},
  350.     {'display xrn-fabric'        => 'CommentOutput'},
  351.     {'display ftm topology-database'    => 'CommentOutput'},
  352.     {'display fan'            => 'CommentOutput'},
  353.     {'display power'            => 'CommentOutput'},
  354.     {'display poe powersupply'        => 'CommentOutput'},
  355.     {'display poe temperature-protection'    => 'CommentOutput'},
  356.     {'display cluster'            => 'CommentOutput'},
  357.     {'display domain'            => 'CommentOutput'},
  358.     {'display local-user'        => 'CommentOutput'},
  359.     {'display password-control'        => 'CommentOutput'},
  360.     {'display password-control super'    => 'CommentOutput'},
  361.     {'display ssh server status'    => 'CommentOutput'},
  362.     {'display fib'            => 'DisplayFib'},
  363.     {'display vlan all'            => 'CommentOutput'},
  364.     {'display ip routing-table'        => 'CommentOutput'},
  365.     {'display lacp sys'            => 'CommentOutput'},
  366.     {'display link-aggregation summary'    => 'CommentOutput'},
  367.     {'display link-aggregation verbose'    => 'CommentOutput'},
  368.     {'display mirror all'        => 'CommentOutput'},
  369.     {'display current-configuration'    => 'DisplayCurrent'},
  370. );

  371. # Use an array to preserve the order of the commands and a hash for mapping
  372. # commands to the subroutine and track commands that have been completed.
  373. @commands = map(keys(%$_), @commandtable);
  374. %commands = map(%$_, @commandtable);

  375. $device_cmds=join(";",@commands);
  376. $cmds_regexp=join("|",@commands);

  377. if (length($host) == 0) {
  378.     if ($file) {
  379.         print(STDERR "Too few arguments: file name required\n");
  380.         exit(1);
  381.     } else {
  382.         print(STDERR "Too few arguments: host name required\n");
  383.         exit(1);
  384.     }
  385. }
  386. open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
  387. select(OUTPUT);
  388. # make OUTPUT unbuffered if debugging
  389. if ($debug) { $| = 1; }

  390. if ($file) {
  391.     print STDERR "opening file $host\n" if ($debug);
  392.     print STDOUT "opening file $host\n" if ($log);
  393.     open(INPUT,"<$host") || die "open failed for $host: $!\n";
  394. } else {
  395.     print STDERR "executing $logincmd -t $timeo -c\"$device_cmds\" $host\n" if ($debug);
  396.     print STDOUT "executing $logincmd -t $timeo -c\"$device_cmds\" $host\n" if ($log);
  397.     if (defined($ENV{NOPIPE}) && $ENV{NOPIPE} =~ /^YES/i) {
  398. #    system "$logincmd -noenable -t $timeo -c \"$device_cmds\" $host $host.raw 2>&1" || die "$logincmd failed for $host: $!\n";
  399. # system "$logincmd -t $timeo -c \"$device_cmds\" $host $host.raw 2>&1" || die "$logincmd failed for $host: $!\n";
  400.     system "$logincmd -t $timeo -c \"$device_cmds\" $host $host.raw 2>&1" || die "$logincmd failed for $host: $!\n";
  401.     open(INPUT, "< $host.raw") || die "$logincmd failed for $host: $!\n";
  402.     } else {
  403. #    open(INPUT,"$logincmd -noenable -t $timeo -c \"$device_cmds\" $host
  404.     open(INPUT,"$logincmd -t $timeo -c \"$device_cmds\" $host
  405.     }
  406. }

  407. # determine ACL sorting mode
  408. if ($ENV{"ACLSORT"} =~ /no/i) {
  409.     $aclsort = "";
  410. }
  411. # determine community string filtering mode
  412. if (defined($ENV{"NOCOMMSTR"}) &&
  413.     ($ENV{"NOCOMMSTR"} =~ /yes/i || $ENV{"NOCOMMSTR"} =~ /^$/)) {
  414.     $filter_commstr = 1;
  415. } else {
  416.     $filter_commstr = 0;
  417. }
  418. # determine password filtering mode
  419. if ($ENV{"FILTER_PWDS"} =~ /no/i) {
  420.     $filter_pwds = 0;
  421. } elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
  422.     $filter_pwds = 2;
  423. } else {
  424.     $filter_pwds = 1;
  425. }

  426. ProcessHistory("","","","!RANCID-CONTENT-TYPE: h3c\n!\n");
  427. #ProcessHistory("COMMENTS","keysort","B0","!\n");
  428. #ProcessHistory("COMMENTS","keysort","D0","!\n");
  429. #ProcessHistory("COMMENTS","keysort","F0","!\n");
  430. #ProcessHistory("COMMENTS","keysort","G0","!\n");
  431. TOP: while() {
  432.     tr/\015//d;
  433. # h3c:
  434. # Look for the command at the end of the output
  435. # if (/\#exit$/) {
  436. # if (/\#quit$/) {
  437. # h3c:
  438.      if (/[\]>]\a?\s*quit/) {
  439. # if (/^[\[<].*[\]>]\a?\s?quit/) {
  440.       $clean_run=1;
  441.       last;
  442.     }
  443.     if (/^Error:/) {
  444.     print STDOUT ("$host $logincmd error: $_");
  445.     print STDERR ("$host $logincmd error: $_") if ($debug);
  446.     $clean_run=0;
  447.     last;
  448.     }
  449. # while (/#\s*($cmds_regexp)\s*$/) {
  450. # h3c:
  451.     while (/[\]>]\a?\s*($cmds_regexp)\s*$/) {
  452. # while (/^[\[<].*[\]>]\a?\s*($cmds_regexp)\s*$/) {
  453.     $cmd = $1;
  454.     if (!defined($prompt)) {
  455.     # h3c:
  456.     # Extract the prompt: look for something not [ or < at the start
  457.     # of the line, until either ] or > is reached:
  458.         #$prompt = ($_ =~ /^([^#]+#)/)[0];
  459.         #$prompt =~ s/([][}{)(\\])/\\$1/g;
  460.         #$prompt = ($_ =~ /^([^\]>]+[\]>]\007?)/)[0];
  461.         $prompt = ($_ =~ /^([^\]>]+[\]>]\a?)/)[0];
  462.         $prompt =~ s/([][}{)(\\])/\\$1/g;
  463.     print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
  464.     }
  465.     print STDERR ("HIT COMMAND:$_") if ($debug);
  466.     if (! defined($commands{$cmd})) {
  467.         print STDERR "$host: found unexpected command - \"$cmd\"\n";
  468.         $clean_run = 0;
  469.         last TOP;
  470.     }
  471.     $rval = &{$commands{$cmd}};
  472.     delete($commands{$cmd});
  473.     if ($rval == -1) {
  474.         $clean_run = 0;
  475.         last TOP;
  476.     }
  477.     }
  478. }
  479. print STDOUT "Done $logincmd: $_\n" if ($log);
  480. # Flush History
  481. ProcessHistory("","","","");
  482. # Cleanup
  483. close(INPUT);
  484. close(OUTPUT);

  485. if (defined($ENV{NOPIPE}) && $ENV{NOPIPE} =~ /^YES/i) {
  486.     unlink("$host.raw") if (! $debug);
  487. }

  488. printf(STDOUT "$host: clean_run=$clean_run found_end=$found_end\n") if ($debug);

  489. # check for completeness
  490. if (scalar(%commands) || !$clean_run || !$found_end) {
  491.     if (scalar(%commands)) {
  492.     printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
  493.     printf(STDERR "$host: missed cmd(s): %s\n", join(',

h3clogin

点击(此处)折叠或打开

  1. #! /usr/local/bin/expect --
  2. ##
  3. ## $Id: $
  4. ##
  5. ## @PACKAGE@ @VERSION@
  6. ## Copyright (c) 1997-2009 by Terrapin Communications, Inc.
  7. ## All rights reserved.
  8. ##
  9. ## This code is derived from software contributed to and maintained by
  10. ## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
  11. ## Pete Whiting, Austin Schutz, and Andrew Fort.
  12. ##
  13. ## Redistribution and use in source and binary forms, with or without
  14. ## modification, are permitted provided that the following conditions
  15. ## are met:
  16. ## 1. Redistributions of source code must retain the above copyright
  17. ## notice, this list of conditions and the following disclaimer.
  18. ## 2. Redistributions in binary form must reproduce the above copyright
  19. ## notice, this list of conditions and the following disclaimer in the
  20. ## documentation and/or other materials provided with the distribution.
  21. ## 3. All advertising materials mentioning features or use of this software
  22. ## must display the following acknowledgement:
  23. ## This product includes software developed by Terrapin Communications,
  24. ## Inc. and its contributors for RANCID.
  25. ## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
  26. ## contributors may be used to endorse or promote products derived from
  27. ## this software without specific prior written permission.
  28. ## 5. It is requested that non-binding fixes and modifications be contributed
  29. ## back to Terrapin Communications, Inc.
  30. ##
  31. ## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
  32. ## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  33. ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34. ## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
  35. ## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  36. ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  37. ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  38. ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  39. ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41. ## POSSIBILITY OF SUCH DAMAGE.
  42. #
  43. # The expect login scripts were based on Erik Sherk's gwtn, by permission.

  44. #
  45. # h3clogin - H3C login
  46. #
  47. # h3clogin covers the following product ranges:
  48. #
  49. # * 3Com SuperStack 4 (post-joint venture with Huawei)
  50. # * H3C
  51. # * HP Networking ('A' & some 'E' portfolio, post 2010 3Com acquitision)
  52. #
  53. # It may also work with some Huawei equipment.
  54. #

  55. # Set to 1 to enable some debugging, or pass "-d" on command line
  56. exp_internal 0

  57. # Usage line
  58. set usage "Usage: $argv0 \[-dSV\] \[-autoenable\] \[-noenable\] \[-c command\] \
  59. \[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
  60. \[-r passphrase\] \[-s script-file\] \[-t timeout\] \[-u username\] \
  61. \[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
  62. \[-y ssh_cypher_type\] router \[router...\]\n"

  63. # env(CLOGIN) may contain:
  64. #    x == do not set xterm banner or name

  65. # Password file
  66. set password_file $env(HOME)/.cloginrc
  67. # Default is to login to the router
  68. set do_command 0
  69. set do_script 0
  70. # The default is to automatically enable
  71. set avenable 1
  72. # The default is that you login non-enabled (tacacs can have you login already
  73. # enabled)
  74. set avautoenable 0
  75. # The default is to look in the password file to find the passwords. This
  76. # tracks if we receive them on the command line.
  77. set do_passwd 1
  78. set do_enapasswd 1
  79. set do_saveconfig 0
  80. # Sometimes routers take awhile to answer (the default is 10 sec)
  81. set timeoutdflt 45
  82. #
  83. set send_human {.1 .3 .7 .05 2}

  84. # H3C: some models don't like "3des"; specify "aes128-cbc" in .cloginrc
  85. set default_cyphertype "3des"

  86. # H3C: command to elevate priviges (aka "enable") is different
  87. set enacmd "super"

  88. # H3C: command to exit from device
  89. set exitcmd "quit"

  90. # Find the user in the ENV, or use the unix userid.
  91. if {[ info exists env(CISCO_USER) ] } {
  92.     set default_user $env(CISCO_USER)
  93. } elseif {[ info exists env(USER) ]} {
  94.     set default_user $env(USER)
  95. } elseif {[ info exists env(LOGNAME) ]} {
  96.     set default_user $env(LOGNAME)
  97. } else {
  98.     # This uses "id" which I think is portable. At least it has existed
  99.     # (without options) on all machines/OSes I've been on recently -
  100.     # unlike whoami or id -nu.
  101.     if [ catch {exec id} reason ] {
  102.     send_error "\nError: could not exec id: $reason\n"
  103.     exit 1
  104.     }
  105.     regexp {\(([^)]*)} "$reason" junk default_user
  106. }

  107. # Process the command line
  108. for {set i 0} {$i < $argc} {incr i} {
  109.     set arg [lindex $argv $i]

  110.     switch -glob -- $arg {
  111.     # Expect debug mode
  112.     -d* {
  113.      exp_internal 1
  114.     # Username
  115.     } -u* {
  116.      if {! [ regexp .\[uU\](.+) $arg ignore user]} {
  117.         incr i
  118.         set username [ lindex $argv $i ]
  119.      }
  120.     # VTY Password
  121.     } -p* {
  122.      if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} {
  123.         incr i
  124.         set userpasswd [ lindex $argv $i ]
  125.      }
  126.      set do_passwd 0
  127.     # ssh passphrase
  128.     } -r* {
  129.      if {! [ regexp .\[rR\](.+) $arg ignore passphrase]} {
  130.      incr i
  131.      set vapassphrase [ lindex $argv $i ]
  132.      }
  133.     # VTY Password
  134.     } -v* {
  135.      if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
  136.         incr i
  137.         set passwd [ lindex $argv $i ]
  138.      }
  139.      set do_passwd 0
  140.     # Version string
  141.     } -V* {
  142.      send_user "@PACKAGE@ @VERSION@\n"
  143.      exit 0
  144.     # Enable Username
  145.     } -w* {
  146.      if {! [ regexp .\[wW\](.+) $arg ignore enauser]} {
  147.         incr i
  148.         set enausername [ lindex $argv $i ]
  149.      }
  150.     # Environment variable to pass to -s scripts
  151.     } -E* {
  152.      if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
  153.         set E$varname $varvalue
  154.      } else {
  155.         send_user "\nError: invalid format for -E in $arg\n"
  156.         exit 1
  157.      }
  158.     # Enable Password
  159.     } -e* {
  160.      if {! [ regexp .\[e\](.+) $arg ignore enapasswd]} {
  161.         incr i
  162.         set enapasswd [ lindex $argv $i ]
  163.      }
  164.      set do_enapasswd 0
  165.     # Command to run.
  166.     } -c* {
  167.      if {! [ regexp .\[cC\](.+) $arg ignore command]} {
  168.         incr i
  169.         set command [ lindex $argv $i ]
  170.      }
  171.      set do_command 1
  172.     # Expect script to run.
  173.     } -s* {
  174.      if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
  175.         incr i
  176.         set sfile [ lindex $argv $i ]
  177.      }
  178.      if { ! [ file readable $sfile ] } {
  179.         send_user "\nError: Can't read $sfile\n"
  180.         exit 1
  181.      }
  182.      set do_script 1
  183.     # save config on exit
  184.     } -S* {
  185.      set do_saveconfig 1
  186.     # 'ssh -c' cypher type
  187.     } -y* {
  188.      if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
  189.         incr i
  190.         set cypher [ lindex $argv $i ]
  191.      }
  192.     # alternate cloginrc file
  193.     } -f* {
  194.      if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
  195.         incr i
  196.         set password_file [ lindex $argv $i ]
  197.      }
  198.     # Timeout
  199.     } -t* {
  200.      if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
  201.         incr i
  202.      set timeoutdflt [ lindex $argv $i ]
  203.      }
  204.     # Command file
  205.     } -x* {
  206.      if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
  207.         incr i
  208.         set cmd_file [ lindex $argv $i ]
  209.      }
  210.      if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
  211.         send_user "\nError: $reason\n"
  212.         exit 1
  213.      }
  214.      set cmd_text [read $cmd_fd]
  215.      close $cmd_fd
  216.      set command [join [split $cmd_text \n] \;]
  217.      set do_command 1
  218.     # Do we enable?
  219.     } -noenable {
  220.      set avenable 0
  221.     # Does tacacs automatically enable us?
  222.     } -autoenable {
  223.      set avautoenable 1
  224.      set avenable 0
  225.     } -* {
  226.      send_user "\nError: Unknown $arg\n"
  227.      send_user $usage
  228.      exit 1
  229.     } default {
  230.      break
  231.     }
  232.     }
  233. }
  234. # Process routers...no routers listed is an error.
  235. if { $i == $argc } {
  236.     send_user "\nError: $usage"
  237. }

  238. # Only be quiet if we are running a script (it can log its output
  239. # on its own)
  240. if { $do_script } {
  241.     log_user 0
  242. } else {
  243.     log_user 1
  244. }

  245. #
  246. # Done configuration/variable setting. Now run with it...
  247. #

  248. # Sets Xterm title if interactive...if its an xterm and the user cares
  249. proc label { host } {
  250.     global env
  251.     # if CLOGIN has an 'x' in it, don't set the xterm name/banner
  252.     if [info exists env(CLOGIN)] {
  253.     if {[string first "x" $env(CLOGIN)] != -1} { return }
  254.     }
  255.     # take host from ENV(TERM)
  256.     if [info exists env(TERM)] {
  257.     if [regexp \^(xterm|vs) $env(TERM) ignore ] {
  258.      send_user "\033]1;[lindex [split $host "."] 0]\a"
  259.      send_user "\033]2;$host\a"
  260.     }
  261.     }
  262. }

  263. # This is a helper function to make the password file easier to
  264. # maintain. Using this the password file has the form:
  265. # add password sl*    pete cow
  266. # add password at*    steve
  267. # add password *    hanky-pie
  268. proc add {var args} { global int_$var ; lappend int_$var $args}
  269. proc include {args} {
  270.     global env
  271.     regsub -all "(^{|}$)" $args {} args
  272.     if { [ regexp "^/" $args ignore ] == 0 } {
  273.     set args $env(HOME)/$args
  274.     }
  275.     source_password_file $args
  276. }

  277. proc find {var router} {
  278.     upvar int_$var list
  279.     if { [info exists list] } {
  280.     foreach line $list {
  281.      if { [string match [lindex $line 0] $router ] } {
  282.         return [lrange $line 1 end]
  283.      }
  284.     }
  285.     }
  286.     return {}
  287. }

  288. # Loads the password file. Note that as this file is tcl, and that
  289. # it is sourced, the user better know what to put in there, as it
  290. # could install more than just password info... I will assume however,
  291. # that a "bad guy" could just as easy put such code in the clogin
  292. # script, so I will leave .cloginrc as just an extention of that script
  293. proc source_password_file { password_file } {
  294.     global env
  295.     if { ! [file exists $password_file] } {
  296.     send_user "\nError: password file ($password_file) does not exist\n"
  297.     exit 1
  298.     }
  299.     file stat $password_file fileinfo
  300.     if { [expr ($fileinfo(mode) & 007)] != 0000 } {
  301.     send_user "\nError: $password_file must not be world readable/writable\n"
  302.     exit 1
  303.     }
  304.     if [ catch {source $password_file} reason ] {
  305.     send_user "\nError: $reason\n"
  306.     exit 1
  307.     }
  308. }

  309. # Log into the router.
  310. # returns: 0 on success, 1 on failure, -1 if rsh was used successfully
  311. proc login { router user userpswd passwd enapasswd cmethod cyphertype identfile } {
  312.     global spawn_id in_proc do_command do_script platform passphrase
  313.     global prompt prompt_match u_prompt p_prompt e_prompt sshcmd
  314.     set in_proc 1
  315.     set uprompt_seen 0

  316.     # try each of the connection methods in $cmethod until one is successful
  317.     set progs [llength $cmethod]
  318.     foreach prog [lrange $cmethod 0 end] {
  319.     incr progs -1
  320.     if [string match "telnet*" $prog] {
  321.      regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
  322.      if {"$port" == ""} {
  323.         set retval [ catch {spawn telnet $router} reason ]
  324.      } else {
  325.         set retval [ catch {spawn telnet $router $port} reason ]
  326.      }
  327.      if { $retval } {
  328.         send_user "\nError: telnet failed: $reason\n"
  329.         return 1
  330.      }
  331.     } elseif [string match "ssh*" $prog] {
  332.      # ssh to the router & try to login with or without an identfile.
  333.      regexp {ssh(:([^[:space:]]+))*} $prog command suffix port
  334.      set cmd [join [lindex $sshcmd 0] " "]
  335.      if {"$port" != ""} {
  336.         set cmd "$cmd -p $port"
  337.      }
  338.      if {"$identfile" != ""} {
  339.         set cmd "$cmd -i $identfile"
  340.      }
  341.      set retval [ catch {eval spawn [split "$cmd -c $cyphertype -x -l $user $router" { }]} reason ]
  342.      if { $retval } {
  343.         send_user "\nError: $sshcmd failed: $reason\n"
  344.         return 1
  345.      }
  346.     } elseif ![string compare $prog "rsh"] {
  347.      if { ! $do_command } {
  348.         if { [llength $cmethod] == 1 } {
  349.          send_user "\nError: rsh is an invalid method for -x and "
  350.          send_user "interactive logins\n"
  351.         }
  352.         if { $progs == 0 } {
  353.          return 1
  354.         }
  355.         continue;
  356.      }

  357.      set commands [split $command \;]
  358.      set num_commands [llength $commands]
  359.      set rshfail 0
  360.      for {set i 0} {$i < $num_commands && !$rshfail} { incr i} {
  361.         log_user 0
  362.         set retval [ catch {spawn rsh $user@$router [lindex $commands $i] } reason ]
  363.         if { $retval } {
  364.          send_user "\nError: rsh failed: $reason\n"
  365.          log_user 1; return 1
  366.         }
  367.         send_user "$router# [lindex $commands $i]\n"

  368.         # rcmd does not get a pager and no prompts, so we just have to
  369.         # look for failures & lines.
  370.         expect {
  371.          "Connection refused" { catch {close}; catch {wait};
  372.                      send_user "\nError: Connection\
  373.                          Refused ($prog): $router\n"
  374.                      set rshfail 1
  375.                     }
  376.          -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
  377.                      catch {close}; catch {wait};
  378.                      send_user "\nError: Connection\
  379.                          closed ($prog): $router\n"
  380.                      set rshfail 1
  381.                     }
  382.          "Host is unreachable" { catch {close}; catch {wait};
  383.                      send_user "\nError: Host Unreachable:\
  384.                          $router\n"
  385.                      set rshfail 1
  386.                     }
  387.          "No address associated with" {
  388.                      catch {close}; catch {wait};
  389.                      send_user "\nError: Unknown host\
  390.                          $router\n"
  391.                      set rshfail 1
  392.                     }
  393.          -re "\b+"     { exp_continue }
  394.          -re "\[\n\r]+"    { send_user -- "$expect_out(buffer)"
  395.                      exp_continue
  396.                     }
  397.          timeout     { catch {close}; catch {wait};
  398.                      send_user "\nError: TIMEOUT reached\n"
  399.                      set rshfail 1
  400.                     }
  401.          eof         { catch {close}; catch {wait}; }
  402.         }
  403.         log_user 1
  404.      }
  405.      if { $rshfail } {
  406.         if { !$progs } {
  407.          return 1
  408.         } else {
  409.          continue
  410.         }
  411.      }
  412.      # fake the end of the session for rancid.
  413.      send_user "$router# exit\n"
  414.      # return rsh "success"
  415.      return -1
  416.     } else {
  417.      puts "\nError: unknown connection method: $prog"
  418.      return 1
  419.     }
  420.     sleep 0.3

  421.     # This helps cleanup each expect clause.
  422.     expect_after {
  423.      timeout {
  424.         send_user "\nError: TIMEOUT reached\n"
  425.         catch {close}; catch {wait};
  426.         if { $in_proc} {
  427.          return 1
  428.         } else {
  429.          continue
  430.         }
  431.      } eof {
  432.         send_user "\nError: EOF received\n"
  433.         catch {close}; catch {wait};
  434.         if { $in_proc} {
  435.          return 1
  436.         } else {
  437.          continue
  438.         }
  439.      }
  440.     }

  441.     # Here we get a little tricky. There are several possibilities:
  442.     # the router can ask for a username and passwd and then
  443.     # talk to the TACACS server to authenticate you, or if the
  444.     # TACACS server is not working, then it will use the enable
  445.     # passwd. Or, the router might not have TACACS turned on,
  446.     # then it will just send the passwd.
  447.     # if telnet fails with connection refused, try ssh
  448.     expect {
  449.     -re "(Connection refused|Secure connection \[^\n\r]+ refused)" {
  450.      catch {close}; catch {wait};
  451.      if !$progs {
  452.         send_user "\nError: Connection Refused ($prog): $router\n"
  453.         return 1
  454.      }
  455.     }
  456.     -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
  457.      catch {close}; catch {wait};
  458.      if !$progs {
  459.         send_user "\nError: Connection closed ($prog): $router\n"
  460.         return 1
  461.      }
  462.     }
  463.     eof { send_user "\nError: Couldn't login: $router\n"; wait; return 1 }
  464.     -nocase "unknown host\r" {
  465.      send_user "\nError: Unknown host $router\n"; wait; return 1
  466.      catch {close}; catch {wait};
  467.      return 1
  468.     }
  469.     "Host is unreachable" {
  470.      send_user "\nError: Host Unreachable: $router\n";
  471.      catch {close}; catch {wait};
  472.      return 1
  473.     }
  474.     "No address associated with name" {
  475.      send_user "\nError: Unknown host $router\n";
  476.      catch {close}; catch {wait};
  477.      return 1
  478.     }
  479.     -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
  480.      send "yes\r"
  481.      send_user "\nHost $router added to the list of known hosts.\n"
  482.      exp_continue
  483.     }
  484.     -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
  485.      send "no\r"
  486.      send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n"
  487.      catch {close}; catch {wait};
  488.      return 1
  489.     }
  490.     -re "Offending key for .* \(yes\/no\)\?" {
  491.      send "no\r"
  492.      send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n"
  493.      catch {close}; catch {wait};
  494.      return 1
  495.     }
  496.     -re "(denied|Sorry)"    {
  497.                  send_user "\nError: Check your passwd for $router\n"
  498.                  catch {close}; catch {wait}; return 1
  499.                 }
  500.     "Login failed"        {
  501.                  send_user "\nError: Check your passwd for $router\n"
  502.                  catch {close}; catch {wait}; return 1
  503.                 }
  504.     -re "% (Bad passwords|Authentication failed)"    {
  505.                  send_user "\nError: Check your passwd for $router\n"
  506.                  catch {close}; catch {wait}; return 1
  507.                 }
  508.     "Press any key to continue." {
  509.                  # send_user "Pressing the ANY key\n"
  510.                  send "\r"
  511.                  exp_continue
  512.                 }
  513.     -re "Enter Selection: " {
  514.                  # Catalyst 1900s have some lame menu. Enter
  515.                  # K to reach a command-line.
  516.                  send "K\r"
  517.                  exp_continue;
  518.                 }
  519.     -re "Last login:"    {
  520.                  exp_continue;
  521.                 }
  522.     -re "@\[^\r\n]+ $p_prompt"    {
  523.                      # ssh pwd prompt
  524.                      sleep 1
  525.                      send "$userpswd\r"
  526.                      exp_continue
  527.                     }
  528.     -re "Enter passphrase.*: " {
  529.                  # sleep briefly to allow time for stty -echo
  530.                  sleep .3
  531.                  send -- "$passphrase\r"
  532.                  exp_continue
  533.                 }
  534.     -re "$u_prompt"        {
  535.                  send -- "$user\r"
  536.                  set uprompt_seen 1
  537.                  exp_continue
  538.                 }
  539.     -re "$p_prompt"        {
  540.                  sleep 1
  541.                  if {$uprompt_seen == 1} {
  542.                     send -- "$userpswd\r"
  543.                  } else {
  544.                     send -- "$passwd\r"
  545.                  }
  546.                  exp_continue
  547.                 }
  548.     -re "$prompt"        {
  549.                  set prompt_match $expect_out(0,string);
  550.                  break;
  551.                 }
  552.     "Login invalid"        {
  553.                  send_user "\nError: Invalid login: $router\n";
  554.                  catch {close}; catch {wait}; return 1
  555.                 }
  556.      }
  557.     }

  558.     set in_proc 0
  559.     return 0
  560. }

  561. # Enable
  562. proc do_enable { enauser enapasswd } {
  563.     global prompt in_proc
  564.     global prompt u_prompt e_prompt
  565.     global enacmd
  566.     set in_proc 1

  567.     send -h "$enacmd\r"
  568.     expect {
  569.     -re "$u_prompt"    { send -h -- "$enauser\r"; exp_continue}
  570.     -re "$e_prompt"    { send -h -- "$enapasswd\r"; exp_continue}
  571.     -re ">"        { set prompt ">" }
  572.     "% Password is not set." {
  573.              send_user "\nError: No 'super' password set for device\n"
  574.              return 1
  575.             }
  576.     "% Authenticate failed." {
  577.              send_user "\nError: Check your enable password for 'super'\n"
  578.              return 1
  579.             }
  580. #    "#"        { set prompt "#" }
  581. #    "(enable)"    { set prompt "> \\(enable\\) " }
  582.     #-re "(denied|Sorry|Incorrect)"    {
  583.     #         # % Access denied - from local auth and poss. others
  584.     #         send_user "\nError: Check your Enable passwd\n";
  585.     #         return 1
  586.     #        }
  587.     #"% Error in authentication" {
  588.     #         send_user "\nError: Check your Enable passwd\n"
  589.     #         return 1
  590.     #        }
  591.     #"% Bad passwords" {
  592.     #         send_user "\nError: Check your Enable passwd\n"
  593.     #         return 1
  594.     #        }
  595.     }
  596.     # We set the prompt variable (above) so script files don't need
  597.     # to know what it is.
  598.     set in_proc 0
  599.     return 0
  600. }

  601. # Run commands given on the command line.
  602. proc run_commands { prompt command } {
  603.     global do_saveconfig in_proc platform
  604.     global exitcmd
  605.     set in_proc 1

  606.     # clogin has this beast:
  607.     #regsub -all {^(.{1,11}).*([#>])$} $prompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
  608.     # escape any parens in the prompt, such as "(enable)"
  609.     regsub -all {[][)(]} $prompt {\\&} reprompt

  610.     expect {
  611.      -re $reprompt    {}
  612.      -re "\[\n\r]+"    { exp_continue }
  613.     }

  614.     # this is the only way i see to get rid of more prompts in o/p..grrrrr
  615.     log_user 0

  616.     set commands [split $command \;]
  617.     set num_commands [llength $commands]
  618.     # The pager can not be turned off on some 3Com/H3C, so we have to look
  619.     # for the "More" prompt.
  620.     for {set i 0} {$i < $num_commands} { incr i} {
  621.     send -- "[subst -nocommands [lindex $commands $i]]\r"
  622.     expect {
  623.         -re "\b+"            { exp_continue }
  624.         -re "^\[^\n\r *]*$reprompt"    { send_user -- "$expect_out(buffer)"
  625.                         }
  626.         -re "^\[^\n\r]*$reprompt."    { send_user -- "$expect_out(buffer)"
  627.                          exp_continue }
  628.         -re "\[\n\r]+"            { send_user -- "$expect_out(buffer)"
  629.                          exp_continue }
  630.         -re "^ ---- More ----.*\[^\n\r]*"    {
  631.                          # H3C pager prompt
  632.                          sleep 0.1
  633.                          send " "
  634.                          exp_continue }
  635.      }

  636.     }

  637.     log_user 1

  638.     send -h "$exitcmd\r"

  639.     # H3C: the exit command leaves the switch completely; it does not
  640.     # prompt to save if the config has been modified
  641.     expect {
  642. #    -re "^\[^\n\r *]*$reprompt"        {
  643. #                         # H3C products
  644. #                         # return to non-enabled mode
  645. #                         # on exit in enabled mode.
  646. #                         send -h "$exitcmd\r"
  647. #                         exp_continue;
  648. #                        }
  649. # TODO: we will need to do this too:
  650. #    "Do you wish to save your configuration changes" {
  651. #                         send -h "n\r"
  652. #                         exp_continue
  653. #                        }
  654.     -re "\[\n\r]+"                { exp_continue }
  655. # hwlogin+mod:
  656.     -re "\[^\n\r *]Note:"            { return 0 }
  657.     timeout                    { catch {close}; catch {wait};
  658.                          return 0
  659.                         }
  660.     eof                    { return 0 }
  661.     }
  662.     set in_proc 0
  663. }

  664. #
  665. # For each router... (this is main loop)
  666. #
  667. source_password_file $password_file
  668. set in_proc 0
  669. set exitval 0
  670. set prompt_match ""
  671. set enable 0
  672. foreach router [lrange $argv $i end] {
  673.     set router [string tolower $router]
  674.     # attempt at platform switching.
  675.     set platform ""
  676.     send_user -- "$router\n"

  677.     # device timeout
  678.     set timeout [find timeout $router]
  679.     if { [llength $timeout] == 0 } {
  680.         set timeout $timeoutdflt
  681.     }

  682.     # Default prompt.
  683.     #set prompt "(>|#| \\(enable\\))"
  684.     set prompt ">\a?"

  685.     # look for noenable option in .cloginrc
  686.     if { [find noenable $router] == "1" } {
  687.     set enable 0
  688.     }

  689.     # Figure out passwords
  690.     if { $do_passwd || $do_enapasswd } {
  691.       set pswd [find password $router]
  692.       if { [llength $pswd] == 0 } {
  693.     send_user "\nError: no password for $router in $password_file.\n"
  694.     continue
  695.       }
  696.       if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
  697.     send_user "\nError: no enable password for $router in $password_file.\n"
  698.     continue
  699.       }
  700.       set passwd [join [lindex $pswd 0] ""]
  701.       set enapasswd [join [lindex $pswd 1] ""]
  702.     } else {
  703.     set passwd $userpasswd
  704.     set enapasswd $enapasswd
  705.     }

  706.     # Figure out username
  707.     if {[info exists username]} {
  708.       # command line username
  709.       set ruser $username
  710.     } else {
  711.       set ruser [join [find user $router] ""]
  712.       if { "$ruser" == "" } { set ruser $default_user }
  713.     }

  714.     # Figure out username's password (if different from the vty password)
  715.     if {[info exists userpasswd]} {
  716.       # command line username
  717.       set userpswd $userpasswd
  718.     } else {
  719.       set userpswd [join [find userpassword $router] ""]
  720.       if { "$userpswd" == "" } { set userpswd $passwd }
  721.     }

  722.     # Figure out enable username
  723.     if {[info exists enausername]} {
  724.       # command line enausername
  725.       set enauser $enausername
  726.     } else {
  727.       set enauser [join [find enauser $router] ""]
  728.       if { "$enauser" == "" } { set enauser $ruser }
  729.     }

  730.     # Figure out prompts
  731.     set u_prompt [find userprompt $router]
  732.     if { "$u_prompt" == "" } {
  733.     set u_prompt "(Username|Login|login|user name|User):"
  734.     } else {
  735.     set u_prompt [join [lindex $u_prompt 0] ""]
  736.     }
  737.     set p_prompt [find passprompt $router]
  738.     if { "$p_prompt" == "" } {
  739.     set p_prompt "(\[Pp]assword|passwd|Enter password for \[^ :]+):"
  740.     } else {
  741.     set p_prompt [join [lindex $p_prompt 0] ""]
  742.     }
  743.     set e_prompt [find enableprompt $router]
  744.     if { "$e_prompt" == "" } {
  745.     set e_prompt "\[Pp]assword:"
  746.     } else {
  747.     set e_prompt [join [lindex $e_prompt 0] ""]
  748.     }

  749.     # Figure out identity file to use
  750.     set identfile [join [lindex [find identity $router] 0] ""]

  751.     # Figure out passphrase to use
  752.     if {[info exists avpassphrase]} {
  753.     set passphrase $avpassphrase
  754.     } else {
  755.     set passphrase [join [lindex [find passphrase $router] 0] ""]
  756.     }
  757.     if { ! [string length "$passphrase"]} {
  758.     set passphrase $passwd
  759.     }

  760.     # Figure out cypher type
  761.     if {[info exists cypher]} {
  762.     # command line cypher type
  763.     set cyphertype $cypher
  764.     } else {
  765.     set cyphertype [find cyphertype $router]
  766.     if { "$cyphertype" == "" } { set cyphertype "$default_cyphertype" }
  767.     }

  768.     # Figure out connection method
  769.     set cmethod [find method $router]
  770.     if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }

  771.     # Figure out the SSH executable name
  772.     set sshcmd [find sshcmd $router]
  773.     if { "$sshcmd" == "" } { set sshcmd {ssh} }

  774.     # Login to the router
  775.     if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype $identfile]} {
  776.     incr exitval
  777.     # if login failed or rsh was unsuccessful, move on to the next device
  778.     continue
  779.     }

  780.     # Figure out the prompt.

  781. # H3C: this is what we used to have, now should be obsolete:
  782. # # Since autoenable is off by default, if we have it defined, it
  783. # # was done on the command line. If it is not specifically set on the
  784. # # command line, check the password file.
  785. # if $avautoenable {
  786. #    set autoenable 1
  787. #    set enable 0
  788. ## hwlogin:
  789. #    #set prompt "(#| \\(enable\\))"
  790. #    set prompt ">\a?"
  791. # } else {
  792. #    set ae [find autoenable $router]
  793. #    if { "$ae" == "1" } {
  794. #     set autoenable 1
  795. #     set enable 0
  796. ## hwlogin:
  797. #     set prompt ">\a?"
  798. #    } else {
  799. #     set autoenable 0
  800. #     set enable $avenable
  801. #     set prompt ">\a?"
  802. #    }
  803. # }
  804. #
  805. # # look for noenable option in .cloginrc
  806. # if { [find noenable $router] == "1" } {
  807. #    set enable 0
  808. # }
  809. ## clogin has:
  810. ## # look for noenable option in .cloginrc
  811. ## if | [find noenable $router] != "" | {
  812. ##    set enable 0
  813. ## }

  814.     # !! H3C does not appear to have a different prompt between lower
  815.     # privilege and higher privilege users, so the following test is
  816.     # not applicable
  817. # if { [regexp -- "(#| \\(enable\\))" $prompt_match junk] == 1 } {
  818. #    set enable 0
  819. # } else {
  820.     if { $avenable == 0 } {
  821.      set enable 0
  822.     } else {
  823.      set ne [find noenable $router]
  824.      set ae [find autoenable $router]
  825.      if { "$ne" == "1" || "$ae" == "1" || $avautoenable } {
  826.         set enable 0
  827.      } else {
  828.         set enable 1
  829.      }
  830.     }
  831. # }
  832.     if { $enable } {
  833.     if {[do_enable $enauser $enapasswd]} {
  834.      if { $do_command || $do_script } {
  835.         incr exitval
  836.         catch {close}; catch {wait};
  837.         continue
  838.      }
  839.     }
  840.     }
  841.     # we are logged in, now figure out the full prompt
  842.     send "\r"
  843.     expect {
  844.     -re "\[\r\n]+"        { exp_continue; }
  845. #    -re "^(.+\[:.])1 ($prompt)" { # stoopid extreme cmd-line numbers and
  846. #                 # prompt based on state of config changes,
  847. #                 # which may have an * at the beginning.
  848. #                 set junk $expect_out(1,string)
  849. #                 regsub -all "^\\\* " $expect_out(1,string) {} junk
  850. #                 regsub -all "\[\]\[\(\)]" $junk {\\&} junk;
  851. #                 set prompt ".? ?$junk\[0-9]+ $expect_out(2,string)";
  852. #                 set platform "extreme"
  853. #                }
  854.     -re "^.+$prompt"    { set junk $expect_out(0,string);
  855.                  regsub -all "\[\]\[\(\)]" $junk {\\&} prompt;
  856.                 }
  857.     }

  858.     # H3C: Disable log junk being sent to terminal: must be done before
  859.     # $enacmd is run. It would be nice for this to be setable in .cloginrc
  860.     send -h "undo terminal monitor\r"
  861.     expect -re $prompt {}

  862.     # Turn session paging off
  863.     # Comware 5 only.
  864.     # Comware 3 models have a screen-length command that only works on
  865.     # a vty basis
  866.     # clogin does this only within the do_script clause below, but I can't
  867.     # see why you wouldn



阅读(4632) | 评论(0) | 转发(0) |
0

上一篇:windows 8.1 dism 启用netfx3.5功能

下一篇:没有了

给主人留下些什么吧!~~