summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorTar Committer <tar@ocjtech.us>2002-08-09 21:59:06 +0000
committerTar Committer <tar@ocjtech.us>2002-08-09 21:59:06 +0000
commitff168ecfe045c690c24d5bbc5a3062bf9d64120c (patch)
treea480f841453c9e22b6fd9ad4a54d1c9d5dbfabf6 /util
parentafcac75e572bcdd3cf269b921b7e8324aa5ffd4c (diff)
downloadrancid-ff168ecfe045c690c24d5bbc5a3062bf9d64120c.tar.gz
rancid-ff168ecfe045c690c24d5bbc5a3062bf9d64120c.tar.xz
rancid-ff168ecfe045c690c24d5bbc5a3062bf9d64120c.zip
Imported from rancid-2.2.2.tar.gz.rancid-2.2.2
Diffstat (limited to 'util')
-rw-r--r--util/README5
-rwxr-xr-xutil/getipacctg.in103
-rw-r--r--util/lg/README14
-rwxr-xr-xutil/lg/lg.cgi.in364
-rwxr-xr-xutil/lg/lgform.cgi.in53
5 files changed, 416 insertions, 123 deletions
diff --git a/util/README b/util/README
index 1a579d6..56d5673 100644
--- a/util/README
+++ b/util/README
@@ -1,8 +1,9 @@
rancid/util includes some utilities that either don't seem to belong
in rancid/bin (ie: not part of the core pkg), contributed sources, or
-sources included for convenience.
+sources included for convenience/example.
README This file.
+downreport Daily report of routers not listed as up in router.db
+getipacctg get and sort show ip accounting o/p from cisco router
lg looking glass pkg
rtrfilter mail filter for diffs
-downreport Daily report of routers not listed as up in router.db
diff --git a/util/getipacctg.in b/util/getipacctg.in
new file mode 100755
index 0000000..d77c919
--- /dev/null
+++ b/util/getipacctg.in
@@ -0,0 +1,103 @@
+#! /bin/sh
+#
+# getipacctg uses clogin to login to a cisco router, collect the o/p of
+# show ip accounting, and sort by the greatest number of bytes. if a
+# second argument is supplied, it is a number indicating the top N producers.
+# a third (3 to N) argument(s) specify a prefix(es) to match/select src/dst
+# IPs, while others will be filtered.
+#
+# usage: getipacctg <router name> [<number of lines off the top>] \
+# [<src/dest prefix filter> [...]]
+# example:
+# getipacctg router 25 192.168.0.0/24
+# will display the top 25 for src or dst ip's within prefix
+# 192.168.0.0/24
+#
+# contributed by steve neighorn.
+
+TMP="/tmp/ipacct.$$.prefixes"
+TMP2="/tmp/ipacct.$$.sorted"
+TMP3="/tmp/ipacct.$$.pl"
+
+if [ $# -eq 0 ] ; then
+ echo "usage: getipacctg router_name [<number of lines off the top>] [<src/dest prefix filter> [...]]" >&2
+ exit 1;
+fi
+
+trap 'rm -fr /tmp/ipacct.$$ $TMP $TMP2 $TMP3;' 1 2 15
+clogin -c 'show ip accounting' $1 > /tmp/ipacct.$$
+
+if [ $? -ne 0 ] ; then
+ echo "clogin failed." >&2
+ exit 1
+fi
+# rest of the command-line options
+exec 6>$TMP
+HEAD="cat"
+shift
+while [ $# -ne 0 ] ; do
+ echo $1 | grep '/' > /dev/null
+ if [ $? -eq 1 ] ; then
+ HEAD="head -$1"
+ else
+ echo $1 1>&6
+ fi
+ shift
+done
+6>&-
+
+egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ +[0-9]+\.[0-9]+\.' /tmp/ipacct.$$ | \
+ sed -e 's/^ *//' -e 's/ */ /g' -e 's/.$//' | \
+ awk '{print $4":"$0;}' | sort -nr | \
+ sed -e 's/^[^:]*://' > $TMP2
+
+if [ -s $TMP ] ; then
+cat > $TMP3 <<PERL
+ my(@prefs);
+ my(\$nprefs) = 0;
+ sub ip_to_int {
+ # Given xxx.xxx.xxx.xxx return corresponding integer.
+ my(\$int);
+ my(\$ip) = shift;
+ \$ip=~s/\s*//g;
+ \$ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\$/;
+ my (\$a,\$b,\$c,\$d) = (int(\$1),int(\$2),int(\$3),int(\$4));
+ return 0 + ((\$a << 24) + (\$b << 16) + (\$c << 8) + \$d) ;
+ }
+ open(PREFS, "< \$ARGV[0]") || die "could not open \$ARGV[0]\n";
+ while (<PREFS>) {
+ chomp;
+ s/\s*//g;
+ /(.*)\/(.*)\$/;
+ my(\$ip) = \$1; my(\$mask) = \$2;
+ \$ip = ip_to_int(\$ip);
+ \$mask = (~0) << (32 - \$mask);
+ \$ip = \$ip & (\$mask);
+ \$prefs[\$nprefs++] = \$ip;
+ \$prefs[\$nprefs++] = \$mask;
+ }
+ close(PREFS);
+ open(DATA, "< \$ARGV[1]") || die "could not open \$ARGV[1]\n";
+ while (<DATA>) {
+ chomp;
+ @A = split(/ /);
+ \$A[0] = ip_to_int(\$A[0]);
+ \$A[1] = ip_to_int(\$A[1]);
+ for (\$f = 0; \$f < \$nprefs; \$f += 2) {
+ if ((\$A[0] & \$prefs[\$f + 1]) == \$prefs[\$f] ||
+ (\$A[1] & \$prefs[\$f + 1]) == \$prefs[\$f]) {
+ print "\$_\n";
+ break;
+ }
+ }
+ }
+PERL
+ perl $TMP3 $TMP $TMP2 | $HEAD
+else
+ $HEAD $TMP2
+fi
+
+rm -fr /tmp/ipacct.$$ $TMP $TMP2 $TMP3
+trap ';' 1 2 15
+exit 0
+
diff --git a/util/lg/README b/util/lg/README
index 4546487..faa4120 100644
--- a/util/lg/README
+++ b/util/lg/README
@@ -1,4 +1,4 @@
-This is a looking glass based on Ed Kern's which can be found on
+This is a looking glass based on Ed Kern's which used to be available on
http://nitrous.digex.net/. This version supports cisco, juniper, and
foundry, using rancid's [cfj]login to login (so rcmd is not necessary,
it can use telnet, ssh, or rsh), and has some additional commands
@@ -18,7 +18,7 @@ the looking glass requires the CGI and LockFile-Simple perl modules.
these can be retrieved from CPAN, http://www.cpan.org/. CGI's home is
ftp://ftp-genome.wi.mit.edu/pub/software/WWW/. it also requires
the POSIX module (for strftime) and Sys::Syslog, which i believe come
-with perl5.
+with perl5 and/or are converted with h2ph(1).
basic installation instructions:
@@ -54,11 +54,13 @@ and install bits in /usr/local/rancid/util/lg (or <prefix>/util/lg).
DirectoryIndex lgform.cgi
2) the LG needs to be able to find and read lg.conf. by default this
- is installed as <PREFIX>/util/lg/lg.conf and the LG will look there.
- however, LG_CONF environment variable can be used to move it elsewhere.
+ is installed as <PREFIX>/util/lg/lg.conf and the LG will first look in
+ its CWD (current working directory) and then <PREFIX>/util/lg/lg.conf if
+ it does not exist in the CWD. However the LG_CONF environment variable can
+ be used to move it elsewhere.
- to get LG_CONF into the enviroment, you can SetEnvIf in apache's
- httpd.conf like this for example:
+ to get LG_CONF into the enviroment, you can use SetEnvIf in apache's
+ httpd.conf. for example:
SetEnvIf Request_URI "\/lg/.*.cgi" LG_CONF=/usr/local/util/lg/lg.conf
3) edit <PREFIX>/util/lg/lg.conf.
diff --git a/util/lg/lg.cgi.in b/util/lg/lg.cgi.in
index fe07c58..2921f72 100755
--- a/util/lg/lg.cgi.in
+++ b/util/lg/lg.cgi.in
@@ -1,6 +1,6 @@
#!@PERLV_PATH@
## The original original lookingglass s/w was written by Ed Kern. it
-## is a single script and can be found at http://nitrous.digex.net/
+## is a single script and used to be available at http://nitrous.digex.net/
#
## Copyright (C) 1997-2001 by Henry Kilmer.
## All rights reserved.
@@ -39,6 +39,41 @@ my($LG_BGP_RT, $LG_CACHE_TIME, $LG_SINGLE, $LG_STRIP);
if (!defined($ENV{HOME})) { $ENV{HOME} = "."; }
+# note: the following functions are duplicated between lgform.cgi and lg.cgi
+# to avoid the need for module inclusion headaches from within a httpd context.
+# it is just easier to be self-contained.
+# SO, ANY CHANGES HERE SHOULD BE REFLECTED IN THE OTHER .cgi.
+
+# logging
+sub dolog
+{
+ my($level, $msg) = @_;
+
+ if (defined($LG_LOG) && $LG_LOG !~ /\//) {
+ openlog($me, "pid", $LG_LOG);
+ syslog($level, "%s", $msg);
+ closelog;
+ } else {
+ local(*LOG);
+ my($file);
+ if (defined($LG_LOG)) {
+ $file = $LG_LOG;
+ } else {
+ $file = "$cache_dir/lg.log";
+ }
+ # log date, hostname, query, addr
+ if (open(LOG, ">>$file") == 0) {
+ # stderr, if all else fails
+ printf(STDERR "[" . strftime("%a %b %e %H:%M:%S %Y", gmtime) .
+ "] could not open log file $file: $!\n");
+ printf(STDERR $msg);
+ } else {
+ printf(LOG $msg);
+ close(LOG);
+ }
+ }
+ return;
+}
# read LG configuration file
sub readconf
{
@@ -65,40 +100,101 @@ sub readconf
eval $cmds;
} else {
printf(STDERR "ERROR: couldn\'t open the configuration file: $conffile: $!\n");
- exit(255);
+ exit(1);
}
return;
}
-# logging
-sub dolog
+# read router.db file
+sub readrouters
{
- my($level, $msg) = @_;
+ my($rtrdb);
+ local(*RTR);
- if (defined($LG_LOG) && $LG_LOG !~ /\//) {
- openlog($me, "pid", $LG_LOG);
- syslog($level, "%s", $msg);
- closelog;
+ if (defined($LG_ROUTERDB)) {
+ $rtrdb = $LG_ROUTERDB;
} else {
- local(*LOG);
- my($file);
- if (defined($LG_LOG)) {
- $file = $LG_LOG;
+ $rtrdb = "$BASEDIR/util/lg/router.db";
+ }
+
+ if (! -f $rtrdb) {
+ my(@dirs, $dir);
+ # if the router.db file does not exist, try to compile the list from
+ # the rancid group router.db files.
+ local(*DIR);
+ if (! opendir(DIR, $BASEDIR)) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR: $!\n");
} else {
- $file = "$cache_dir/lg.log";
+ while ($dir = readdir(DIR)) {
+ next if ($dir =~ /^(\.|\.\.|CVS|bin|logs|util)$/);
+ push(@dirs, $dir) if (-d "$BASEDIR/$dir");
+ }
+ closedir(DIR);
+
+ foreach $dir (@dirs) {
+ if (! opendir(DIR, "$BASEDIR/$dir")) {
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR/$dir: $!\n");
+ next;
+ }
+ closedir(DIR);
+ next if (! -f "$BASEDIR/$dir/router.db");
+ if (open(RTR, "< $BASEDIR/$dir/router.db")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: $BASEDIR/$dir/router.db: $!\n");
+ }
+ }
+ }
+ } else {
+ if (open(RTR, "< $rtrdb")) {
+ while (<RTR>) {
+ next if (/^\s*(#|$)/);
+ # fqdn:mfg:state
+ @record = split('\:', $_);
+ next if ($record[2] !~ /up/i || $record[1] !~ /(cisco|foundry|juniper)/);
+ push(@rtrlist, join(':', ($record[0], $record[1])));
+ $rtrlabels{join(':', ($record[0], $record[1]))} = $record[0];
+ }
+ close(RTR);
+ } else {
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: $rtrdb: $!\n");
+ exit(1);
}
- # log date, hostname, query, addr
- open(LOG,">>$file") ;
- printf(LOG "$msg");
- close(LOG);
}
+
return;
}
-# run commands on the router
+
+# the functions remaining are particular to lg.cgi.
+
+# return true if $router is a member of @rtrlist
+sub arraymember {
+ my($rtrlist) = shift;
+ my($router) = shift;
+ my($r);
+
+ foreach $r (@$rtrlist) {
+ $r = (split(':', $r))[0];
+ return(1) if ($r eq $router);
+ }
+
+ return(0);
+}
+# check reachability and lock file before attempting to connect to device
+# return non-zero on error.
sub DoRsh
{
my ($router, $mfg, $cmd, $arg) = @_;
my($ctime) = time();
+ my($val);
my($lckobj) = LockFile::Simple->make(-delay => $lock_int,
-max => $max_lock_wait, -hold => $max_lock_hold);
@@ -109,15 +205,20 @@ sub DoRsh
`$pingcmd $router 56 1`;
}
if ($?) {
- return ("$router is unreachable. Try again later.\n");
+ push(@results, "$router is unreachable. Try again later.\n");
+ print @results;
+ return(-1);
}
if (! $lckobj->lock("$cache_dir/$router")) {
- return ("$router is busy. Try again later.\n");
+ push(@results, "$router is busy. Try again later.\n");
+ print @results;
+ return(-1);
}
- @results = &DoCmd($router, $mfg, $cmd, $arg);
+ $val = &DoCmd($router, $mfg, $cmd, $arg);
$lckobj->unlock("$cache_dir/$router");
- return (@results);
+ return ($val);
}
+# run commands on the router. return non-zero on error.
sub DoCmd
{
my($rtr, $mfg, $cmd, $arg) = @_;
@@ -139,24 +240,60 @@ sub DoCmd
dolog(LOG_ERR, $_);
if ($LG_STRIP) { undef(@results); }
push(@results, $_);
- return (@results);
+ print @results;
+ return(-1);
}
push(@results, $_);
if (/$cmd/) {
($prompt) = /^(\S*)[\#>]/;
-# push(@results, "prompt = $prompt\n\n");
- if ($LG_STRIP) { undef(@results); }
+ if ($LG_STRIP) {
+ undef(@results);
+ } else {
+ print @results;
+ }
last;
}
}
+
while (<CMD>) {
last if /^$prompt[\#>]/;
tr/\015//d;
+ print $_;
push(@results, $_);
}
while (<CMD>) {}
close(CMD);
- return @results;
+
+ return(0);
+}
+# Subroutine: Error
+# Usage: &Error("msg"));
+# Description: displays an error and exits.
+##
+sub Error {
+ my($msg) = @_;
+
+ my($q) = new CGI();
+ print $q->header;
+ print $q->start_html("Looking Glass Error");
+
+ print "<BODY>";
+
+ # add the company image, LG_IMAGE
+ print $LG_IMAGE;
+
+
+ print <<EOF ;
+<br>
+<B><FONT SIZE=+2>Looking Glass Error:</FONT></B>
+<p>
+$msg
+<br>
+</body>
+EOF
+
+ print $q->end_html;
+ exit(0);
}
# convert a ipv4 address mask to prefix length
sub mask2len {
@@ -171,12 +308,24 @@ sub mask2len {
return($len);
}
-# create the page and log the transaction...
-sub print_results {
+# end the page and exit.
+sub end_page {
+
+ print <<END ;
+ </pre>
+ <!--- end page content --->
+ </body>
+END
+
+ print $query->end_html;
+ exit(0);
+}
+# start the page and log the transaction...
+sub start_page {
my($mfg) = @_;
my($cmd);
- my($timestr) = strftime("%a %b %e %H:%M:%S %Y %Z", gmtime);
+ my($timestr) = strftime("%a %b %e %H:%M:%S %Y", gmtime);
dolog(LOG_INFO, sprintf("%s %s %s %s\n",
$ENV{REMOTE_HOST}, $ENV{REMOTE_ADDR}, $ENV{REMOTE_USER},
"- - [$timestr] $type $router $arg"));
@@ -212,43 +361,35 @@ HEAD
if ($arg) { print "<b>Argument(s):</b> $arg\n"; }
print "</center>\n";
- print <<END ;
+ print <<END ;
<!--$cached-->
</center>
<p>
<pre>
END
- if ($seconds) { print "<b>From cache (number of seconds old (max $max_time_diff)):</b> $seconds\n\n" ; }
-
- print @results;
-
- print <<END ;
- </pre>
- <!--- end page content --->
- </body>
-END
-
- print $query->end_html;
- exit;
-
-} #end sub print_results
+ return;
+} #end sub start_page
+# Main()
# read the configuration file if it exists.
readconf();
## The script will now cache the results as simple files in the $cache_dir,
-## named after the type of query (queries must, of course, be one word no
+## named after the type of query (queries must, of course, be one word no
## spaces). Modify $max_time_diff to set the lifetime for each cache.
## Currently, cache lifetime is the same for all queries.
-# for most web servers, cache_dir must be writable by uid nobody
+# for most web servers, cache_dir must be writable by uid nobody
if (defined($LG_CACHE_DIR)) {
$cache_dir = $LG_CACHE_DIR;
} else {
$cache_dir = "./tmp";
}
+# read routers table to get @rtrlist
+readrouters();
+
# when to display cache? max time difference (in seconds)
if (defined($LG_CACHE_TIME)) {
$max_time_diff = $LG_CACHE_TIME;
@@ -279,15 +420,23 @@ $arg = ($query->param('args'))[0];
$arg =~ s/["'`]//g; # these are BS in any arg for any query
@arg = split(' ', $arg);
-# verify commands, arguments, etc.
+# verify router, commands, arguments, etc.
($router, $mfg) = split(':', $router_param);
if (!defined($type) || !defined($router)) {
$results[0] = "You must at least choose a Query and a router. Try buying a clue.\n";
- &print_results($mfg);
+ &Error("You must at least choose a Query and a router. Try buying a clue.\n");
+}
+
+if (! arraymember(\@rtrlist, $router)) {
+ my($timestr) = strftime("%a %b %e %H:%M:%S %Y", gmtime);
+ dolog(LOG_WARNING, sprintf("%s %s %s %s\n",
+ $ENV{REMOTE_HOST}, $ENV{REMOTE_ADDR}, $ENV{REMOTE_USER},
+ "- - [$timestr] lg.cgi: attempt to access $router\n"));
+ Error("access to $router not permitted");
}
# conversion of command "type" passed from lgform.cgi to the vendor's syntax.
-%ciscoCmd = (
+%ciscoCmd = (
#acl => "show access-list",
#aspath => "show ip as-path-access-list",
#communitylist => "show ip community-list",
@@ -309,7 +458,7 @@ if (!defined($type) || !defined($router)) {
summary => "show ip bgp summary",
trace => "traceroute"
);
-%foundryCmd = (
+%foundryCmd = (
#acl => "show access-list",
#aspath => "show ip as-path-access-list",
#communitylist => "show ip community-list",
@@ -330,7 +479,7 @@ if (!defined($type) || !defined($router)) {
summary => "show ip bgp summary",
trace => "traceroute"
);
-%juniperCmd = (
+%juniperCmd = (
#acl => "show access-list",
#aspath => "show ip as-path-access-list",
#communitylist => "show ip community-list",
@@ -351,7 +500,7 @@ if (!defined($type) || !defined($router)) {
summary => "show bgp summary",
trace => "traceroute"
);
-%cmdDisp = (
+%cmdDisp = (
#acl => "show access-list",
#aspath => "show ip as-path-access-list",
#communitylist => "show ip community-list",
@@ -376,37 +525,34 @@ if (!defined($type) || !defined($router)) {
# not all cmds/queries are implemented for junipers
if ($mfg =~ /juniper/) {
if (! defined($juniperCmd{$type})) {
- $results[0] = "$cmdDisp{$type} not implemented for junipers. sorry.\n";
- &print_results($mfg);
+ Error("$cmdDisp{$type} not implemented for junipers. sorry.\n");
}
$cmd = $juniperCmd{$type};
} elsif ($mfg =~ /foundry/) {
if(! defined($foundryCmd{$type})) {
- $results[0] = "$cmdDisp{$type} not implemented for foundrys. sorry.\n";
- &print_results($mfg);
+ Error("$cmdDisp{$type} not implemented for foundrys. sorry.\n");
}
$cmd = $foundryCmd{$type};
} else {
+ if(! defined($ciscoCmd{$type})) {
+ Error("$cmdDisp{$type} not implemented for cisco. sorry.\n");
+ }
$cmd = $ciscoCmd{$type};
}
-
if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
- $results[0] = "The IP address \"$arg[0]\" is not valid and lacking an address would over-burden our router.\n";
- &print_results($mfg);
+ &Error("The IP address \"$arg[0]\" is not valid and lacking an address would over-burden our router.\n");
} elsif (defined($arg[1]) && $arg[1] !~ /^\d+\.\d+\.\d+\.\d+$/) {
- $results[0] = "The IP netmask \"$arg[1]\" is not valid.\n";
- &print_results($mfg);
+ &Error("The IP netmask \"$arg[1]\" is not valid.\n");
}
if ($mfg =~ /juniper/i && defined($arg[1])) {
$arg = $arg[0] . "/" . mask2len($arg[1]);
}
} elsif ($type eq "framerelay") {
if ($mfg =~ /juniper/) {
- $results[0] = "Juniper does not have a show frame-relay pvc command. ".
- "Use show interface.\n";
- &print_results($mfg);
+ &Error("Juniper does not have a show frame-relay pvc command. " .
+ "Use show interface.\n");
}
if ($arg[0] > 15 && $arg[0] < 1024) {
$arg = $arg[0];
@@ -459,30 +605,27 @@ if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
} elsif ($type eq "ping" || $type eq "trace") {
if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
if ($arg[0] !~ /^[A-Za-z0-9._-]+$/) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
}
$arg = $arg[0];
} elsif ($type eq "aspath" || $type eq "communitylist") {
if ($arg[0] !~ /^\d+$/ || ($arg[0] < 1 && $arg[0] > 199)) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
$arg = $arg[0];
} elsif ($type eq "acl") {
if ($arg[0] !~ /^\d+$/ || ($arg[0] < 100 && $arg[0] > 199) ||
($arg[0] < 1300 && $arg[0] > 2699)) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
$arg = $arg[0];
# don't show the jewels
- &print_results($mfg) if ($arg == 98 || $arg == 99);
+ # XXX: this error msg is useless, but show acl is un-implemented.
+ &Error($mfg) if ($arg == 98 || $arg == 99);
} elsif ($type eq "prefixlist" || $type eq "routemap") {
if ($arg[0] !~ /^[0-9A-Za-z][^\s\"]*$/) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
$arg = $arg[0];
} elsif ($type eq "regex") {
@@ -493,14 +636,13 @@ if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
# remove leading/trailing whitespace
$arg =~ s/^\s*//; $arg =~ s/\s*$//;
if ($arg !~ /^[0-9_ ^.*+?[\])\(-]*\$?$/ || $arg =~ /^\s*$/) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
# pathetic excuses for lookups
if ($arg =~ /^[_.* ^]*(\*|1|701|1239|1280|1740|3561|5462|10303)+[_\$]*$/ ||
$arg =~ /^[_.* ^]*(1|701|1239|1280|1740|3561|5462|10303)+[_ .]*[\[*.]/) {
- $results[0] = "Get real. Such a query has potential to over-burden our router.\nLook that up on your own router.\n";
- &print_results($mfg);
+ &Error("Get real. Such a query has potential to over-burden our " .
+ "router.\nLook that up on your own router.\n");
}
if ($mfg =~ /juniper/) {
$arg =~ s/_/ /g;
@@ -517,8 +659,7 @@ if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
} elsif ($type eq "neighbor") {
if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
if ($arg[0] !~ /([A-Za-z0-9-]*.)*[A-Za-z0-9-]*.(com|edu|net|org)/) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
}
$arg = $arg[0];
@@ -554,8 +695,7 @@ if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
} elsif ($type eq "mneighbor") {
if ($arg[0] !~ /^\d+\.\d+\.\d+\.\d+$/) {
if ($arg[0] !~ /([A-Za-z0-9-]*.)*[A-Za-z0-9-]*.(com|edu|net|org)/) {
- $results[0] = "That argument ($arg[0]) is not valid.\n";
- &print_results($mfg);
+ &Error("That argument ($arg[0]) is not valid.\n");
}
}
$arg = $arg[0];
@@ -586,46 +726,58 @@ if ($type eq "prefix" || $type eq "mbgp" || $type eq "route" ) {
undef($arg);
}
+# make stdout unbuffered, so result page streams.
+$| = 1;
+start_page();
+
# cache the following
-if ($type eq "summary" || $type eq "mbgpsu" || $type eq "damp" || $type eq "log") {
+if ($type eq "summary" || $type eq "mbgpsu" || $type eq "damp"
+ || $type eq "log") {
if (!$arg) {
# cache requests with no addr/argument
local(*CACHE);
- my($file) = "$cache_dir/$type" ;
+ my($file) = "$cache_dir/$type" ;
$file =~ s/\s+/_/g;
$file .= "_$router";
if (-e $file) {
# see if cache exists
- @stat = stat($file);
- $ftime = $stat[9] ;
- $dtime = time - $stat[9] ;
+ @stat = stat($file);
+ $ftime = $stat[9];
+ $dtime = time() - $stat[9];
- # see if we are within cache time
+ # see if we are within cache time
if ($dtime <= $max_time_diff) {
- open(CACHE,"$file") ;
- while (<CACHE>) { push(@results, $_); }
- close CACHE ;
- $seconds = $dtime;
- &print_results($mfg);
+ if (open(CACHE, "<$file") == 0) {
+ dolog(LOG_ERR, "couldnt open cache file $file: $!\n");
+ } else {
+ print "<b>From cache (number of seconds old (max " .
+ "$max_time_diff)):</b> $dtime\n\n";
+ while (<CACHE>) { print $_; }
+ close(CACHE);
+ &end_page();
+ }
}
}
# else, execute command and save to a new cache file
- open(CACHE,">$file") || die "couldnt create cache file $file" ;
-
- @results = &DoRsh($router, $mfg, $cmd, $arg);
-
- print CACHE "@results";
- close CACHE ;
+ if (! &DoRsh($router, $mfg, $cmd, $arg)) {
+ if (open(CACHE, ">$file") == 0) {
+ dolog(LOG_ERR, "couldnt create cache file $file: $!\n");
+ exit(1);
+ } else {
+ printf(CACHE "@results");
+ close(CACHE);
+ }
+ }
} else {
- @results = &DoRsh($router, $mfg, $cmd, $arg);
+ &DoRsh($router, $mfg, $cmd, $arg);
}
- &print_results($mfg);
-} # end dampened-paths/flap-statistics
-
-@results = &DoRsh($router, $mfg, $cmd, $arg);
-&print_results($mfg);
+ &end_page();
+} else {
+ &DoRsh($router, $mfg, $cmd, $arg);
+ &end_page();
+}
-exit;
+exit(0);
diff --git a/util/lg/lgform.cgi.in b/util/lg/lgform.cgi.in
index 3ea6856..97a0c71 100755
--- a/util/lg/lgform.cgi.in
+++ b/util/lg/lgform.cgi.in
@@ -20,7 +20,41 @@ use CGI qw/:standard/;
my(@rtrlist, %rtrlabels);
my($BASEDIR) = "@prefix@";
+# note: the following functions are duplicated between lgform.cgi and lg.cgi
+# to avoid the need for module inclusion headaches from within a httpd context.
+# it is just easier to be self-contained.
+# SO, ANY CHANGES HERE SHOULD BE REFLECTED IN THE OTHER .cgi.
+# logging
+sub dolog
+{
+ my($level, $msg) = @_;
+
+ if (defined($LG_LOG) && $LG_LOG !~ /\//) {
+ openlog($me, "pid", $LG_LOG);
+ syslog($level, "%s", $msg);
+ closelog;
+ } else {
+ local(*LOG);
+ my($file);
+ if (defined($LG_LOG)) {
+ $file = $LG_LOG;
+ } else {
+ $file = "$cache_dir/lg.log";
+ }
+ # log date, hostname, query, addr
+ if (open(LOG, ">>$file") == 0) {
+ # stderr, if all else fails
+ printf(STDERR "[" . strftime("%a %b %e %H:%M:%S %Y", gmtime) .
+ "] could not open log file $file: $!\n");
+ printf(STDERR $msg);
+ } else {
+ printf(LOG $msg);
+ close(LOG);
+ }
+ }
+ return;
+}
# read LG configuration file
sub readconf
{
@@ -47,7 +81,7 @@ sub readconf
eval $cmds;
} else {
printf(STDERR "ERROR: couldn\'t open the configuration file: $conffile: $!\n");
- exit(255);
+ exit(1);
}
return;
@@ -66,11 +100,11 @@ sub readrouters
if (! -f $rtrdb) {
my(@dirs, $dir);
- # if the router.db file does not exist, try to compile from
- # the rancid group's router.db files.
+ # if the router.db file does not exist, try to compile the list from
+ # the rancid group router.db files.
local(*DIR);
if (! opendir(DIR, $BASEDIR)) {
- printf(STDERR "ERROR: couldn\'t read $BASEDIR: $!\n");
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR: $!\n");
} else {
while ($dir = readdir(DIR)) {
next if ($dir =~ /^(\.|\.\.|CVS|bin|logs|util)$/);
@@ -80,7 +114,7 @@ sub readrouters
foreach $dir (@dirs) {
if (! opendir(DIR, "$BASEDIR/$dir")) {
- printf(STDERR "ERROR: couldn\'t read $BASEDIR/$dir: $!\n");
+ dolog(LOG_ERR, "ERROR: couldn\'t read $BASEDIR/$dir: $!\n");
next;
}
closedir(DIR);
@@ -96,7 +130,7 @@ sub readrouters
}
close(RTR);
} else {
- printf(STDERR "ERROR: couldn\'t open the router.db file: $BASEDIR/$dir/router.db: $!\n");
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: $BASEDIR/$dir/router.db: $!\n");
}
}
}
@@ -112,14 +146,15 @@ sub readrouters
}
close(RTR);
} else {
- printf(STDERR "ERROR: couldn\'t open the router.db file: $rtrdb: $!\n");
- exit(255);
+ dolog(LOG_ERR, "ERROR: couldn\'t open the router.db file: $rtrdb: $!\n");
+ exit(1);
}
}
return;
}
+# Main()
# read the configuration file if it exists.
readconf();
@@ -207,4 +242,4 @@ TAIL
print $query->end_html;
-exit 0;
+exit(0);