#!/usr/local/bin/perl -w ######################################################### # # # CGI program to allow NCC engineers # # to access our routers for troubleshooting # # purposes. # # # # Mark Tripod Exodus Communications # # 9/23/97 # # # ######################################################### use strict; use Net::Telnet; use CGI; require 5.004; # With a few minor code modifications this could be # changed to 5.002 ################ # Begin MAIN # ################ # Global variables use vars qw(@return $site $router %Sites); ############ # DEFINE THESE VARIABLE FIRST ############ my $company = ''; # Company name for WWW header my $logo = '/icons/logo.gif'; # Path to company logo (if exists) my $timeout = '45'; # Time to wait for remote command to respond my $user = ''; # User ID to login to routers my $passwd = ''; # Router login password my $email = ''; # email account to send comments to # Sites passed over command line must be defined # in a file called "looking-glass.sites". # The file format is a two column tab seperated list containing # the site name in the first column and the router IP # address in the second column. Each line contains one site entry. # This is done not only for cleaner looking URIs, # but for security reasons also. open(SITES, 'looking-glass.sites') || die "Looking Glass Sites: $!\n"; while( defined( my $var = ) ) { my ($sitename, $siteip) = split(/\t/, $var); $Sites{$sitename} = $siteip; } close(SITES); my $q = new CGI; $q->use_named_parameters(1); #$q->nph(1); # I was playing with using non-parsed headers for the tracing # and ping utilities, but I haven't had time to work out all # of the buffering issues. print $q->header(); if ($q->request_method eq 'POST') { &ExecCmd(); &DisplayResult(); } elsif ($q->request_method eq 'GET') { # Site to look into comes from command line (or in this case # the text after the "?" in the HTML link) $site = shift; die &Usage() unless $site; $router = $Sites{$site}; &DisplayForm(); } else { &DisplayForm(); } print "
"; print "
Please email questions/comments to $email
"; print $q->end_html(); ############## # End MAIN # ############## sub DisplayForm { my $Site; if ($Sites{$site} eq '') { &NoSupport(); return; } if ($site eq 'Mae-West-mfs') { $Site = 'Mae-West (MFS)'; } elsif ($site eq 'Mae-West-ames') { $Site = 'Mae-West (AMES)'; } else { $Site = $site; } # Some JavaScript for a help button that is displayed. I use the help window to # display an explaination for each of the commands listed on the web page # as well as list pointers to Ciscos online documentation if more information # is needed. print <<"Script"; Script print $q->start_html('title'=>"$company : $Site Looking Glass", 'BGCOLOR'=>'FFFFFF', 'TEXT'=>'0F0F0F' ); print "\n"; print "

$Site Looking Glass

\n"; print $q->start_form(); print $q->hidden('name'=>'site', 'default'=>$site); print "Select a query type:

\n"; # Leading spaces are needed in the value list below to keep # the radio button names from being displayed right next # to the buttons themselves. I supposed I could strip them, # but I can't see any useful reason to do so. print $q->radio_group( 'name'=>'query_type', 'values'=>[' Access List', ' BGP', ' BGP Summary', ' Dampened AS Paths', ' Environmental', ' Route Flap Statistics', ' Ping from this site', ' Trace from this site'], 'default'=>' BGP', 'rows'=>'3', 'cols'=>'3', 'linebreak'=>'true' ); print "

Address: "; print $q->textfield( 'name'=>'address', 'size'=>'18'); print "

\n"; print ""; print "
", $q->submit('Submit'), "
\n"; print "
"; print "
\n"; print "
", $q->reset(), "
\n"; print "
"; print "
\n"; print $q->endform(); } sub ExecCmd { # Translate commands into usable router statements. my %Commands = ( ' Access List' => 'sh ip access-list', ' BGP' => 'sh ip bgp', ' BGP Summary' => 'sh ip bgp sum', ' Dampened AS Paths' => 'sh ip bgp damp', ' Environmental' => 'sh env all', ' Route Flap Statistics' => 'sh ip bgp flap', ' Ping from this site' => 'ping', ' Trace from this site' => 'trace' ); my $cmd = $Commands{$q->param('query_type')}; my $address = $q->param('address'); my $router = $Sites{$q->param('site')}; $site = $q->param('site'); my $connection = new Net::Telnet (Host => "$router", Timeout => 10, Prompt => '/[\w\-]+>$/'); $connection->login($user, $passwd); $connection->timeout($timeout); $connection->errmode('return'); $connection->max_buffer_length('3048576'); unless ($connection->cmd("terminal length 0")) { print "Can't set terminal length"; } if (($address ne "") && (($q->param('query_type') eq ' BGP') || ($cmd eq 'ping') || ($cmd eq 'trace'))) { @return = $connection->cmd("$cmd $address"); if ($connection->timed_out()) { @return = 'Command timed out'; } } elsif (($address eq "") && ($q->param('query_type') eq ' BGP')) { # I really don't want to kill my routers or the web server just # because an experienced NOC person didn't bother to read the # help page. @return = 'It is not recommended that the BGP table be queried without '. 'an address entry.
This would cause a dump of the entire '. 'BGP route table (over 40,000 routes).'; } else { @return = $connection->cmd("$cmd"); if ($address ne "") { $address =~ s/\./\\./g; my @lines = grep(/$address/, @return); @lines = 'No matches found.' unless @lines; unshift(@lines, "\n"); # I like things to look nice! my @head = splice(@return, 0, 4); @return = @head; while( defined( my $var = shift( @lines ) ) ) { push(@return, $var); } } if ($connection->timed_out()) { @return = 'Command timed out'; } } $connection->close; } sub DisplayResult { my $Site; if ($site eq 'Mae-West-mfs') { $Site = 'Mae-West (MFS)'; } elsif ($site eq 'Mae-West-ames') { $Site = 'Mae-West (AMES)'; } else { $Site = $site; } print $q->start_html( 'title'=>"$company : $Site Query Results", 'BGCOLOR'=>'FFFFFF', 'TEXT'=>'000000' ); print "\n"; print "

$Site Query Results

\n"; print "
\n";
  print "@return
\n"; print "
\n"; } sub Usage { print $q->start_html("Error"); print "Program cannot be run without a site designation
\n"; print $q->end_html; exit; } sub NoSupport { print $q->start_html('title'=>"$company : $site Looking Glass", 'BGCOLOR'=>'FFFFFF', 'TEXT'=>'0F0F0F' ); print "\n"; print "

$site is not yet supported.

"; }