📄 lg.cgi
字号:
#!/usr/bin/perl## The original original lookingglass s/w was written by Ed Kern. it## is a single script and used to be available at http://nitrous.digex.net/### Copyright (C) 1997-2001 by Henry Kilmer.## All rights reserved.#### This software may be freely copied, modified and redistributed without## fee for non-commerical purposes provided that this copyright notice is## preserved intact on all copies and modified copies.#### There is no warranty or other guarantee of fitness of this software.## It is provided solely "as is". The author(s) disclaim(s) all## responsibility and liability with respect to this software's usage## or its effect upon hardware, computer systems, other software, or## anything else.## Looking glass# vars: query, router, argsBEGIN {$me = $0;$me =~ s/.*\/(\S+)$/$1/;}use CGI qw/:standard/;use POSIX qw(strftime);use Sys::Syslog;use LockFile::Simple qw(lock trylock unlock);my($BASEDIR) = "/nmis/rancid/";my($pingcmd) = "/bin/ping -c 1";my($query, $max_time_diff, $cache_dir, $cloginrc, @results);my($type, $router_param, $remote_user, $arg, $router, $mfg);my($LG_CACHE_DIR, $LG_CLOGINRC, $LG_IMAGE, $LG_LOG, $LG_ROUTERDB, $LG_AS_REG);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.# loggingsub 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 filesub readconf{ my($conffile, $cmds); local(*CONF); if (defined($env{LG_CONF})) { $conffile = $env{LG_CONF}; } elsif (-e "lg.conf") { $conffile = "lg.conf"; } else { $conffile = "$BASEDIR/util/lg/lg.conf"; } if (! -f $conffile) { return; } if (open(CONF, "< $conffile")) { while (<CONF>) { next if (/^\s*(#|$)/); $cmds .= $_; } close(CONF); eval $cmds; } else { printf(STDERR "ERROR: couldn\'t open the configuration file: $conffile: $!\n"); exit(1); } return;}# read router.db filesub readrouters{ my($rtrdb); local(*RTR); if (defined($LG_ROUTERDB)) { $rtrdb = $LG_ROUTERDB; } else { $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 { 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"); next if ( $dir =~ /$LG_SKIPGROUP/i ); # skip this rancid group 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); } } return;}# the functions remaining are particular to lg.cgi.# return true if $router is a member of @rtrlistsub 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); if ($pingcmd =~ /\d$/) { `$pingcmd $router`; } else { `$pingcmd $router 56 1`; } if ($?) { push(@results, "$router is unreachable. Try again later.\n"); print @results; return(-1); } if (! $lckobj->lock("$cache_dir/$router")) { push(@results, "$router is busy. Try again later.\n"); print @results; return(-1); } $val = &DoCmd($router, $mfg, $cmd, $arg); $lckobj->unlock("$cache_dir/$router"); return ($val);}# run commands on the router. return non-zero on error.sub DoCmd{ my($rtr, $mfg, $cmd, $arg) = @_; local(*CMD); if ($mfg =~ /foundry/i) { $cmd = $foundryCmd{$type}; open(CMD, "sh -c \"flogin -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |"); } elsif ($mfg =~ /juniper/i) { $cmd = $juniperCmd{$type}; open(CMD, "sh -c \"jlogin -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |"); } else { $cmd = $ciscoCmd{$type}; open(CMD, "sh -c \"clogin -noenable -f $cloginrc -c \'$cmd $arg\' $rtr\" 2>&1 |"); } while (<CMD>) { tr/\015//d; if (/^error:/i) { dolog(LOG_ERR, $_); if ($LG_STRIP) { undef(@results); } push(@results, $_); print @results; return(-1); } push(@results, $_); if (/$cmd/) { ($prompt) = /^(\S*)[\#>]/; 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(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 lengthsub mask2len { my($mask) = shift; my($a, $b, $c, $d) = split('\.', $mask); my($p, $len); $p = ~ (($a << 24) + ($b << 16) + ($c << 8) + $d); for ($len = 32; $p > 0; $len --) { $p = $p >> 1; } return($len);}# 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", gmtime); dolog(LOG_INFO, sprintf("%s %s %s %s\n", $ENV{REMOTE_HOST}, $ENV{REMOTE_ADDR}, $ENV{REMOTE_USER}, "- - [$timestr] $type $router $arg")); print $query->header; print $query->start_html("Looking Glass Results - $router"); $timestr = strftime("%a %b %e %H:%M:%S %Y %Z", gmtime); # add the company image, LG_IMAGE print $LG_IMAGE; if ($mfg =~ /foundry/i) { $cmd = $foundryCmd{$type}; } elsif ($mfg =~ /juniper/i) { $cmd = $juniperCmd{$type}; } else { $cmd = $ciscoCmd{$type}; } print <<HEAD ; </b></font> <font size=+3><b><h1>Looking Glass Results - $router </b></h1></font> <hr> <center> <b>Date:</b> $timestr <p> <b>Query:</b> $cmd <br>HEAD if ($arg) { print "<b>Argument(s):</b> $arg\n"; } print "</center>\n"; print <<END ; <!--$cached--> </center> <p> <pre>END 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## 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 nobodyif (defined($LG_CACHE_DIR)) { $cache_dir = $LG_CACHE_DIR;} else { $cache_dir = "./tmp";}# read routers table to get @rtrlistreadrouters();# when to display cache? max time difference (in seconds)if (defined($LG_CACHE_TIME)) { $max_time_diff = $LG_CACHE_TIME;} else { $max_time_diff = "600" ;}# max seconds to wait for a 'router' lock to free up$max_lock_wait = 30;$lock_int = 5;$max_lock_hold = 300;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -