### 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__
syntax highlighted by Code2HTML, v. 0.9.1