### Local Variables: *** ### mode:perl *** ### comment-column:0 *** ### comment-start: "### " *** ### comment-end: "***" *** ### End: *** # # ****************DO NOT MOVE OR CHANGE LINES ABOVE THIS********************* # # The first set of lines runs perl from any shell. The second set of lines # identifies the rest of the file as PERL for EMACS autoformatting. # See end of copyright for more information. # # # ------------------------------------------------------------------- # X-BONE # # http://www.isi.edu/xbone # USC Information Sciences Institute (USC/ISI) # Marina del Rey, California 90292, USA # Copyright (c) 1998-2005 # # ------------------------------------------------------------------- # # Copyright (c) 1998-2005 by the University of Southern California. # All rights reserved. # # Permission to use, copy, modify, and distribute this software and # its documentation in source and binary forms for non-commercial # purposes and without fee is hereby granted, provided that the above # copyright notice appear in all copies and that both the copyright # notice and this permission notice appear in supporting # documentation, and that any documentation, advertising materials, # and other materials related to such distribution and use acknowledge # that the software was developed by the University of Southern # California, Information Sciences Institute. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # # THE UNIVERSITY OF SOUTHERN CALIFORNIA MAKES NO REPRESENTATIONS ABOUT # THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS # PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # Other copyrights might apply to parts of this software and are so # noted when applicable. # # ------------------------------------------------------------------- # # Effort partly sponsored by the Defense Advanced Research Projects # Agency (DARPA) and Air Force Research Laboratory, Air Force Materiel # Command, USAF, under agreement numbers F30602-98-1-0200 (X-Bone) and # F30602-01-2-0529 (DynaBone). The views and conclusions contained # herein are those of the authors and should not be interpreted as # necessarily representing the official policies or endorsements, # either expressed or implied, of the Defense Advanced Research # Projects Agency (DARPA), the Air Force Research Laboratory, or the # U.S. Government. # # This work was partly supported by the NSF STI-XTEND (ANI-0230789) # and NETFS (ANI-0129689) projects. Any opinions, findings, and # conclusions or recommendations expressed in this material are those # of the authors and do not necessarily reflect the views of the # National Science Foundation. # # -------------------------------------------------------------------------- # $RCSfile: XB_Cisco.pm,v $ # # $Revision: 1.2 $ # $Author: pingali $ # $Date: 2005/03/31 07:03:53 $ # $State: Exp $ # ---------------------------------------------------------------------------- # # Primary Author: Mohit Pande package Cisco; require Exporter; @ISA = qw(Exporter); @Export = qw(); @EXPORT_OK = qw(new new_cmd); use strict; use sigtrap; use XB_Log; $|++; use Net::SSH::Perl; use Net::SSH::Perl::Constants qw( :msg ); ############################################################################ # GENERIC EXPORTED API ############################################################################ # Description: # Set up a connection to Cisco Router # Argument: # a hash containing the Cisco Router access information # Returns: # a object of the Cisco connection # Exceptions: # None. # sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { host => '', username => '', password => '', enable_password => '', timeout => 10, @_, #override previous attributes }; bless($self, $class); return $self; } # Description: # Issue command to the connected Cisco Router # Argument: # a object of the Cisco connection # Returns: # the output of the cmd returned by the Cisco Router # Exceptions: # None # sub new_cmd { my $self = shift; my $router_cmd = shift; my $host = $self->{host}; my $username = $self->{username}; my $password = $self->{password}; my $enable_password = $self->{enable_password}; my $timeout = $self->{timeout}; XB_Log::log "debug1", "+++ enter new_cmd +++"; XB_Log::log "debug1", "+++ host=$host, username = $username,". " password= $password, enable_password = $enable_password,". " timeout = $timeout +++"; my @cmd; # modify these in case of prompt (hostname) changes # assuming alphanumeric characters only: # [a-zA-Z0-9] is actually \w, but some hosts have '_' or '-' in their names my $enb_prompt = qr/(?:[a-zA-Z0-9]+\#)\s*/; # alphanumeric followed by '#' my $reg_prompt = qr/(?:[a-zA-Z0-9]+>)\s*/; # alphanumeric followed by '>' my $pass_prompt = qr/Password:\s*/; my ($prompt_cnt,$save) = (0,0); my ($ssh, @config); # login on the device eval { local $SIG{'ALRM'} = sub { die 'TimedouT' }; alarm $timeout; XB_Log::log "debug1", "+++ start login +++"; $ssh = Net::SSH::Perl->new($host, protocol=>1, cipher=>'DES', port=>22); $ssh->login($username, $password); alarm 0; }; XB_Log::log "debug1", "+++ login sucessfully +++"; ($@)? ( die '[',scalar localtime,'] ', ($@ =~ /TimedouT/)? "Takes too long to login on $host.\n" : "Unexpected eval err: $@.\n" ) : undef; # set up handler and intercept everything that goes to STDOUT $ssh->register_handler(SSH_SMSG_STDOUT_DATA, sub { my($ssh, $packet) = @_; my $str = $packet->get_str; if ( $save ) { # reading config if ( $str =~ /$enb_prompt$/ ) { # last line of the config + prompt @cmd = "exit" . "\n"; _send_cmd ($ssh, @cmd); } $str =~ s/\cM//g; chomp $str; # skip echo of the command push @config, $str unless ($str =~ /^(\w|\s|\W)$/ || $str eq ''); } else { # login part if ($str =~ /$reg_prompt$/) { # go to enable mode @cmd = "enable" . "\n"; _send_cmd ($ssh, @cmd); } elsif ( $str =~ /$pass_prompt$/ ) { # going into enable mode.... @cmd = $enable_password . "\n"; _send_cmd ($ssh, @cmd); } elsif ( $str =~ /$enb_prompt$/ && !$prompt_cnt ) { # exec first command in enable mode @cmd = "terminal length 0" . "\n"; _send_cmd ($ssh, @cmd); $prompt_cnt++; } elsif ( $str =~ /$enb_prompt$/ && $prompt_cnt ) { # exec second command in enable mode @cmd = $router_cmd . "\n"; _send_cmd ($ssh, @cmd); $save++; } else { # Uncomment this for debug purposes # print "Useless data: $str\n"; } } }); eval { local $SIG{'ALRM'} = sub { die 'TimedouT' }; alarm $timeout; $ssh->cmd(''); alarm 0; }; ($@)? ( die '[ ',scalar localtime,'] ', ($@ =~ /TimedouT/)? "Timed out while pulling from $host.\n" : "Unexpected eval err: $@.\n" ) : undef; # at this point you have config in @config # do whatever you need to do with it my @output = split "\n", $config[0]; pop @output; # removing the router prompt from the output for (my $i= 0; $i<=$#output; $i++) { $output[$i] .= "\n"; } XB_Log::log "debug1", "+++ leave new_cmd +++"; @config; } ########################################################################## # UTILITY FUNCTIONS ########################################################################## # Description: # Dispatch the cisco command # Arguments: # Object of a cisco connection # Returns: # None. # sub _send_cmd { my $ssh = shift; my @cmd = @_; my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA); $packet->put_str(@cmd); $packet->send; } 1; __END__