diff --git a/Dockerfile b/Dockerfile
index 2d07e7c..560cb59 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,7 +7,7 @@ COPY conf/globalnoc-public-el7.repo /etc/yum.repos.d/globalnoc-public-el7.repo
RUN yum makecache
RUN yum -y install epel-release
-RUN yum -y install perl-Template-Toolkit perl-XML-Parser perl-XML-Simple perl-CGI-Ajax perl-Time-ParseDate perl-Net-Telnet perl-Expect perl-GRNOC-TL1 perl-GRNOC-Config perl-Class-Accessor perl-YAML perl-JSON perl-Log-Log4perl
+RUN yum -y install perl-Template-Toolkit perl-XML-Parser perl-XML-Simple perl-CGI perl-Time-ParseDate perl-Net-Telnet perl-Expect perl-GRNOC-TL1 perl-GRNOC-Config perl-Class-Accessor perl-YAML perl-JSON perl-Log-Log4perl
RUN yum -y install perl-GRNOC-WebService perl-GRNOC-WebService-Client perl-Test-Deep perl-Test-Exception perl-Test-Pod perl-Test-Pod-Coverage perl-Devel-Cover perl-Data-Dumper perl-Test-Harness perl-Test-Simple openssh-clients
COPY conf/routerproxy.conf /etc/httpd/conf.d/routerproxy.conf
diff --git a/README.md b/README.md
index bde08ed..b1bf161 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,6 @@ Perl modules need to be installed as well (generally easily done with cpan).
(NOTE: This is now only required for the menu based commands.. if you
don't have it installed, RouterProxy will still work).
* CGI
-* CGI::Ajax
* XML::Simple
* Encode
* Expect
diff --git a/conf/logging.conf b/conf/logging.conf
index 065be51..752a2aa 100644
--- a/conf/logging.conf
+++ b/conf/logging.conf
@@ -1,15 +1,11 @@
-log4perl.logger.GRNOC.RouterProxy = INFO, Screen
-log4perl.logger.GRNOC.RouterProxy.Generator = INFO, Screen
-log4perl.logger = DEBUG, Screen
+log4perl.logger.GRNOC.RouterProxy = INFO, SYSLOG
+log4perl.logger.GRNOC.RouterProxy.Generator = INFO, SYSLOG
+log4perl.logger = DEBUG, SYSLOG
-# Logs against only the most specific category
+# Only log one line (prevents duplicate logging)
log4perl.oneMessagePerAppender = 1
-log4perl.appender.Screen = Log::Log4perl::Appender::Screen
-log4perl.appender.Screen.stderr = 0
-log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout
-
log4perl.appender.SYSLOG = Log::Dispatch::Syslog
log4perl.appender.SYSLOG.facility = LOCAL0
log4perl.appender.SYSLOG.layout = PatternLayout
-log4perl.appender.SYSLOG.layout.ConversionPattern=[%d] %p %F %L %c - %m%n
+log4perl.appender.SYSLOG.layout.ConversionPattern=[%p] %l: %m%n
diff --git a/grnoc-routerproxy.spec b/grnoc-routerproxy.spec
index 4c23184..821f946 100644
--- a/grnoc-routerproxy.spec
+++ b/grnoc-routerproxy.spec
@@ -1,6 +1,6 @@
Summary: GRNOC Router Proxy
Name: grnoc-routerproxy
-Version: 2.3.2
+Version: 2.4.0
Release: %{_buildno}%{?dist}
License: GRNOC
Group: Auth
@@ -14,7 +14,7 @@ Requires: perl >= 5.8.8
Requires: perl-Template-Toolkit
Requires: perl(XML::Parser)
Requires: perl(XML::Simple)
-Requires: perl(CGI::Ajax)
+Requires: perl(CGI)
Requires: perl(Time::ParseDate)
Requires: perl(Net::Telnet)
Requires: perl(Expect)
@@ -26,7 +26,9 @@ Requires: perl(JSON)
Requires: perl(Log::Log4perl)
Provides: perl(GRNOC::RouterProxy)
-Provides: perl(GRNOC::RouterProxy::Commands), perl(GRNOC::RouterProxy::Config), perl(GRNOC::RouterProxy::Logger)
+Provides: perl(GRNOC::RouterProxy::Commands)
+Provides: perl(GRNOC::RouterProxy::Config)
+Provides: perl(GRNOC::RouterProxy::Logger)
BuildRequires: tar
AutoReqProv: no
@@ -47,6 +49,8 @@ rm -rf $RPM_BUILD_ROOT
%{__install} conf/routerproxy.yaml %{buildroot}%{_sysconfdir}/grnoc/routerproxy/
%{__install} conf/logging.conf %{buildroot}%{_sysconfdir}/grnoc/routerproxy/
+%{__install} -d -p %{buildroot}/var/log/grnoc/routerproxy/
+
%{__install} -d -p %{buildroot}%{_sysconfdir}/httpd/conf.d/grnoc/
%{__install} conf/routerproxy.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/grnoc/
@@ -90,9 +94,11 @@ rm -rf $RPM_BUILD_ROOT
%defattr(754,apache,apache,-)
%{_datadir}/grnoc/routerproxy/www/index.cgi
%{_datadir}/grnoc/routerproxy/www/routerproxy.js
+
%defattr(644,root,apache,-)
%config(noreplace) %{_datadir}/grnoc/routerproxy/www/style.css
%{_datadir}/grnoc/routerproxy/templates/index.tt
%attr(755,apache,apache) %dir %{_datadir}/grnoc/routerproxy/.ssh/
+%attr(755,apache,apache) %dir /var/log/grnoc/routerproxy/
diff --git a/lib/GRNOC/RouterProxy.pm b/lib/GRNOC/RouterProxy.pm
index e9b6a8a..4e50951 100644
--- a/lib/GRNOC/RouterProxy.pm
+++ b/lib/GRNOC/RouterProxy.pm
@@ -1,26 +1,12 @@
package GRNOC::RouterProxy;
+our $VERSION = '2.4.0';
use strict;
+use warnings;
-use Net::Telnet;
use Expect;
-
-# gots junoscript?
-my $hasJunoscript;
-BEGIN {
-
- eval {
- require JUNOS::Device;
- };
- if ($@) {
- $hasJunoscript = 0;
- }
- else {
- $hasJunoscript = 1;
- JUNOS::Device->import;
- }
-}
-
+use Net::Telnet;
+use Log::Log4perl;
use Data::Dumper;
use GRNOC::Config;
@@ -33,425 +19,381 @@ use GRNOC::TL1::Device::Ciena::CoreDirector;
use GRNOC::RouterProxy::Config;
my $timeout = 0;
+my $hasJunoscript;
-our $VERSION = '2.3.2';
-sub new {
-
- my $caller = shift;
- my $class = ref($caller) || $caller;
-
- my $self = {
- username => 'username',
- password => 'password',
- type => 'junos',
- method => 'ssh',
- junoscript => '0',
- iosxml => '0',
- hostname => 'hostname',
- port => '23',
- maxlines => '5000',
- timeout => '60',
- debug => '0',
- @_
- };
-
- bless($self, $class);
+Log::Log4perl::init('/etc/grnoc/routerproxy/logging.conf');
+my $logger = Log::Log4perl->get_logger('GRNOC.RouterProxy');
- return $self;
+BEGIN {
+ eval {
+ require JUNOS::Device;
+ };
+ if ($@) {
+ $hasJunoscript = 0;
+ }
+ else {
+ $hasJunoscript = 1;
+ JUNOS::Device->import;
+ }
}
-sub command {
-
- my ($self) = @_;
- shift;
- my $command = shift;
-
- if ($self->{type} eq "ome" || $self->{type} eq "hdxc" || $self->{type} eq "ons15454" || $self->{type} eq "ciena") {
-
- my $tl1 = GRNOC::TL1->new(
- username => $self->{username},
- password => $self->{password},
- type => $self->{type},
- host => $self->{hostname},
- port => $self->{port},
- ctag => 1337);
- $tl1->connect();
- $tl1->login();
-
- my $result = $tl1->cmd($command);
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- $result = $self->sanitize_text($result);
- return $result;
- }
-
- elsif ($self->{type} eq "iosxr" && $self->{method} eq "ssh") {
-
- my $result = &iosxrSSH($self, $command);
-
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- return $result;
- }
-
- elsif ($self->{type} eq "hp" && $self->{method} eq "ssh") {
-
- my $result = &hpSSH($self, $command);
-
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- $result = $self->sanitize_text($result);
- return $result;
- }
- elsif (($self->{type} eq "ios2" || $self->{type} eq "ios" || $self->{type} eq "ios6509" || $self->{type} eq "nx-os" || $self->{type} eq 'brocade') && $self->{method} eq "ssh") {
-
- my $result = &ios2SSH($self, $command);
-
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- $result = $self->sanitize_text($result);
- return $result;
- }
-
- elsif ($self->{type} eq "ios2" && $self->{method} eq "telnet") {
-
- my $result = &ios2Telnet($self, $command);
+sub new {
+ my $caller = shift;
+ my $class = ref($caller) || $caller;
+
+ my $self = {
+ username => 'username',
+ password => 'password',
+ type => 'junos',
+ method => 'ssh',
+ junoscript => '0',
+ iosxml => '0',
+ hostname => 'hostname',
+ port => '23',
+ maxlines => '5000',
+ timeout => '60',
+ debug => '0',
+ @_
+ };
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
+ bless($self, $class);
+ return $self;
+}
- $result = $self->sanitize_text($result);
- return $result;
- }
- elsif ($self->{type} eq "force10" && $self->{method} eq "ssh") {
+#ISSUE=12307 Remove sensitive information, as specified in the config file, from any output
+sub sanitize_text {
+ my $self = shift;
+ my $text = shift;
- my $result = &force10SSH($self, $command);
+ my $conf = GRNOC::RouterProxy::Config->new($self->{'config_path'});
+ my $stanzas = $conf->Redacts();
- #$result =~ s/\t/ /g;
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- $result = $self->sanitize_text($result);
- return $result;
- }
-
- elsif ($self->{type} eq "bladeOS" && $self->{method} eq "ssh") {
-
- my $result = &bladeOS($self, $command);
-
- #$result =~ s/\t/ /g;
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
-
- $result = $self->sanitize_text($result);
- return $result;
- }
-
- elsif ($self->{type} eq "junos" && $self->{method} eq "ssh") {
+ foreach my $stanza ( @$stanzas ) {
+ $stanza =~ s/ / \;/g;
+ $stanza =~ s/(?/>\;/g;
+ $text =~ s/$stanza/\[REDACTED\]/g;
+ }
+ return $text;
+}
- my $result = &junosSSH($self, $command);
+# Helper to swap chars for HTML codes and sanitize result strings
+sub clean_result {
+ my $self = shift;
+ my $result = shift;
+ my $sanitize = shift || 1;
$result =~ s/ / /g;
$result =~ s/</g;
$result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
+ $result = $self->sanitize_text($result) if $sanitize;
+ return $result
+}
- $result = $self->sanitize_text($result);
- return $result;
- }
+sub blankPrompt {
+ my $string = shift;
- elsif ($self->{type} eq "arista" && $self->{method} eq "ssh") {
+ # pull out the first line
+ my $line = substr($string, 0, index($string, "\n"));
- my $result = &aristaSSH($self, $command);
+ # find the first >
+ my $index = index($line, '>');
- $result =~ s/ / /g;
- $result =~ s/</g;
- $result =~ s/>/>/g;
- #$result =~ s/\n/
/g;
+ # otherwise find the first #
+ $index = index($line, '#') if ($index < 0);
- return $result;
- }
+ # get the prompt (user at host)
+ my $prompt = substr($string, 0, $index + 1);
- elsif ($self->{method} eq "ssh") {
+ # replace each char with a space
+ $prompt =~ s/#/>/;
+ $prompt =~ s/[^>]/\./g;
- my $result;
- # using junoscript?
- if ($self->{junoscript} eq "1") {
+ # get everything after the prompt
+ $string = substr($string, $index + 1);
- if (!$hasJunoscript) {
+ # reattach our blanked out prompt to the rest of the string
+ $string = $prompt . $string;
- $result = "Junoscript must be installed.";
- }
-
- else {
-
- my %info = (
- access => "ssh",
- login => $self->{username},
- password => $self->{password},
- hostname => $self->{hostname});
+ return $string;
+}
- my $junos = new JUNOS::Device(%info);
- $result = $junos->command($command)->toString;
- $result =~ s/junos://g;
- }
- $result = $self->sanitize_text($result);
- return $result;
+sub command {
+ my ($self) = @_;
+ shift;
+ my $command = shift;
+
+ $logger->info("Issuing command '$command' on $self->{'hostname'}");
+
+ if ($self->{'type'} eq "ome" || $self->{'type'} eq "hdxc" || $self->{'type'} eq "ons15454" || $self->{'type'} eq "ciena") {
+ my $tl1 = GRNOC::TL1->new(
+ username => $self->{'username'},
+ password => $self->{'password'},
+ type => $self->{'type'},
+ host => $self->{'hostname'},
+ port => $self->{'port'},
+ ctag => 1337
+ );
+ $tl1->connect();
+ $tl1->login();
+
+ my $result = $tl1->cmd($command);
+ return $self->clean_result($result);
}
- else {
-
- return "Unsupported connection type";
+ elsif ($self->{'type'} eq "iosxr" && $self->{'method'} eq "ssh") {
+ my $result = &iosxrSSH($self, $command);
+ return $self->clean_result($result, 0);
}
- }
- elsif ($self->{method} eq "telnet") {
+ elsif ($self->{'type'} eq "hp" && $self->{'method'} eq "ssh") {
+ my $result = &hpSSH($self, $command);
+ return $self->clean_result($result);
+ }
- my $buf;
- my $prompt;
+ elsif (($self->{'type'} eq "ios2" || $self->{'type'} eq "ios" || $self->{'type'} eq "ios6509" || $self->{'type'} eq "nx-os" || $self->{'type'} eq 'brocade') && $self->{'method'} eq "ssh") {
+ my $result = &ios2SSH($self, $command);
+ return $self->clean_result($result);
+ }
- # default port 23
- my $port = $self->{port};
+ elsif ($self->{'type'} eq "ios2" && $self->{'method'} eq "telnet") {
+ my $result = &ios2Telnet($self, $command);
+ return $self->clean_result($result);
+ }
- if ($port eq "") {
- $port = "23";
+ elsif ($self->{'type'} eq "force10" && $self->{'method'} eq "ssh") {
+ my $result = &force10SSH($self, $command);
+ return $self->clean_result($result);
}
- my $telnet = Net::Telnet->new(Timeout => 1, Errmode => 'return', Port => $port);
- my $result = $telnet->open($self->{hostname});
- if (!$result) {
- die($telnet->errmsg());
+ elsif ($self->{'type'} eq "bladeOS" && $self->{'method'} eq "ssh") {
+ my $result = &bladeOS($self, $command);
+ return $self->clean_result($result);
+ }
+
+ elsif ($self->{'type'} eq "junos" && $self->{'method'} eq "ssh") {
+ my $result = &junosSSH($self, $command);
+ return $self->clean_result($result);
}
- # JunOS login
- if ($self->{type} eq "junos") {
+ elsif ($self->{'type'} eq "arista" && $self->{'method'} eq "ssh") {
+ my $result = &aristaSSH($self, $command);
+ return $self->clean_result($result, 0);
+ }
- # junoscript?
- if ($self->{junoscript} eq "1") {
+ elsif ($self->{'method'} eq "ssh") {
+ return "Unsupported connection type" if ($self->{'junoscript'} ne "1");
+ my $result;
if (!$hasJunoscript) {
-
- $result = "Junoscript must be installed.";
+ $result = "Junoscript must be installed";
}
else {
- my %info = (
- access => "telnet",
- login => $self->{username},
- password => $self->{password},
- hostname => $self->{hostname});
-
- my $junos = new JUNOS::Device(%info);
- my $result = $junos->command($command)->toString;
- $result =~ s/junos://g;
+ my %info = (
+ access => "ssh",
+ login => $self->{'username'},
+ password => $self->{'password'},
+ hostname => $self->{'hostname'}
+ );
+ my $junos = new JUNOS::Device(%info);
+ $result = $junos->command($command)->toString;
+ $result =~ s/junos://g;
}
-
$result = $self->sanitize_text($result);
return $result;
- }
- else {
+ }
- my $result = $telnet->login($self->{username}, $self->{password});
- if (!$result) {
- die($telnet->errmsg());
+ elsif ($self->{'method'} eq "telnet") {
+ my $buf;
+ my $prompt;
+
+ my $port = $self->{'port'} || "23"; # Default port 23
+ my $telnet = Net::Telnet->new(
+ Timeout => 1,
+ Errmode => 'return',
+ Port => $port
+ );
+ my $result = $telnet->open($self->{'hostname'});
+ die($telnet->errmsg()) unless $result;
+
+ # JunOS login
+ if ($self->{'type'} eq "junos") {
+ if ($self->{'junoscript'} eq "1") {
+ if (!$hasJunoscript) {
+ $result = "Junoscript must be installed";
+ }
+ else {
+ my %info = (
+ access => "telnet",
+ login => $self->{'username'},
+ password => $self->{'password'},
+ hostname => $self->{'hostname'}
+ );
+ my $junos = new JUNOS::Device(%info);
+ my $result = $junos->command($command)->toString;
+ $result =~ s/junos://g;
+ }
+ $result = $self->sanitize_text($result);
+ return $result;
+ }
+ else {
+ my $result = $telnet->login($self->{'username'}, $self->{'password'});
+ die($telnet->errmsg()) unless ($result);
+ $telnet->cmd("set cli screen-length 0");
+ }
}
- $telnet->cmd("set cli screen-length 0");
- }
- }
- # IOS login
- elsif ($self->{type} eq "ios" || $self->{type} eq "ios6509") {
+ # IOS login
+ elsif ($self->{'type'} eq "ios" || $self->{'type'} eq "ios6509") {
+ $telnet->login($self->{'username'}, $self->{'password'});
+ die($telnet->errmsg()) unless ($result);
+ $telnet->cmd("terminal length 0");
+ }
- $telnet->login($self->{username}, $self->{password});
- if (!$result) {
- die($telnet->errmsg());
- }
- $telnet->cmd("terminal length 0");
+ eval {
+ # setup the timeout handler
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n";
+ die;
+ };
+
+ # start the timeout timer
+ alarm($self->{'timeout'});
+
+ # issue command and eat up echo
+ $telnet->print($command);
+ $telnet->getline();
+
+ # eat up extra lines for IOS
+ if ($self->{'type'} eq "ios") {
+ $telnet->getline();
+ $telnet->getline();
+ $telnet->getline();
+ }
+
+ my $i = 0;
+ my $msg;
+ while (1) {
+ $msg = $telnet->getline();
+ last if ($msg eq "");
+ # $msg =~ s/ / /g;
+ # $msg =~ s/</g;
+ # $msg =~ s/>/>/g;
+ $msg = $self->clean_result($msg, 0);
+ $buf .= $msg;
+ $i++;
+ if ($i == $self->{'maxlines'}) {
+ $buf .= "\n--- Maximum Output Exceeded ---\n";
+ last;
+ }
+ }
+ alarm(0);
+ };
+
+ $buf = $self->sanitize_text($buf);
+ return $buf;
}
+}
- eval {
-
- # setup the timeout handler
- local $SIG{ALRM} = sub {
- $buf .= "\n--- Maximum Timeout Exceeded ---\n";
- die;
- };
+sub force10SSH {
+ my $self = shift;
+ my $cmd = shift;
- # start the timeout timer
- alarm($self->{'timeout'});
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- my $i = 0;
- my $msg;
+ my $prompt;
+ my $buf;
+ my $count = 0;
+ my $ssh;
- # issue command and eat up echo
- $telnet->print($command);
- $telnet->getline();
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->log_file(sub {$prompt .= shift });
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- # eat up extra lines for IOS
- if ($self->{type} eq "ios") {
- $telnet->getline();
- $telnet->getline();
- $telnet->getline();
- }
+ $prompt = reverse($prompt);
+ my $index = index($prompt, "\n");
+ $prompt = reverse(substr($prompt, 0, $index));
- while (1) {
+ $ssh->log_file(sub { $buf .= shift });
+ $ssh->send("terminal length 0\r\n");
+ $ssh->expect($self->{'timeout'}, ["^$prompt", sub {}]);
- $msg = $telnet->getline();
- if ($msg eq "") {
- last;
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ $ssh->log_file(undef);
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+ alarm($self->{'timeout'});
+
+ # dont give a newline if the command contains ?
+ my $matchCmd = $cmd;
+ if ($cmd =~ /\?/) {
+ chop($matchCmd);
+ $ssh->send("$cmd");
}
- $msg =~ s/ / /g;
- $msg =~ s/</g;
- $msg =~ s/>/>/g;
- #$msg =~ s/\n/
/g;
- $buf .= $msg;
- $i++;
- if ($i == $self->{maxlines}) {
- $buf .= "\n--- Maximum Output Exceeded ---\n";
- last;
+ else {
+ $ssh->send("$cmd\r\n");
}
- }
- alarm(0);
+ $ssh->expect($self->{'timeout'}, ["^$prompt", sub {}]);
+ alarm(0);
};
- $buf = $self->sanitize_text($buf);
+ $buf =~ s/.*\n//;
+ $buf = blankPrompt($buf);
+ $buf = reverse($buf);
+ $buf =~ s/.*\n//;
+ $buf = reverse($buf);
return $buf;
- }
}
-sub force10SSH {
-
- my $self = shift;
- my $cmd = shift;
-
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
-
- my $prompt;
- my $buf;
- my $count = 0;
- my $ssh;
-
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->log_file(sub {$prompt .= shift });
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
-
- $prompt = reverse($prompt);
- my $index = index($prompt, "\n");
- $prompt = substr($prompt, 0, $index);
- $prompt = reverse($prompt);
-
- $ssh->log_file(sub { $buf .= shift });
- $ssh->send("terminal length 0\r\n");
- $ssh->expect($self->{'timeout'},
- ["^$prompt", sub {}]);
-
- eval {
-
- local $SIG{ALRM} = sub {
-
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
- };
-
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
-
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- $ssh->log_file(undef);
- die;
- }
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
- alarm($self->{'timeout'});
-
- # dont give a newline if the command contains ?
- my $matchCmd = $cmd;
- if ($cmd =~ /\?/) {
- chop($matchCmd);
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\r\n");
- }
- $ssh->expect($self->{'timeout'},
- ["^$prompt",
- sub {}]);
- alarm(0);
- };
-
- $buf =~ s/.*\n//;
- $buf = blankPrompt($buf);
-
- $buf = reverse($buf);
- $buf =~ s/.*\n//;
-
- # if they got a command list, remove another line at the end
- #if ($cmd =~ /\?/) {
-
- # $buf =~ s/.*\n//;
- #}
- $buf = reverse($buf);
-
- return $buf;
-}
sub bladeOS {
-
my $self = shift;
my $cmd = shift;
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
my $prompt;
my $buf;
@@ -461,803 +403,671 @@ sub bladeOS {
$ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
$ssh->log_stdout(0);
$ssh->log_file(sub {$prompt .= shift });
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
$prompt = reverse($prompt);
my $index = index($prompt, "\n");
- $prompt = substr($prompt, 0, $index);
- $prompt = reverse($prompt);
+ $prompt = reverse(substr($prompt, 0, $index));
$ssh->log_file(sub { $buf .= shift });
$ssh->send("terminal length 0\r\n");
- $ssh->expect($self->{'timeout'},
- ["^$prompt", sub {}]);
+ $ssh->expect($self->{'timeout'}, ["^$prompt", sub {}]);
eval {
-
- local $SIG{ALRM} = sub {
-
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
- };
-
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
-
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- $ssh->log_file(undef);
- die;
- }
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
- alarm($self->{'timeout'});
-
- # dont give a newline if the command contains ?
- my $matchCmd = $cmd;
- if ($cmd =~ /\?/) {
- chop($matchCmd);
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\r\n");
- }
- $ssh->expect($self->{'timeout'},
- ["^$prompt",
- sub {}]);
- alarm(0);
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ $ssh->log_file(undef);
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+ alarm($self->{'timeout'});
+
+ # dont give a newline if the command contains ?
+ my $matchCmd = $cmd;
+ if ($cmd =~ /\?/) {
+ chop($matchCmd);
+ $ssh->send("$cmd");
+ }
+ else {
+ $ssh->send("$cmd\r\n");
+ }
+ $ssh->expect($self->{'timeout'},["^$prompt",sub {}]);
+ alarm(0);
};
# remove 4 blank lines
$buf =~ s/.*\n//;
$buf =~ s/.*\n//;
$buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- #$buf = blankPrompt($buf);
-
+ $buf =~ s/.*\n//;
$buf = reverse($buf);
#remove last line (prompt)
$buf =~ s/.*\n//;
$buf = reverse($buf);
-
return $buf;
}
-sub hpSSH {
- my $self = shift;
- my $cmd = shift;
+sub hpSSH {
+ my $self = shift;
+ my $cmd = shift;
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- my $buf;
- my $count = 0;
- my $ssh;
+ my $buf;
+ my $count = 0;
+ my $ssh;
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['Press any key to continue',
- sub {
- my $out = shift;
- print $out "\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [ 'Press any key to continue',
+ sub {
+ my $out = shift;
+ print $out "\n";
+ exp_continue;
+ }
+ ],
+ [ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
+
+ my $questionMark = 0;
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $ssh->log_file(undef);
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ die;
+ }
+ my $data = shift;
+ $data =~ s/-- MORE --.*Control-C.*$//;
+ $data =~ s/\e[[\w;]*//g;
+ $buf .= $data;
+
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+ alarm($self->{'timeout'});
+
+ if ($cmd =~ /\?/) {
+ $questionMark = 1;
+ $cmd =~ s/(.*)\?/$1/;
+ $ssh->send("$cmd");
+ sleep(1);
+ $ssh->send("?");
+ }
+ else {
+ $ssh->send("$cmd\n");
+ }
+ $ssh->expect(
+ $self->{'timeout'},
+ ['[>]', sub {}],
+ [
+ 'Control-C',
sub {
- }]
- );
-
- my $questionMark = 0;
-
- eval {
-
- local $SIG{ALRM} = sub {
-
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
+ my $out = shift;
+ print $out " ";
+ exp_continue;
+ }
+ ]
+ );
+ alarm(0);
};
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
- $ssh->log_file(undef);
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- die;
- }
- my $data = shift;
- $data =~ s/-- MORE --.*Control-C.*$//;
- $data =~ s/\e[[\w;]*//g;
-
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
- alarm($self->{'timeout'});
-
- if ($cmd =~ /\?/) {
+ # detect invalid input and fix it
+ if ($buf =~ /input: (.*)/) {
+ $buf = "Invalid input: $1";
+ return $buf;
+ }
+ $buf =~ s/.*\n//;
- $questionMark = 1;
- $cmd =~ s/(.*)\?/$1/;
- $ssh->send("$cmd");
- sleep(1);
- $ssh->send("?");
+ # create dummy prompt
+ if ($questionMark) {
+ $buf = "> $cmd?\n" . $buf;
}
else {
- $ssh->send("$cmd\n");
+ $buf = "> $cmd\n" . $buf;
}
- $ssh->expect($self->{'timeout'},
- ['[>]',
- sub {
- }],
- ['Control-C',
- sub {
- my $out = shift;
- print $out " ";
- exp_continue;
- }]);
- alarm(0);
- };
- # detect invalid input and fix it
- if ($buf =~ /input: (.*)/) {
- $buf = "Invalid input: $1";
+ $buf = reverse($buf);
+ # remove last line (prompt)
+ $buf =~ s/.*\n//;
+ $buf = reverse($buf);
return $buf;
- }
- $buf =~ s/.*\n//;
- #$buf = blankPrompt($buf);
-
- # create dummy prompt
- if ($questionMark) {
- $buf = "> $cmd?\n" . $buf;
- }
- else {
- $buf = "> $cmd\n" . $buf;
- }
-
- $buf = reverse($buf);
- # remove last line (prompt)
- $buf =~ s/.*\n//;
- $buf = reverse($buf);
-
- return $buf;
}
-sub ios2Telnet {
-
- my $self = shift;
- my $cmd = shift;
-
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
-
- my $buf;
- my $count = 0;
- my $telnet;
-
- $telnet = Net::Telnet->new(Timeout => 1, Errmode => 'return', Port => $self->{port});
- my $result = $telnet->open($self->{hostname});
- if (!$result) {
- die($telnet->errmsg());
- }
- $telnet->login($username, $password);
- $telnet->cmd("terminal length 0");
- $telnet->buffer_empty();
+sub ios2Telnet {
+ my $self = shift;
+ my $cmd = shift;
- eval {
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- # setup the timeout handler
- local $SIG{ALRM} = sub {
+ my $buf;
+ my $count = 0;
+ my $telnet;
- $buf .= "\n--- Maximum Timeout Exceeded ---\n";
- die;
- };
+ $telnet = Net::Telnet->new(Timeout => 1, Errmode => 'return', Port => $self->{'port'});
+ my $result = $telnet->open($self->{'hostname'});
+ die($telnet->errmsg()) unless ($result);
- # start the timeout timer
- alarm($self->{'timeout'});
+ $telnet->login($username, $password);
+ $telnet->cmd("terminal length 0");
+ $telnet->buffer_empty();
- my $i = 0;
- my $msg;
+ eval {
+ # setup the timeout handler
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n";
+ die;
+ };
- # issue command and eat up echo
- $telnet->print($cmd);
- $telnet->getline();
+ # start the timeout timer
+ alarm($self->{'timeout'});
- # eat up extra lines for IOS
- if ($self->{type} eq "ios") {
- $telnet->getline();
- $telnet->getline();
- $telnet->getline();
- }
+ # issue command and eat up echo
+ $telnet->print($cmd);
+ $telnet->getline();
- while (1) {
-
- $msg = $telnet->getline();
- if ($msg eq "") {
- last;
- }
- $buf .= $msg;
- $i++;
- if ($i == $self->{maxlines}) {
- $buf .= "\n--- Maximum Output Exceeded ---\n";
- last;
- }
- }
- alarm(0);
- };
+ # eat up extra lines for IOS
+ if ($self->{'type'} eq "ios") {
+ $telnet->getline();
+ $telnet->getline();
+ $telnet->getline();
+ }
- return $buf;
+ my $i = 0;
+ my $msg;
+ while (1) {
+ $msg = $telnet->getline();
+ last if ($msg eq "");
+ $buf .= $msg;
+ $i++;
+ if ($i == $self->{'maxlines'}) {
+ $buf .= "\n--- Maximum Output Exceeded ---\n";
+ last;
+ }
+ }
+ alarm(0);
+ };
+ return $buf;
}
-sub ios2SSH {
-
- my $self = shift;
- my $cmd = shift;
-
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
- my $buf;
- my $count = 0;
- my $ssh;
+sub ios2SSH {
+ my $self = shift;
+ my $cmd = shift;
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->expect(5,
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- $ssh->log_file(sub { $buf .= shift });
- $ssh->send("terminal length 0\n");
- $ssh->expect(5,
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
+ my $buf;
+ my $count = 0;
+ my $ssh;
- eval {
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->expect(
+ 5,
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- local $SIG{ALRM} = sub {
+ $ssh->log_file(sub { $buf .= shift });
+ $ssh->send("terminal length 0\n");
+ $ssh->expect(
+ 5,
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $ssh->log_file(undef);
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+ alarm($self->{'timeout'});
+
+ if ($cmd =~ /\?/) {
+ $ssh->send("$cmd");
+ }
+ else {
+ $ssh->send("$cmd\n");
+ }
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^\S*#', sub {}],
+ ['^\S*>', sub {}]
+ );
+ alarm(0);
};
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
- $ssh->log_file(undef);
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- die;
- }
-
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
- alarm($self->{'timeout'});
- if ($cmd =~ /\?/) {
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\n");
- }
-
- $ssh->expect($self->{'timeout'},
- ['^\S*#',
- sub {
- }],
- ['^\S*>',
- sub {
- }]);
- alarm(0);
- };
-
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- $buf = blankPrompt($buf);
- $buf = reverse($buf);
- # remove last line (prompt)
- $buf =~ s/.*\n//;
- $buf = reverse($buf);
-
- return $buf;
+ $buf =~ s/.*\n//;
+ $buf =~ s/.*\n//;
+ $buf = blankPrompt($buf);
+ $buf = reverse($buf);
+ # remove last line (prompt)
+ $buf =~ s/.*\n//;
+ $buf = reverse($buf);
+ return $buf;
}
-sub iosxrSSH {
- my $self = shift;
- my $cmd = shift;
-
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
-
- my $buf;
- my $count = 0;
- my $questionMark = 0;
- my $ssh;
+sub iosxrSSH {
+ my $self = shift;
+ my $cmd = shift;
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- $ssh->log_file(sub { $buf .= shift });
- $ssh->send("terminal length 0\n");
- $ssh->expect($self->{'timeout'},
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]);
+ my $buf;
+ my $count = 0;
+ my $questionMark = 0;
+ my $ssh;
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- eval {
+ $ssh->log_file(sub { $buf .= shift });
+ $ssh->send("terminal length 0\n");
+ $ssh->expect(
+ $self->{'timeout'},
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- local $SIG{ALRM} = sub {
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+ alarm($self->{'timeout'});
+
+ if ($cmd =~ /\?/) {
+ $questionMark = 1;
+ $ssh->send("$cmd");
+ }
+ else {
+ $ssh->send("$cmd\n");
+ }
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $ssh->log_file(undef);
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+
+ if ($questionMark) {
+ $cmd =~ s/(.*)\?/$1/;
+ $ssh->expect(
+ $self->{'timeout'},
+ ["^.*[#>]($cmd)", sub {}]
+ );
+ }
+ else {
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^.*#$', sub {}],
+ ['^.*>$', sub {}]
+ );
+ }
+ alarm(0);
};
- alarm($self->{'timeout'});
-
- if ($cmd =~ /\?/) {
- $questionMark = 1;
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\n");
- }
-
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
- $ssh->log_file(undef);
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- die;
- }
-
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
-
- if ($questionMark) {
-
- $cmd =~ s/(.*)\?/$1/;
- $ssh->expect($self->{'timeout'},
- ["^.*[#>]($cmd)",
- sub {}]);
- }
- else {
- $ssh->expect($self->{'timeout'},
- ['^.*#$',
- sub {
- }],
- ['^.*>$',
- sub {
- }]);
- }
-
- alarm(0);
- };
-
- # remove first blank line
- $buf =~ s/.*\n//;
- $buf = blankPrompt($buf);
-
- # add an extra space to line up the ^ if needed
- if ($buf =~ /% Invalid input detected at/) {
-
- $buf =~ s/\^/ ^/;
- }
+ # remove first blank line
+ $buf =~ s/.*\n//;
+ $buf = blankPrompt($buf);
- $buf = reverse($buf);
- #remove last line (prompt)
- $buf =~ s/.*\n//;
- $buf = reverse($buf);
+ # add an extra space to line up the ^ if needed
+ $buf =~ s/\^/ ^/ if ($buf =~ /% Invalid input detected at/);
- return $buf;
+ $buf = reverse($buf);
+ #remove last line (prompt)
+ $buf =~ s/.*\n//;
+ $buf = reverse($buf);
+ return $buf;
}
+
sub junosSSH {
+ my $self = shift;
+ my $cmd = shift;
- my $self = shift;
- my $cmd = shift;
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
+ my $buf;
+ my $count = 0;
+ my $ssh;
+ my $questionMark = 0;
- my $buf;
- my $count = 0;
- my $ssh;
- my $questionMark = 0;
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ]
+ );
+
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^([^\\s])*#\\\s\$', sub {}],
+ ['^([^\\s])*>\\\s\$', sub {}]
+ );
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }]);
-
- $ssh->expect($self->{'timeout'},
- ["^([^\\s])*#\\\s\$",
- sub {
- }],
- ["^([^\\s])*>\\\s\$",
- sub {
- }]);
-
- $ssh->log_file(sub { $buf .= shift });
- $ssh->send("set cli screen-length 0\n");
-
- $ssh->expect($self->{'timeout'},
- ["^([^\\s])*#\\\s\$",
- sub {
- }],
- ["^([^\\s])*>\\\s\$",
- sub {
- }]);
+ $ssh->log_file(sub { $buf .= shift });
+ $ssh->send("set cli screen-length 0\n");
+
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^([^\\s])*#\\\s\$', sub {}],
+ ['^([^\\s])*>\\\s\$', sub {}]
+ );
- eval {
-
- local $SIG{ALRM} = sub {
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $ssh->log_file(undef);
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+ alarm($self->{'timeout'});
+
+ if ($cmd =~ /\?/) {
+ $questionMark = 1;
+ $ssh->send("$cmd");
+ }
+ else {
+ $ssh->send("$cmd\n");
+ }
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
+ if ($questionMark) {
+ $cmd =~ s/(.*)\?/$1/;
+ $ssh->expect(
+ $self->{'timeout'},
+ ["^.*# $cmd", sub {}],
+ ["^.*> $cmd", sub {}]
+ );
+ }
+ else {
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^([^\\s])*#\\\s\$', sub {}],
+ ['^([^\\s])*>\\\s\$', sub {}]
+ );
+ }
+ alarm(0);
};
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
- $ssh->log_file(undef);
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- die;
- }
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
- alarm($self->{'timeout'});
-
- if ($cmd =~ /\?/) {
-
- $questionMark = 1;
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\n");
- }
-
- if ($questionMark) {
-
- $cmd =~ s/(.*)\?/$1/;
- $ssh->expect($self->{'timeout'},
- ["^.*# $cmd",
- sub {
- }],
- ["^.*> $cmd",
- sub {
- }]);
- }
- else {
- $ssh->expect($self->{'timeout'},
- ["^([^\\s])*#\\\s\$",
- sub {
- }],
- ["^([^\\s])*>\\\s\$",
- sub {
- }]);
- }
-
- alarm(0);
- };
-
- # remove first 3 lines
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
-
- if ($buf =~ /{.*}.*\n/) {
+ # remove first 3 lines
+ $buf =~ s/.*\n//;
$buf =~ s/.*\n//;
- }
-
- # blank out the prompt on the first line
- $buf = blankPrompt($buf);
- $buf = reverse($buf);
- # remove last line (prompt)
- $buf =~ s/.*\n//;
-
- if ($buf =~ /}.*{.*\n/) {
$buf =~ s/.*\n//;
- }
-
- if ($questionMark) {
- my $check = reverse("syntax error, expecting");
- if ($buf =~ /$check/) {
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- $buf =~ s/.*\n//;
- if ($buf =~ /}.*{.*\n/) {
+ if ($buf =~ /{.*}.*\n/) {
$buf =~ s/.*\n//;
- }
}
- }
-
- $buf = reverse($buf);
-
- return $buf;
-}
-
-sub aristaSSH {
-
- my $self = shift;
- my $cmd = shift;
-
- my $username = $self->{username};
- my $password = $self->{password};
- my $hostname = $self->{hostname};
-
- my $buf;
- my $count = 0;
- my $questionMark = 0;
- my $ssh;
-
- $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
- $ssh->log_stdout(0);
- $ssh->expect($self->{'timeout'},
- ['assword:',
- sub {
- my $out = shift;
- print $out "$password\n";
- exp_continue;
- }],
- ['yes/no',
- sub {
- my $out = shift;
- print $out "yes\n";
- exp_continue;
- }],
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]
- );
-
- $ssh->log_file(sub { $buf .= shift });
- $ssh->send("terminal length 0\n");
- $ssh->expect($self->{'timeout'},
- ['#',
- sub {
- }],
- ['>',
- sub {
- }]);
- eval {
-
- local $SIG{ALRM} = sub {
-
- $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
- die;
- };
-
- alarm($self->{'timeout'});
-
- if ($cmd =~ /\?/) {
- $questionMark = 1;
- $ssh->send("$cmd");
- }
- else {
- $ssh->send("$cmd\n");
- }
-
- $ssh->log_file(sub {
-
- if ($count >= $self->{maxlines}) {
- $ssh->log_file(undef);
- $buf .= "\n--- Maximum Output Exceeded ---\n\n";
- die;
- }
-
- my $data = shift;
- $buf .= $data;
-
- my $newlines = ($data =~ tr/\n//);
- $count += $newlines;
- });
+ # blank out the prompt on the first line
+ $buf = blankPrompt($buf);
+ $buf = reverse($buf);
+ # remove last line (prompt)
+ $buf =~ s/.*\n//;
+ $buf =~ s/.*\n// if ($buf =~ /}.*{.*\n/);
if ($questionMark) {
-
- $cmd =~ s/(.*)\?/$1/;
- $ssh->expect($self->{'timeout'},
- ["^.*[#>]($cmd)",
- sub {}]);
- }
- else {
- $ssh->expect($self->{'timeout'},
- ['^.*#$',
- sub {
- }],
- ['^.*>$',
- sub {
- }]);
+ my $check = reverse("syntax error, expecting");
+ if ($buf =~ /$check/) {
+ $buf =~ s/.*\n//;
+ $buf =~ s/.*\n//;
+ $buf =~ s/.*\n//;
+ $buf =~ s/.*\n//;
+ if ($buf =~ /}.*{.*\n/) {
+ $buf =~ s/.*\n//;
+ }
+ }
}
-
- alarm(0);
- };
-
- # remove first blank line
- $buf =~ s/.*\n//;
- $buf = blankPrompt($buf);
-
- # add an extra space to line up the ^ if needed
- if ($buf =~ /% Invalid input detected at/) {
-
- $buf =~ s/\^/ ^/;
- }
-
- $buf = reverse($buf);
- #remove last line (prompt)
- $buf =~ s/.*\n//;
- $buf = reverse($buf);
-
- return $buf;
+ $buf = reverse($buf);
+ return $buf;
}
-sub blankPrompt {
-
- my $string = shift;
-
- # pull out the first line
- my $line = substr($string, 0, index($string, "\n"));
-
- # find the first >
- my $index = index($line, '>');
-
- # otherwise find the first #
- if ($index < 0) {
- $index = index($line, '#');
- }
-
- # get the prompt (user at host)
- my $prompt = substr($string, 0, $index + 1);
- # print STDERR "index is $index, prompt is $prompt, ";
+sub aristaSSH {
+ my $self = shift;
+ my $cmd = shift;
- # replace each char with a space
- $prompt =~ s/#/>/;
- $prompt =~ s/[^>]/\./g;
+ my $username = $self->{'username'};
+ my $password = $self->{'password'};
+ my $hostname = $self->{'hostname'};
- #print STDERR "now its $prompt\n";
+ my $buf;
+ my $count = 0;
+ my $questionMark = 0;
+ my $ssh;
- # get everything after the prompt
- $string = substr($string, $index + 1);
+ $ssh = Expect->spawn("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l $username $hostname");
+ $ssh->log_stdout(0);
+ $ssh->expect(
+ $self->{'timeout'},
+ [
+ 'assword:',
+ sub {
+ my $out = shift;
+ print $out "$password\n";
+ exp_continue;
+ }
+ ],
+ [
+ 'yes/no',
+ sub {
+ my $out = shift;
+ print $out "yes\n";
+ exp_continue;
+ }
+ ],
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- # reattach our blanked out prompt to the rest of the string
- $string = $prompt . $string;
+ $ssh->log_file(sub { $buf .= shift });
+ $ssh->send("terminal length 0\n");
+ $ssh->expect(
+ $self->{'timeout'},
+ ['#', sub {}],
+ ['>', sub {}]
+ );
- return $string;
-}
+ eval {
+ local $SIG{'ALRM'} = sub {
+ $buf .= "\n--- Maximum Timeout Exceeded ---\n\n";
+ die;
+ };
+ alarm($self->{'timeout'});
+
+ if ($cmd =~ /\?/) {
+ $questionMark = 1;
+ $ssh->send("$cmd");
+ }
+ else {
+ $ssh->send("$cmd\n");
+ }
-#ISSUE=12307 Remove sensitive information, as specified in the config file, from any output
-sub sanitize_text{
- my $self = shift;
- my $text = shift;
+ $ssh->log_file(sub {
+ if ($count >= $self->{'maxlines'}) {
+ $ssh->log_file(undef);
+ $buf .= "\n--- Maximum Output Exceeded ---\n\n";
+ die;
+ }
+ my $data = shift;
+ $buf .= $data;
+ my $newlines = ($data =~ tr/\n//);
+ $count += $newlines;
+ });
+
+ if ($questionMark) {
+ $cmd =~ s/(.*)\?/$1/;
+ $ssh->expect(
+ $self->{'timeout'},
+ ["^.*[#>]($cmd)", sub {}]
+ );
+ }
+ else {
+ $ssh->expect(
+ $self->{'timeout'},
+ ['^.*#$', sub {}],
+ ['^.*>$', sub {}]
+ );
+ }
+ alarm(0);
+ };
- my $conf = GRNOC::RouterProxy::Config->New($self->{'config_path'});
- my $stanzas = $conf->Redacts();
+ # remove first blank line
+ $buf =~ s/.*\n//;
+ $buf = blankPrompt($buf);
- foreach my $stanza ( @$stanzas ) {
- $stanza =~ s/ / \;/g;
- $stanza =~ s/(?/>\;/g;
- $text =~ s/$stanza/\[REDACTED\]/g;
- }
+ # add an extra space to line up the ^ if needed
+ $buf =~ s/\^/ ^/ if ($buf =~ /% Invalid input detected at/);
- return $text;
+ $buf = reverse($buf);
+ #remove last line (prompt)
+ $buf =~ s/.*\n//;
+ $buf = reverse($buf);
+ return $buf;
}
1;
diff --git a/lib/GRNOC/RouterProxy/Config.pm b/lib/GRNOC/RouterProxy/Config.pm
index a07b8c9..1208a3c 100644
--- a/lib/GRNOC/RouterProxy/Config.pm
+++ b/lib/GRNOC/RouterProxy/Config.pm
@@ -7,10 +7,13 @@ use Log::Log4perl;
use XML::Simple;
use YAML;
+Log::Log4perl::init('/etc/grnoc/routerproxy/logging.conf');
+
sub New {
my $class = shift;
+
my $self = {
- log => Log::Log4perl->get_logger('GRNOC.RouterProxy.Config'),
+ log => Log::Log4perl->get_logger('GRNOC.RouterProxy'),
path => shift
};
@@ -41,7 +44,7 @@ sub loadXML {
my $self = shift;
my $path = shift;
- $self->{'log'}->info("Loading xml configuration from $self->{'path'}.");
+ $self->{'log'}->debug("Loading XML config $self->{'path'}");
my $xml = XMLin($path, forcearray => 1);
@@ -174,7 +177,7 @@ Loads configuration from a JSON file.
sub loadYAML {
my $self = shift;
- $self->{'log'}->info("Loading yaml configuration from $self->{'path'}.");
+ $self->{'log'}->debug("Loading YAML config $self->{'path'}.");
my $yaml = YAML::LoadFile($self->{'path'});
diff --git a/lib/GRNOC/RouterProxy/Logger.pm b/lib/GRNOC/RouterProxy/Logger.pm
index 038a3c5..14b0787 100644
--- a/lib/GRNOC/RouterProxy/Logger.pm
+++ b/lib/GRNOC/RouterProxy/Logger.pm
@@ -3,55 +3,38 @@ package GRNOC::RouterProxy::Logger;
use Time::ParseDate;
sub addEntry {
+ my ($logfile, $ip, $router, $cmd) = @_;
- my $logfile = shift;
- my $ip = shift;
- my $router = shift;
- my $cmd = shift;
-
- my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
- $year += 1900;
- $mon++;
-
- if ($hour < 10) {
- $hour = "0$hour";
- }
- if ($min < 10) {
- $min = "0$min";
- }
- if ($sec < 10) {
- $sec = "0$sec";
- }
-
- my $time = "[$year/$mon/$mday $hour:$min:$sec]";
-
- open(FILE, ">>$logfile") || die ("Error opening log file");
- print FILE "$time $ip $router: $cmd\n";
- close(FILE);
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
+ $year += 1900;
+ $mon++;
+ $hour = "0$hour" if ($hour < 10);
+ $min = "0$min" if ($min < 10);
+ $sec = "0$sec" if ($sec < 10);
+
+ my $time = "[$year/$mon/$mday $hour:$min:$sec]";
+
+ open(FILE, ">>$logfile") || die ("ERROR: Could not open logfile '$logfile'");
+ print FILE "$time $ip $router: $cmd\n";
+ close(FILE);
}
sub getLastTime {
+ my $logfile = shift;
+
+ open(FILE, $logfile);
+ my @lines = ;
+ close(FILE);
+
+ my $lastLine = $lines[@lines - 1];
+ return undef unless $lastLine;
+
+ my ($year, $month, $day, $hour, $min, $sec) = $lastLine =~ /\[([^\/]*)\/([^\/]*)\/([^ ]*) ([^:]*):([^:]*):([^\]]*).*/;
+ $hour = "0$hour" if ($hour < 10);
+ $min = "0$min" if ($min < 10);
+ $sec = "0$sec" if ($sec < 10);
- my $logfile = shift;
- open(FILE, $logfile);
- my @lines = ;
- close(FILE);
-
- my $lastLine = $lines[@lines - 1];
- my ($year, $month, $day, $hour, $min, $sec) = $lastLine =~ /\[([^\/]*)\/([^\/]*)\/([^ ]*) ([^:]*):([^:]*):([^\]]*).*/;
- #$month++;
-
- if ($hour < 10) {
- $hour = "0" . $hour;
- }
- if ($min < 10) {
- $min = "0" . $min;
- }
- if ($sec < 10) {
- $sec = "0" . $sec;
- }
-
- return parsedate("$month-$day-$year $hour:$min:$sec");
+ return parsedate("$month-$day-$year $hour:$min:$sec");
}
1;
diff --git a/webroot/index.cgi b/webroot/index.cgi
index 6aa1e17..90ecb8a 100755
--- a/webroot/index.cgi
+++ b/webroot/index.cgi
@@ -1,26 +1,38 @@
#!/usr/bin/perl
+use strict;
use warnings;
-use FindBin;
-
use CGI;
+use JSON;
+use FindBin;
use FileHandle;
+use Encode;
+use Template;
use XML::Simple;
+use Data::Dumper;
+use Time::ParseDate;
+
use GRNOC::RouterProxy;
+use GRNOC::RouterProxy::Logger;
use GRNOC::RouterProxy::Config;
use GRNOC::RouterProxy::Commands;
-use Encode;
-use Data::Dumper;
use GRNOC::Config;
-use Template;
-use JSON;
+use GRNOC::TL1;
+use GRNOC::TL1::Device::Nortel::OME6500;
+use GRNOC::TL1::Device::Nortel::HDXc;
+use GRNOC::TL1::Device::Cisco::ONS15454;
+use GRNOC::TL1::Device::Ciena::CoreDirector;
-# set our home directory relative to our script
+# Set the home directory relative to this script
my $home_dir = "$FindBin::Bin/../";
$ENV{'HOME'} = $home_dir;
-# do they have Junoscript installed?
+# Initialize the logger
+Log::Log4perl::init('/etc/grnoc/routerproxy/logging.conf');
+my $logger = Log::Log4perl->get_logger('GRNOC.RouterProxy');
+
+# Check for and import JUNOS Script support
my $hasJunoscript;
BEGIN {
eval {
@@ -34,7 +46,7 @@ BEGIN {
}
}
-# do they have IOS XR XML installed?
+# Check for and import IOS XR XML support
my $hasIosXML;
BEGIN {
eval {
@@ -48,66 +60,100 @@ BEGIN {
}
}
-use GRNOC::TL1;
-use GRNOC::TL1::Device::Nortel::OME6500;
-use GRNOC::TL1::Device::Nortel::HDXc;
-use GRNOC::TL1::Device::Cisco::ONS15454;
-use GRNOC::TL1::Device::Ciena::CoreDirector;
-
-use GRNOC::RouterProxy::Logger;
-use Time::ParseDate;
-
-use strict;
-
-# use fast XML parser
+# Use the fast XML parser
local $ENV{'XML_SIMPLE_PREFERRED_PARSER'} = 'XML::Parser';
+# Init CGI
my $cgi = CGI->new();
-my $config_path = ConfigChooser( $ENV{'REQUEST_URI'},
- "/etc/grnoc/routerproxy/mappings.xml");
+# Confirm the mappings config path or error out
+my $config_path = getMappedConfig($ENV{'REQUEST_URI'}, "/etc/grnoc/routerproxy/mappings.xml");
unless (defined($config_path) && -e $config_path) {
- warn ("Please check mapping file. The config file for this url cannot be located\n");
+ my $msg = "Configuration for $ENV{'REQUEST_URI'} not found. Check mapping file '$config_path'";
+ $logger->error($msg);
print $cgi->header();
print $cgi->start_html();
- print "Please check mapping file. The config file for this url cannot be located
";
+ print "$msg
";
print $cgi->end_html();
-
exit 1;
}
+# Read the config and store devices by address
my $conf = GRNOC::RouterProxy::Config->New($config_path);
+my $devices = $conf->Devices();
+my $logfile = $conf->LogFile();
+my $maxlines = $conf->MaxLines();
+my $timeout = $conf->MaxTimeout();
+my $spamSeconds = $conf->MaxRate();
+my $enable_menu = $conf->ShowDropdown();
+my $remoteIP = $ENV{'REMOTE_ADDR'};
-# A little hack to store devices by address. Should be changed to use
-# device name in the future.
-my $devices = $conf->Devices();
-my $logfile = $conf->LogFile();
-my $maxlines = $conf->MaxLines();
-my $timeout = $conf->MaxTimeout();
-my $spamSeconds = $conf->MaxRate();
-my $global_enable_menu_commands = $conf->ShowDropdown();
+# Handles errors for undefined methods
+sub getError {
+ my $msg = "The requested method does not exist";
+ $logger->error($msg);
+ print $cgi->header(-type => "text/html", -status => "501");
+ print $msg;
+}
+
-my $remoteIP = $ENV{'REMOTE_ADDR'};
+# Prints HTML to STDOUT, called immediately after definition
+sub makeHTML2 {
+ my $template = Template->new({ABSOLUTE => 1});
+ my $input = "/usr/share/grnoc/routerproxy/templates/index.tt";
+
+ # If $handler is defined outside the makeHTML2 subroutine this error is returned:
+ # Can't use string ("") as a subroutine ref while "strict refs" in use at /gnoc/routerproxy/webroot/index.cgi line 302.
+ my $handler = {
+ device => \&getDevice,
+ devices => \&getDevices,
+ error => \&getError,
+ submit => \&getResponses
+ };
+ # Check if a method has been called on this CGI.
+ my $method = $cgi->param('method');
+ if (defined $method) {
+ if (!defined $handler->{$method}) {
+ $handler->{"error"}->();
+ } else {
+ $handler->{$method}->();
+ }
+ # HTML has been printed; Return.
+ return;
+ }
-# Prints HTML to STDOUT
+ my $html = "";
+ my $vars = {
+ network_name => $conf->NetworkName(),
+ primary_color => $conf->PrimaryColor(),
+ secondary_color => $conf->SecondaryColor(),
+ noc_mail => $conf->NOCMail(),
+ noc_name => $conf->NOCName(),
+ noc_site => $conf->NOCSite(),
+ groups => $conf->DeviceGroups(sort_devices => 1)
+ };
+ $template->process($input, $vars, \$html);
+ print $cgi->header(-type => "text/html", -status => "200");
+ print $html;
+ return;
+}
makeHTML2();
-sub ConfigChooser {
- my $url = shift;
- my $map_file = shift;
-
- # If mapping file is not found
+# Gets a YAML config using the mappings config
+sub getMappedConfig {
+ my ($url, $map_file) = @_;
+
+ # Confirm the mapping config exists
unless (-e $map_file) {
- warn ("Mapping file is not found.\n");
+ $logger->error("Mapping file '$map_file' not found.\n");
return undef;
}
my $config = GRNOC::Config->new( config_file => $map_file, force_array => 1 );
my $entries = $config->get( '/mappings/map' );
-
foreach my $entry ( @$entries ) {
my $regexp = $entry->{'regexp'};
if ( $url =~ /$regexp/ ) {
@@ -117,45 +163,55 @@ sub ConfigChooser {
return undef;
}
+
+# Gets device metadata and prints it on the page
sub getDevice {
my $device = $cgi->param("device");
+
if (!defined $device) {
- print $cgi->header(-type => "text/html",
- -status => "400" );
- print "Request requires parameters: device";
+ my $msg = "Request is missing the 'device' parameter";
+ $logger->error($msg);
+ print $cgi->header(-type => "text/html", -status => "400");
+ print $msg;
return;
}
# Create a copy of the device data and remove all secrets.
my $data = $devices->{$device};
+
if (!defined $data) {
- print $cgi->header(-type => "text/html",
- -status => "200" );
- print "The specified device does not exist.";
+ my $msg = "The specified device '$device' does not exist";
+ $logger->error($msg);
+ print $cgi->header(-type => "text/html", -status => "200");
+ print $msg;
return;
}
+ # Set commands and menu flag
$data->{"commands"} = $conf->DeviceCommands($data->{"address"});
- $data->{"enable_menu"} = $global_enable_menu_commands;
+ $data->{"enable_menu"} = $enable_menu;
+ # Remove sensitive data fields
delete $data->{"username"};
delete $data->{"password"};
delete $data->{"method"};
delete $data->{"command_group"};
delete $data->{"exclude_group"};
- print $cgi->header(-type => "text/html",
- -status => "200" );
+ # Print the data as encoded JSON
+ print $cgi->header(-type => "text/html", -status => "200");
print encode_json($data);
}
+
+# getDevice for many devices
sub getDevices {
my @device_keys = keys %$devices;
my @result = ();
foreach my $key (keys %$devices) {
my $data = $devices->{$key};
$data->{"commands"} = $conf->DeviceCommands($data->{"address"});
- $data->{"enable_menu"} = $global_enable_menu_commands;
+ $data->{"enable_menu"} = $enable_menu;
delete $data->{"username"};
delete $data->{"password"};
@@ -164,56 +220,76 @@ sub getDevices {
delete $data->{"exclude_group"};
push @result, $data;
}
- print $cgi->header(-type => "text/html",
- -status => "200" );
+ print $cgi->header(-type => "text/html", -status => "200");
print encode_json(\@result);
}
+
+# Filters out spam requests by comparing last op time and $now using logs
+sub filterSpam {
+ # Get the last log time from the logfile
+ my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
+
+ # Don't try to enforce spam limits for new logfiles
+ return unless $last;
+
+ # Return a warning of how log to wait if the last command was less than spamSeconds before
+ my $diff = time() - $last;
+ if ($diff < $spamSeconds) {
+ my $wait = $spamSeconds - $diff;
+ return "Please wait $wait seconds before sending another command.";
+ }
+ return;
+}
+
+
+# Handle the request for data from a device for a command and return the response to the page
sub getResponses {
my $address = $cgi->param("device");
my $command = $cgi->param("command");
my $arguments = $cgi->param("arguments") || "";
my $menu_req = $cgi->param("menu") || 0;
+ # Confirm that the request has an address and command
if (!defined $address || !defined $command) {
- print $cgi->header(-type => "text/html",
- -status => "400" );
- print "Request requires parameters: device, command";
+ my $msg = "Request is missing either the 'device' or 'command' parameters";
+ $logger->error($msg);
+ print $cgi->header(-type => "text/html", -status => "400" );
+ print $msg;
return;
}
+ # Get the device data from the hash and confirm it is not empty
my $device = $devices->{$address};
if (!defined $device) {
- print $cgi->header(-type => "text/html",
- -status => "200" );
- print "The specified device does not exist.";
+ my $msg = "The specified device '$device' does not exist";
+ $logger->error($msg);
+ print $cgi->header(-type => "text/html", -status => "200" );
+ print $msg;
return;
}
- my $menu_enabled = $global_enable_menu_commands;
- my $data = "";
-
- if ($menu_req && $menu_enabled && $device->{"type"} eq "junos") {
- $data = getMenuResponse($command, $device);
- } elsif ($menu_req && $menu_enabled && $device->{"type"} eq "iosxr") {
- $data = getIosMenuResponse($command, $device);
- } elsif ($menu_req && $menu_enabled && $device->{"type"} eq "hdxc") {
- $data = getHdxcMenuResponse($command, $device);
- } elsif ($menu_req && $menu_enabled && $device->{"type"} eq "ons15454") {
- $data = getOnsMenuResponse($command, $device);
- } elsif ($menu_req && $menu_enabled && $device->{"type"} eq "ome") {
- $data = getOmeMenuResponse($command, $device);
- } elsif ($menu_req && $menu_enabled && $device->{"type"} eq "ciena") {
- $data = getCienaMenuResponse($command, $device);
+ # Route the request and return the response to the page
+ my $response = "";
+ if ($menu_req && $enable_menu && $device->{"type"} eq "junos") {
+ $response = getMenuResponse($command, $device);
+ } elsif ($menu_req && $enable_menu && $device->{"type"} eq "iosxr") {
+ $response = getIosMenuResponse($command, $device);
+ } elsif ($menu_req && $enable_menu && $device->{"type"} eq "hdxc") {
+ $response = getHdxcMenuResponse($command, $device);
+ } elsif ($menu_req && $enable_menu && $device->{"type"} eq "ons15454") {
+ $response = getOnsMenuResponse($command, $device);
+ } elsif ($menu_req && $enable_menu && $device->{"type"} eq "ome") {
+ $response = getOmeMenuResponse($command, $device);
+ } elsif ($menu_req && $enable_menu && $device->{"type"} eq "ciena") {
+ $response = getCienaMenuResponse($command, $device);
} elsif ($menu_req) {
- $data = "Menu enabled requests are not configured for this device. Please reload the page.";
+ $response = "Menu-enabled requests are not configured for this device. Please reload the page.";
} else {
- $data = getResponse($command, $arguments, $device);
+ $response = getResponse($command, $arguments, $device);
}
-
- print $cgi->header(-type => "text/html",
- -status => "200" );
- print "$data";
+ print $cgi->header(-type => "text/html", -status => "200");
+ print "$response";
}
@@ -222,427 +298,254 @@ sub getResponse {
my $arguments = shift;
my $device = shift;
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ if (!validCommand($command, $arguments, $device) && $device->{'type'} ne 'TEST') {
+ my $msg = "Attempt to issue disabled command '$command' for $device->{'name'}";
+ $logger->info($msg);
+ return $msg;
}
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device->{'address'}, $command . " " . $arguments);
- if (!validCommand($command, $arguments, $device)) {
- return "Disabled Command.";
- }
+ # Append arguments to the command if any
+ $command = $command . " " . $arguments if ($arguments ne "");
- if ($arguments ne "") {
- $command = $command . " " . $arguments;
- }
+ # Add the command to the history log
+ GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device->{'address'}, $command . " " . $arguments);
- my $name = $device->{'name'};
- my $hostname = $device->{'address'};
- my $method = $device->{'method'};
+ # Fix encoding (legacy)
my $username = $device->{'username'};
my $password = $device->{'password'};
- my $type = $device->{'type'};
- my $port = $device->{'port'};
-
- # Fix encoding. I don't know why. This is legecy.
Encode::from_to($username, 'utf8', 'iso-8859-1');
Encode::from_to($password, 'utf8', 'iso-8859-1');
my $proxy = GRNOC::RouterProxy->new(
- hostname => $hostname,
- port => $port,
+ hostname => $device->{'address'},
+ port => $device->{'port'},
+ method => $device->{'method'},
+ type => $device->{'type'},
username => $username,
password => $password,
- method => $method,
- type => $type,
maxlines => $maxlines,
config_path => $config_path,
timeout => $timeout
);
my $result = $proxy->command($command);
- # End the timer if the command was successful.
+ # End the timer if the command was successful and return the result
alarm(0);
return $result;
}
-sub getError {
- print $cgi->header(-type => "text/html",
- -status => "501" );
- print "The requested method does not exist.";
-}
-
-sub makeHTML2 {
- my $tt = Template->new({ ABSOLUTE => 1 });
- my $input = "/usr/share/grnoc/routerproxy/templates/index.tt";
-
- # If $handler is defined outside the makeHTML2 subroutine an error
- # is returned.
- #
- # Can't use string ("") as a subroutine ref while "strict refs" in
- # use at /gnoc/routerproxy/webroot/index.cgi line 302.
- my $handler = { device => \&getDevice,
- devices => \&getDevices,
- error => \&getError,
- submit => \&getResponses
- };
- # Check if a method has been called on this CGI.
- my $method = $cgi->param('method');
- if (defined $method) {
- if (!defined $handler->{$method}) {
- $handler->{"error"}->();
- } else {
- $handler->{$method}->();
- }
- # HTML has been printed; Return.
- return;
- }
+sub tl1Connect {
+ my ($cmd, $device) = @_;
- my $html = "";
- my $vars = { network_name => $conf->NetworkName(),
- primary_color => $conf->PrimaryColor(),
- secondary_color => $conf->SecondaryColor(),
- noc_mail => $conf->NOCMail(),
- noc_name => $conf->NOCName(),
- noc_site => $conf->NOCSite(),
- groups => $conf->DeviceGroups(sort_devices => 1)
- };
- $tt->process($input, $vars, \$html);
-
- print $cgi->header(-type => "text/html",
- -status => "200" );
- print $html;
- return;
-}
+ # Add a history log entry for this command and device
+ GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-sub getCienaMenuResponse {
+ # Create a TL1 connection for issuing commands
+ $logger->debug("Establishing TL1 connection to $device->{'name'}");
+ my $tl1 = GRNOC::TL1->new(
+ username => $device->{'username'},
+ password => $device->{'password'},
+ type => $device->{'type'},
+ host => $device->{'address'},
+ port => $device->{'port'},
+ ctag => 1337
+ );
+ $tl1->connect();
+ $tl1->login();
- my $cmd = shift;
- my $device = shift;
-
- my @rows;
- my $result;
-
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-
- # make sure the device exists in the config
- if ( !defined( $devices->{$device} ) ) {
-
- return "Requested device is not configured. Please reload the page.";
- }
-
- # use my TL1 module to issue the command
- my $name = $devices->{$device}->{'name'};
- my $hostname = $devices->{$device}->{'address'};
- my $method = $devices->{$device}->{'method'};
- my $username = $devices->{$device}->{'username'};
- my $password = $devices->{$device}->{'password'};
- my $type = $devices->{$device}->{'type'};
- my $port = $devices->{$device}->{'port'};
-
- my $tl1 = GRNOC::TL1->new(
- username => $username,
- password => $password,
- type => $type,
- host => $hostname,
- port => $port,
- ctag => 1337);
-
- $tl1->connect();
- $tl1->login();
-
- # alarms cmd
- if ($cmd eq "alarms") {
-
- @rows = $tl1->get_alarms();
- $result = retrAlmAll3(@rows);
- }
-
- # eqpt cmd
- elsif ($cmd eq "inventory") {
-
- @rows = $tl1->get_inventory();
- $result = retrEqpt(@rows);
- }
-
- # circuits cmd
- elsif ($cmd eq "circuits") {
-
- @rows = $tl1->get_cross_connects();
- $result = retrCrs2(@rows);
- }
-
- return $result;
+ # Return the TL1 connection
+ return $tl1;
}
-sub getOnsMenuResponse {
- my $cmd = shift;
- my $device = shift;
-
- my @rows;
- my $result;
-
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-
- # make sure the device exists in the config
- if ( !defined( $devices->{$device} ) ) {
-
- return "Requested device is not configured. Please reload the page.";
- }
-
- # use my TL1 module to issue the command
- my $name = $devices->{$device}->{'name'};
- my $hostname = $devices->{$device}->{'address'};
- my $method = $devices->{$device}->{'method'};
- my $username = $devices->{$device}->{'username'};
- my $password = $devices->{$device}->{'password'};
- my $type = $devices->{$device}->{'type'};
- my $port = $devices->{$device}->{'port'};
-
- my $tl1 = GRNOC::TL1->new(
- username => $username,
- password => $password,
- type => $type,
- host => $hostname,
- port => $port,
- ctag => 1337);
-
- $tl1->connect();
- $tl1->login();
-
- # alarms cmd
- if ($cmd eq "alarms") {
-
- @rows = $tl1->get_alarms();
- $result = retrAlmAll(@rows);
- }
-
- # circuits cmd
- elsif ($cmd eq "circuits") {
-
- @rows = $tl1->get_cross_connects();
- $result = retrCrs(@rows);
- }
-
- # inventory cmd
- elsif ($cmd eq "inventory") {
-
- @rows = $tl1->get_inventory();
- $result = retrInv(@rows);
- }
-
- return $result;
-}
+sub getCienaMenuResponse {
+ my ($cmd, $device) = @_;
+ my @rows;
+ my $result;
+
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ # Get the device from the hash of devices if it exists or return a warning
+ $device = $devices->{$device} if (exists($devices->{$device}) && defined($devices->{$device}));
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device->{'name'}\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
-sub getOmeMenuResponse {
+ my $tl1 = tl1Connect($cmd, $device);
- my $cmd = shift;
- my $device = shift;
-
- my @rows;
- my $result;
-
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-
- # make sure the device exists in the config
- if ( !defined( $devices->{$device} ) ) {
-
- return "Requested device is not configured. Please reload the page.";
- }
-
- # use my TL1 module to issue the command
- my $name = $devices->{$device}->{'name'};
- my $hostname = $devices->{$device}->{'address'};
- my $method = $devices->{$device}->{'method'};
- my $username = $devices->{$device}->{'username'};
- my $password = $devices->{$device}->{'password'};
- my $type = $devices->{$device}->{'type'};
- my $port = $devices->{$device}->{'port'};
-
- my $tl1 = GRNOC::TL1->new(
- username => $username,
- password => $password,
- type => $type,
- host => $hostname,
- port => $port,
- ctag => 1337);
-
- $tl1->connect();
- $tl1->login();
-
- # alarms cmd
- if ($cmd eq "alarms") {
-
- @rows = $tl1->get_alarms();
- $result = retrAlmAll2(@rows);
- }
-
- # circuits cmd
- elsif ($cmd eq "circuits") {
-
- @rows = $tl1->get_cross_connects();
- $result = retrCrsAll2(@rows);
- }
-
- # inventory cmd
- elsif ($cmd eq "inventory") {
-
- @rows = $tl1->get_inventory();
- $result = retrInventory2(@rows);
- # ons15454$result = retrInv(@rows);
- }
-
- return $result;
+ if ($cmd eq "alarms") {
+ @rows = $tl1->get_alarms();
+ $result = retrAlmAll3(@rows);
+ }
+ elsif ($cmd eq "inventory") {
+ @rows = $tl1->get_inventory();
+ $result = retrEqpt(@rows);
+ }
+ elsif ($cmd eq "circuits") {
+ @rows = $tl1->get_cross_connects();
+ $result = retrCrs2(@rows);
+ }
+ return $result;
}
-sub getHdxcMenuResponse {
-
- my $cmd = shift;
- my $device = shift;
- my @rows;
- my $result;
-
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-
- # make sure the device exists in the config
- if ( !defined( $devices->{$device} ) ) {
- return "Requested device is not configured. Please reload the page.";
- }
-
- # use my TL1 module to issue the command
- my $name = $devices->{$device}->{'name'};
- my $hostname = $devices->{$device}->{'address'};
- my $method = $devices->{$device}->{'method'};
- my $username = $devices->{$device}->{'username'};
- my $password = $devices->{$device}->{'password'};
- my $type = $devices->{$device}->{'type'};
- my $port = $devices->{$device}->{'port'};
-
- my $tl1 = GRNOC::TL1->new(
- username => $username,
- password => $password,
- type => $type,
- host => $hostname,
- port => $port,
- ctag => 1337);
-
- $tl1->connect();
- $tl1->login();
-
- # alarms cmd
- if ($cmd eq "alarms") {
+sub getOnsMenuResponse {
+ my ($cmd, $device) = @_;
+ my @rows;
+ my $result;
+
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ # Get the device from the hash of devices if it exists or return a warning
+ $device = $devices->{$device} if (exists($devices->{$device}) && defined($devices->{$device}));
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device->{'name'}\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
- @rows = $tl1->get_alarms();
- $result = retrAlmAll(@rows);
- }
+ my $tl1 = tl1Connect($cmd, $device);
- # circuits cmd
- elsif ($cmd eq "circuits") {
+ if ($cmd eq "alarms") {
+ @rows = $tl1->get_alarms();
+ $result = retrAlmAll(@rows);
+ }
+ elsif ($cmd eq "circuits") {
+ @rows = $tl1->get_cross_connects();
+ $result = retrCrs(@rows);
+ }
+ elsif ($cmd eq "inventory") {
+ @rows = $tl1->get_inventory();
+ $result = retrInv(@rows);
+ }
+ return $result;
+}
- @rows = $tl1->get_cross_connects();
- $result = retrCrsAll(@rows);
- }
- # inventory cmd
- elsif ($cmd eq "inventory") {
+sub getOmeMenuResponse {
+ my ($cmd, $device) = @_;
+ my @rows;
+ my $result;
+
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ # Get the device from the hash of devices if it exists or return a warning
+ $device = $devices->{$device} if (exists($devices->{$device}) && defined($devices->{$device}));
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device->{'name'}\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
- @rows = $tl1->get_inventory();
+ my $tl1 = tl1Connect($cmd, $device);
- if ($type eq "hdxc") {
- $result = retrInventory(@rows);
+ if ($cmd eq "alarms") {
+ @rows = $tl1->get_alarms();
+ $result = retrAlmAll2(@rows);
}
- elsif ($type eq "ome") {
- $result = retrInventory2(@rows);
+ elsif ($cmd eq "circuits") {
+ @rows = $tl1->get_cross_connects();
+ $result = retrCrsAll2(@rows);
}
- else {
- $result = retrInv(@rows);
+ elsif ($cmd eq "inventory") {
+ @rows = $tl1->get_inventory();
+ $result = retrInventory2(@rows);
+ # ons15454$result = retrInv(@rows);
}
- }
-
- return $result;
+ return $result;
}
-sub getIosMenuResponse {
- my $cmd = shift;
- my $device = shift;
+sub getHdxcMenuResponse {
+ my ($cmd, $device) = @_;
+ my @rows;
+ my $result;
+
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ # Get the device from the hash of devices if it exists or return a warning
+ $device = $devices->{$device} if (exists($devices->{$device}) && defined($devices->{$device}));
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device->{'name'}\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
- if (!$hasIosXML) {
- return "IOS XR XML must be installed.";
- }
+ my $tl1 = tl1Connect($cmd, $device);
- my $result;
+ if ($cmd eq "alarms") {
+ @rows = $tl1->get_alarms();
+ $result = retrAlmAll(@rows);
+ }
+ elsif ($cmd eq "circuits") {
+ @rows = $tl1->get_cross_connects();
+ $result = retrCrsAll(@rows);
+ }
+ elsif ($cmd eq "inventory") {
+ @rows = $tl1->get_inventory();
+ if ($device->{'type'} eq "hdxc") {
+ $result = retrInventory(@rows);
+ }
+ elsif ($device->{'type'} eq "ome") {
+ $result = retrInventory2(@rows);
+ }
+ else {
+ $result = retrInv(@rows);
+ }
+ }
+ return $result;
+}
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
- # make sure the device exists in the config
- if ( !defined( $devices->{$device} ) ) {
+sub getIosMenuResponse {
+ my ($cmd, $device) = @_;
+ my $result;
- return "Requested device is not configured. Please reload the page.";
- }
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
- # use IOS XR XML to issue the command
- my $name = $devices->{$device}->{'name'};
- my $address = $devices->{$device}->{'address'};
+ # Return early if IOS XR XML isn't installed
+ return "IOS XR XML must be installed" if (!$hasIosXML);
- my $cisco = Cisco::IOS_XR->new(
- host => $address,
- transport => $devices->{$device}->{'method'},
- username => $devices->{$device}->{'username'},
- password => $devices->{$device}->{'password'},
- connection_timeout => $timeout);
+ # Get the device from the hash of devices if it exists or return a warning
+ $device = $devices->{$device} if (exists($devices->{$device}) && defined($devices->{$device}));
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device->{'name'}\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
- if ($cmd eq "bgp") {
+ GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
- my $oper = Cisco::IOS_XR::Data::Operational();
- $result = $oper->BGP->DefaultVRF->NeighborTable->get_keys();
- $result = "
" . bgp($result, $oper);
- }
+ # Get the device name to simplify formatting
+ my $name = $device->{'name'};
- elsif ($cmd eq "isis") {
+ # Connect to the device
+ my $cisco = Cisco::IOS_XR->new(
+ host => $device->{'address'},
+ transport => $device->{'method'},
+ username => $device->{'username'},
+ password => $device->{'password'},
+ connection_timeout => $timeout
+ );
- my $xml = '
+ if ($cmd eq "bgp") {
+ my $oper = Cisco::IOS_XR::Data::Operational();
+ $result = $oper->BGP->DefaultVRF->NeighborTable->get_keys();
+ $result = "
" . bgp($result, $oper);
+ }
+ elsif ($cmd eq "isis") {
+ my $xml = '
@@ -651,13 +554,11 @@ sub getIosMenuResponse {
';
- $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
- $result = "
" . isis($result);
- }
-
- elsif ($cmd eq "msdp") {
-
- my $xml = '
+ $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
+ $result = "
" . isis($result);
+ }
+ elsif ($cmd eq "msdp") {
+ my $xml = '
@@ -666,13 +567,11 @@ sub getIosMenuResponse {
';
- $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
- $result = "
" . msdp($result);
- }
-
- elsif ($cmd eq "interfaces") {
-
- my $xml = '
+ $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
+ $result = "
" . msdp($result);
+ }
+ elsif ($cmd eq "interfaces") {
+ my $xml = '
@@ -681,13 +580,11 @@ sub getIosMenuResponse {
';
- $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
- $result = "
" . interfaces($result);
- }
-
- elsif ($cmd eq "inventory") {
-
- my $xml = '
+ $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
+ $result = "
" . interfaces($result);
+ }
+ elsif ($cmd eq "inventory") {
+ my $xml = '
@@ -695,13 +592,11 @@ sub getIosMenuResponse {
';
- $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
- $result = "
" . inventory($result);
- }
-
- elsif ($cmd eq "ipv6Neighbors") {
-
- my $xml = '
+ $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
+ $result = "
" . inventory($result);
+ }
+ elsif ($cmd eq "ipv6Neighbors") {
+ my $xml = '
@@ -709,176 +604,100 @@ sub getIosMenuResponse {
';
- $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
- $result = "
" . ipv6Neighbors($result);
- }
-
- return $result;
+ $result = XMLin($cisco->send_req($xml)->to_string, forcearray => 1);
+ $result = "
" . ipv6Neighbors($result);
+ }
+ return $result;
}
-sub getMenuResponse {
-
- my $cmd = shift;
- my $device = shift;
-
- if (!$hasJunoscript) {
- return ("Junoscript must be installed.", "");
- }
-
- my $result;
- my $xml;
-
- my $last = GRNOC::RouterProxy::Logger::getLastTime($logfile);
- my $now = time();
- my $diff = $now - $last;
- if ($diff < $spamSeconds) {
- my $wait = $spamSeconds - $diff;
- return "Please wait $wait seconds before sending another command.";
- }
- GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
-
- # make sure the device exists in the config
- if (!defined $device) {
- return "Requested device $device is not configured. Please reload the page.";
- }
-
- # use JUNOSCRIPT to issue the command
- my $name = $device->{'name'};
- my $hostname = $device->{'address'};
- my $method = $device->{'method'};
- my $username = $device->{'username'};
- my $password = $device->{'password'};
- my $type = $device->{'type'};
-
- $username = encode("utf8", $username);
- $password = encode("utf8", $password);
-
- my %info = (
- access => $method,
- login => $username,
- password => $password,
- hostname => $hostname);
-
- my $junos = new JUNOS::Device(%info);
- if ($cmd eq "bgp") {
-
- $result = $junos->command("show bgp summary")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showBgpSummary($xml);
- }
-
- # show system boot-messages command
- elsif ($cmd eq "bootMessages") {
-
- $result = $junos->command("show system boot-messages")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showSystemBootMessages($xml);
- }
-
- # show chassis environment command
- elsif ($cmd eq "environment") {
-
- $result = $junos->command("show chassis environment")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showChassisEnvironment($xml);
- }
-
- # show system storge command
- elsif ($cmd eq "filesystem") {
-
- $result = $junos->command("show system storage")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showSystemStorage($xml);
- }
-
- # show interfaces detail
- elsif ($cmd eq "interfaces") {
-
- $result = $junos->command("show interfaces")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showInterfaces($xml);
- }
-
- # show chassis hardware command
- elsif ($cmd eq "inventory") {
-
- $result = $junos->command("show chassis hardware")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showChassisHardware($xml);
- }
-
- # show ipv6 neighbors command
- elsif ($cmd eq "ipv6Neighbors") {
-
- $result = $junos->command("show ipv6 neighbors")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showIpv6Neighbors($xml);
- }
-
- # show isis adjacency command
- elsif ($cmd eq "isis") {
-
- $result = $junos->command("show isis adjacency")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showIsisAdjacency($xml);
- }
-
- # show msdp detail command
- elsif ($cmd eq "msdp") {
-
- $result = $junos->command("show msdp detail")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showMsdpDetail($xml);
- }
-
- # show multicast statistics command
- elsif ($cmd eq "multicastStatistics") {
-
- $result = $junos->command("show multicast statistics")->toString;
+# Helper function to get and format JUNOS command results
+sub junosResult {
+ my ($junos, $cmd, $method, $msg) = @_;
+ my $result = $junos->command($cmd)->toString;
$result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showMulticastStatistics($xml);
- }
-
- # show snmp statistics command
- elsif ($cmd eq "snmpStatistics") {
+ my $xml = XMLin($result, forcearray => 1);
+ $result = "
" . $method->($xml);
+}
- $result = $junos->command("show snmp statistics")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showSnmpStatistics($xml);
- }
- # show version command
- elsif ($cmd eq "version") {
+sub getMenuResponse {
+ my ($cmd, $device) = @_;
+ my $result;
+
+ # Return early if JUNOS Script isn't installed
+ return ("Junoscript must be installed", "") if (!$hasJunoscript);
+
+ my $spam_warning = filterSpam();
+ return $spam_warning if ($spam_warning);
+
+ GRNOC::RouterProxy::Logger::addEntry($logfile, $remoteIP, $device, $cmd);
+
+ # Return a warning if the device doesn't exist
+ if (!defined($device)) {
+ my $msg = "The requested device \"$device\" does not exist. Please reload the page.";
+ $logger->warn($msg);
+ return $msg;
+ }
- $result = $junos->command("show version")->toString;
- $result =~ s/junos://g;
- $xml = XMLin($result, forcearray => 1);
- $result = "
" . showVersion($xml);
- }
+ # Issue the command with JUNOSCRIPT
+ my %info = (
+ hostname => $device->{'address'},
+ access => $device->{'method'},
+ login => encode("utf8", $device->{'username'}),
+ password => encode("utf8", $device->{'password'}),
+ );
+ my $junos = new JUNOS::Device(%info);
- return $result;
+ # Route menu commands to the right JUNOS command and processing method
+ if ($cmd eq "bgp") {
+ $result = junosResult($junos, 'show bgp summary', \&showBgpSummary, "BGP Summary for $device->{'name'}");
+ }
+ elsif ($cmd eq "bootMessages") {
+ $result = junosResult($junos, 'show system boot-messages', \&showSystemBootMessages, "System Boot Messages for $device->{'name'}");
+ }
+ elsif ($cmd eq "environment") {
+ $result = junosResult($junos, 'show chassis environment', \&showChassisEnvironment, "Chassis Environment for $device->{'name'}");
+ }
+ elsif ($cmd eq "filesystem") {
+ $result = junosResult($junos, 'show system storage', \&showSystemStorage, "System Storage for $device->{'name'}");
+ }
+ elsif ($cmd eq "interfaces") {
+ $result = junosResult($junos, 'show interfaces', \&showInterfaces, "Interfaces for $device->{'name'}");
+ }
+ elsif ($cmd eq "inventory") {
+ $result = junosResult($junos, 'show chassis hardware', \&showChassisHardware, "Chassis Hardware for $device->{'name'}");
+ }
+ elsif ($cmd eq "ipv6Neighbors") {
+ $result = junosResult($junos, 'show ipv6 neighbors', \&showIpv6Neighbors, "IPv6 Neighbors for $device->{'name'}");
+ }
+ elsif ($cmd eq "isis") {
+ $result = junosResult($junos, 'show isis adjacency', \&showIsisAdjacency, "ISIS Adjacencies for $device->{'name'}");
+ }
+ elsif ($cmd eq "msdp") {
+ $result = junosResult($junos, 'show msdp detail', \&showMsdpDetail, "MSDP Details for $device->{'name'}");
+ }
+ elsif ($cmd eq "multicastStatistics") {
+ $result = junosResult($junos, 'show multicast statistics', \&showMulticastStatistics, "Multicast Statistics for $device->{'name'}");
+ }
+ elsif ($cmd eq "snmpStatistics") {
+ $result = junosResult($junos, 'show snmp statistics', \&showSnmpStatistics, "SNMP Statistics for $device->{'name'}");
+ }
+ elsif ($cmd eq "version") {
+ $result = junosResult($junos, 'show version', \&showVersion, "Version for $device->{'name'}");
+ }
+ return $result;
}
+
sub validCommand {
my $command = shift;
my $args = shift;
my $device = shift;
my $type = $device->{"type"};
- # Do not allow non alphanumeric-ish chars. This prevents circumventing
- # multiple / altered commands.
+ # Do not allow non alphanumeric-ish chars.
+ # This prevents circumventing multiple / altered commands.
if ($command =~ /[\x00-\x1f]/ || $command =~ /\x7f/ ||
$args =~ /[\x00-\x1f]/ || $args =~ /\x7f/) {
return 0;
@@ -888,29 +707,24 @@ sub validCommand {
if ($args =~ m/regexp/i) {
return 0;
}
- # Do not allow piping to other commands besides display and match.
+ # Do not allow piping to other commands besides display and match.
if ($args =~ m/\|/ && ($args =~ m/.*\|.*\|.*/ || !($args =~ m/display/ or $args =~ m/match/)) ) {
return 0;
}
- if ($args ne "") {
- $command = $command . " " . $args;
- }
+ # Append command arguments to the command if any
+ $command = $command . " " . $args if ($args ne "");
my $validCommands = $conf->DeviceCommands($device->{"address"});
my $excludeCommands = $conf->DeviceExcludeCommands($device->{"address"});
- # First check to see if this command matches one of the deliberately
- # exluded ones.
+ # Check if the command matches any exluded ones
foreach my $excludeCommand (@{$excludeCommands}) {
- if ($command =~ /$excludeCommand/) {
- return 0;
- }
+ return 0 if ($command =~ /$excludeCommand/);
}
foreach my $validCommand (@{$validCommands}) {
- # For layer2/3, accept anything which has the prefix of a valid
- # command.
+ # For layer2/3, accept anything with the prefix of a valid command
if ($type eq "ciena" || $type eq "hdxc" || $type eq "ons15454" || $type eq "ome") {
return 1 if ($command eq $validCommand);
} else {
@@ -918,10 +732,10 @@ sub validCommand {
return 1 if ($command =~ m/$validCommand/);
}
}
-
return 0;
}
+
sub _parseLocationData {
my %args = @_;
my $city = $args{'city'};
@@ -930,8 +744,9 @@ sub _parseLocationData {
my @loc_array = ($city, $state);
my $location_data = "";
- for( my $i = 0; $i <= $#loc_array; $i++) {
+ for (my $i = 0; $i <= $#loc_array; $i++) {
my $loc_element = $loc_array[$i];
+
# add opeing paren if first element is defined
if($i == 0 && (ref $loc_array[$i] ne ref {} ) ) {
$location_data .= "(";
@@ -949,7 +764,5 @@ sub _parseLocationData {
}
}
}
-
return $location_data;
-
}