#!/usr/bin/perl # DONT FORGET TO CHANGE THE ABOVE PATH TO MATCH YOUR PERL LOCATION! # vim:ts=4 ############################################################################## # To use Speedycgi, you need to change the first line to this: ##!/usr/bin/speedy -- -M20 -t3600 -gnone -r500 # and then set the CACHE global variable (below) to 1. # To use mod_perl, you should be able to put the script directly into the # mod_perl directory and it will work. This is not very thoroughly tested # though. You also need to set the CACHE global below to 1. ############################################################################## # routers.cgi : Version v2.16 # Create router monitoring pages # # This code is covered by the Gnu GPL. See the README file, or the Gnu # web site for more details. # Developed and tested with RRDTool v1.0.46, Perl 5.8, under Linux (RH9.0) # Also partially tested with ActivePerl 5.6 with Apache under NT # Note - 95th percentile calcs DO NOT WORK under RRDTool v1.0.24 or earlier # Windows users should avoid RRDTool v1.0.33 - v1.0.39 due to a bug. ############################################################################## # DONT FORGET TO CHANGE THE LOCATION OF THE CONFIG FILE DEFINED BELOW! ############################################################################## use strict; use CGI; # for CGI use File::Basename; # for identifying filenames under different OSs use Text::ParseWords; # for parsing MRTG .conf file use FileHandle; # to have multiple conf files in recursion use Getopt::Std; # For limited command line operation use POSIX qw(tzset); # For timezone support ##CONFIG#START################################################################ # You MUST set this to the location of the configuration file! my ($conffile) = "/home/mholtz/sites/etc/mrtg/routers2.conf"; ############################################################################## # Are we running in speedycgi or mod_perl mode? Can we cache configs? # If you set this to 1 when you dont have speedycgi or mod_perl, it will # slightly slow things down, but will not break anything. # This can also be set in the routers2.conf with the cache=yes option my ($CACHE) = 0; ############################################################################## # You should set this to something random and secret, if you are using # the script's internal authentication via cookies. It's called this because # it is embedded into a cookie... my ($CHOCOLATE_CHIP) = 'nvhjkg5890^.>fj8psu89psupy89pu=({UIu'; ##CONFIG#END################################################################## my ($VERSION) = 'v2.16beta7'; my ($APPURL ) = 'http://www.steveshipway.org/software/'; my ($FURL ) = 'http://www.steveshipway.org/forum/'; my ($MLURL ) = 'http://www.steveshipway.org/mailman/listinfo/support_steveshipway.org'; my ($WLURL ) = 'http://www.steveshipway.org/software/wishlist.html'; my ($APPMAIL) = 'mailto:steve@steveshipway.org'; ##GLOBAL#START################################################################ # Global variables : uses 'use vars' for speeycgi and mod_perl use vars qw($opt_A $opt_D $opt_T $opt_r $opt_i $opt_s $opt_t); use vars qw($meurl $meurlfull); use vars qw($mtype $gtype $defgopts $defgtype $defrouter $defif $cookie); ($mtype,$gtype,$defgopts, $defgtype, $defrouter, $defif, $cookie) = ('','','','','','',''); use vars qw(@cookies); @cookies=(); use vars qw($gopts $baropts $defbaropts $uopts); ($gopts, $baropts, $defbaropts, $uopts) = ('','','',''); use vars qw(%routers %routerscache); %routers = (); # loaded from cache use vars qw(%cachedays); %cachedays = (); use vars qw($readinrouters); $readinrouters = 0; use vars qw(%interfaces %ifstore); use vars qw(%lang $language); $language = ''; use vars qw(%gtypes @gorder); use vars qw(%gstyles @sorder %gstylenames); use vars qw($gstyle $defgstyle $archdate); ($gstyle, $defgstyle, $archdate) = ('','',''); use vars qw(%headeropts); %headeropts = (); use vars qw(@cfgfiles); @cfgfiles = (); use vars qw($lastupdate $workdir $interval); ($lastupdate, $workdir, $interval) = ('','',''); use vars qw($pagetype); $pagetype = ''; use vars qw($donecfg); $donecfg = 0; use vars qw(%config); use vars qw($bn); $bn = ''; use vars qw($graphsuffix); $graphsuffix = "gif"; use vars qw($NT); $NT = 0; # gets set to 1 if using NT use vars qw($pathsep); $pathsep = "/"; # gets set to "\\" if you have NT use vars qw($dailylabel); $dailylabel = "%k"; # set to "%H" if you have ActivePerl use vars qw($monthlylabel); $monthlylabel = "%V";# use "%W" for alternate week numbering method # gets set to %W if you have ActivePerl use vars qw($usesixhour); $usesixhour = 0; use vars qw($twinmenu); $twinmenu = 0; use vars qw($rrdoutput); $rrdoutput = ""; use vars qw($rrdxsize $rrdysize); ($rrdxsize, $rrdysize) = (0,0); use vars qw($router $interface); ($router, $interface) = ('',''); use vars qw($uselastupdate); $uselastupdate = 0; use vars qw($ksym $k $M $G); ($ksym,$k,$M,$G) = ("K",1024,1024000,1024000000); # mixed option use vars qw($grouping); $grouping = 0; # Do we group when sorting routers? use vars qw($group); $group = ""; use vars qw($csvmime); $csvmime = "text/comma-separated"; # MIME type for CSV downloads use vars qw($windowtitle); $windowtitle = "Systems Monitor"; # Widow title use vars qw($toptitle); $toptitle = ""; # Title at top of page use vars qw($timezone); $timezone = 0; use vars qw($bits $factor); ($bits, $factor) = ("!bits",8); use vars qw($defbgcolour); $defbgcolour = "#ffd0ff"; # default colours use vars qw($deffgcolour); $deffgcolour = "#000000"; use vars qw($menubgcolour); $menubgcolour = "#d0d0d0"; use vars qw($menufgcolour); $menufgcolour = "#000000"; use vars qw($linkcolour); $linkcolour = "#2020ff"; use vars qw($extra); $extra = ""; use vars qw($archiveme); $archiveme = 0; use vars qw($archive); $archive = ""; use vars qw($myname); $myname = 'routers2.cgi'; use vars qw($debugmessage); $debugmessage = ""; use vars qw($authuser); $authuser = ""; use vars qw($crypthack); $crypthack = 0; # compatibility for broken crypt use vars qw(@params); @params = (); use vars qw($traffic); $traffic = ""; use vars qw($seclevel); $seclevel = 0; use vars qw($comma); $comma = ','; # for CSV use vars qw(@pathinfo); @pathinfo = (); use vars qw($stime); $stime = time; use vars qw($linewidth); $linewidth = 1; use vars qw($charset); $charset = ''; ##GLOBAL#END############################################################ # You MAY configure the descriptions in the lines below if you require # or, remove some entries from the @sorder Styles list. ######################################################################## sub initlabels { %gtypes = ( d=>"Daily",w=>"Weekly", m=>"Monthly",y=>"Yearly", dwmy=>"All Graphs", dwmys=>"Compact", 6=>"6 hour", "m-"=>"Last Month", "w-"=>"Last week", "d-"=>"Yesterday", "y-"=>"Last Year", x1=>"X1", x2=>"X2", x3=>"X3", x4=>"X4", "dw"=>"Short term", "my"=>"Long term" ); @gorder = qw/d w m y dwmy dwmys/; # you might prefer to have the order reversed # NOTE: first word of these is the key used in routers.conf for default %gstyles = ( s=>"Short (PDA)", n=>"Normal (640x480)", t=>"Stretch", l=>"Long", n2=>"Tall", l2=>"Big (800x600)", x3=>"Huge (1024x768)", x=>"ExtraLong", sbp=>"Palm III/V", nbp=>"Psion 3/3x/5", np=>"WinCE-1", sp=>"WinCE-2", l2p=>"Web TV", x2=>"Huge (1024x768)" ); if(defined $config{'routers.cgi-sorder'} ) { @sorder = (); foreach ( split " ", $config{'routers.cgi-sorder'} ) { push @sorder, $_ if(defined $gstyles{$_}); } } else { # you might want to remove some of these @sorder = qw/s t n n2 l l2 x x3 sbp nbp np l2p/; } } ##CODE#START############################################################ # Nothing else to configure after this line ######################################################################## # initialize CGI use vars qw($q); $q = new CGI; # At this point, parameters are parsed $meurl = $q->url(-absolute=>1); # /cgi-bin/routers2.cgi $meurlfull = $q->url(-full=>1); # http://server/cgi-bin/routers2.cgi $router = $interface = ""; ################################# # For RRD v1.2 compatibility: remove colons for COMMENT directive if # we are in v1.2 or later, else leave them there sub decolon($) { my($s) = $_[0]; return $s if($RRDs::VERSION < 1.002 ); $s =~ s/:/\\:/g; return $s; } ################################# # For sorting sub rev { $b cmp $a; } sub numerically { return ($a cmp $b) if( $a !~ /\d/ or $b !~ /\d/ ); $a <=> $b; } sub bytraffic { return -1 if(!$a or !$b or !$traffic); # return -1 if(!defined $interfaces{$a}{$traffic} # or !defined $interfaces{$b}{$traffic}); $interfaces{$b}{$traffic} <=> $interfaces{$a}{$traffic}; } sub byiflongdesc { my ( $da, $db ) = ( "#$a","#$b" ); # is this an invalid interface? return 0 if(!defined $interfaces{$a} or !defined $interfaces{$b}); return 1 if(!$interfaces{$a}{inmenu}); return -1 if(!$interfaces{$b}{inmenu}); if( defined $config{'targetnames-ifsort'} ) { if( $config{'targetnames-ifsort'} eq 'icon' ) { return $interfaces{$a}{icon} cmp $interfaces{$b}{icon} if($interfaces{$a}{icon} ne $interfaces{$b}{icon}); } elsif( $config{'targetnames-ifsort'} eq 'mode' ) { return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); } } else { return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); } # we always sort by description in the end $da = $interfaces{$a}{shdesc} if( defined $interfaces{$a}{shdesc} ); $db = $interfaces{$b}{shdesc} if( defined $interfaces{$b}{shdesc} ); $da = $interfaces{$a}{desc} if( defined $interfaces{$a}{desc} ); $db = $interfaces{$b}{desc} if( defined $interfaces{$b}{desc} ); (lc $da) cmp (lc $db); } sub byifdesc { my ( $da, $db ) = ( "#$a","#$b" ); # is this an invalid interface? return 0 if(!defined $interfaces{$a} or !defined $interfaces{$b}); return 1 if(!$interfaces{$a}{inmenu}); return -1 if(!$interfaces{$b}{inmenu}); if( defined $config{'targetnames-ifsort'} ) { if( $config{'targetnames-ifsort'} eq 'icon' ) { return $interfaces{$a}{icon} cmp $interfaces{$b}{icon} if($interfaces{$a}{icon} ne $interfaces{$b}{icon}); } elsif( $config{'targetnames-ifsort'} eq 'mode' ) { return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); } } else { return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); } # we always sort by description in the end $da = $interfaces{$a}{shdesc} if( defined $interfaces{$a}{shdesc} ); $db = $interfaces{$b}{shdesc} if( defined $interfaces{$b}{shdesc} ); (lc $da) cmp (lc $db); } sub bydesc { my ( $da, $db ) = ($routers{$a}{desc}, $routers{$b}{desc}); $da = $a if ( ! $da ); $db = $b if ( ! $db ); (lc $da) cmp (lc $db); } # Sorting function for devices menu sub byshdesc { my ( $da, $db ) = ($routers{$a}{shdesc}, $routers{$b}{shdesc}); if( $grouping ) { my ( $ga ) = $routers{$a}{group}; my ( $gb ) = $routers{$b}{group}; $ga=$config{"targetnames-$ga"} if(defined $config{"targetnames-$ga"}); $gb=$config{"targetnames-$gb"} if(defined $config{"targetnames-$gb"}); # Sort by group name first my ( $c ) = $ga cmp $gb; if($c) { return $c; } } # Sort by description of device $da = $a if ( ! $da ); $db = $b if ( ! $db ); (lc $da) cmp (lc $db); } ###################### # For grouping multilevel. Work out which groups we need to display. # (activegroup, thisgroup, lastgroup) # returns [ [groupname,depth,active], ... ] sub getgroups($$$) { my(@rv) = (); my($ag,$tg,$lg) = @_; my(@ag,@tg,@lg); my($gs) = ':'; my($i) = 0; my($actv) = 1; $gs = $config{'routers.cgi-groupsep'} if(defined $config{'routers.cgi-groupsep'}); @ag = split /$gs/,$ag; @tg = split /$gs/,$tg; @lg = split /$gs/,$lg; while( $i <= $#tg ) { last if( $i > $#ag ); $actv = 0 if( $tg[$i] ne $ag[$i] ); if( $tg[$i] ne $lg[$i] ) { $tg[$i] =~ s/^\s*//; # trim leading spaces push @rv, [ $tg[$i], $i, $actv ]; } if( $tg[$i] ne $ag[$i] ) { last; } $i += 1; } # push @rv, [ $tg, 0, 0 ]; return @rv; } ###################### # Replacement for glob: find archives # return list of dates sub findarch($$) { my(@files) = (); my($path,$file) = @_; opendir DIR, $path or return @files; foreach ( readdir DIR ) { push @files, $_ if( -f $path.$pathsep.$_.$pathsep.$file ); } closedir DIR; return @files; } ###################### # calculate short date string from given time index sub shortdate($) { my( $dformat ) = "%c"; # windows perl doesnt have %R my( $datestr, $fmttime ) = ("",0); return "DATE ERROR 1" if(!$_[0]); $fmttime = $_[0]; $fmttime = time if(!$fmttime); my( $sec, $min, $hour, $mday, $mon, $year ) = localtime($fmttime); # try to get local formatting $dformat = $config{'web-shortdateformat'} if(defined $config{'web-shortdateformat'}); $dformat =~ s/ / /g; eval { require POSIX; }; if($@) { $datestr = $mday."/".($mon+1)."/".($year-100); } else { $datestr = POSIX::strftime($dformat, 0,$min,$hour,$mday,$mon,$year); } return "DATE ERROR 2" if(!$datestr); return $datestr; } ################################# # For string trims. Remove leading and trailing blanks sub trim($) { my($x)=$_[0]; $x=~s/\s*$//; $x=~s/^\s*//; $x; } ################################# # build up option string sub optionstring(%) { my(%o,$options); %o = %{$_[0]}; $o{page}="graph" if(!defined $o{page}); $o{xgtype}="$gtype" if($gtype and !defined $o{xgtype}); $o{xmtype}="$mtype" if($mtype and !defined $o{xmtype}); $o{xgstyle}="$gstyle" if($gstyle and !defined $o{xgstyle}); $o{xgopts}="$gopts" if($gopts and !defined $o{xgopts}); $o{bars}="$baropts" if($baropts and !defined $o{bars}); $o{rtr}="$router" if($router and !defined $o{rtr}); $o{if}="$interface" if($interface and !defined $o{if}); $o{extra}="$extra" if($extra and !defined $o{extra}); $o{uopts}="$uopts" if($uopts and !defined $o{uopts}); $o{arch}="$archdate" if($archdate and !defined $o{arch}); $options = ""; foreach ( keys %o ) { if( $o{$_} ) { $options .= "&" if ($options); $options .= "$_=".$q->escape($o{$_}); } } return $options; } ################################# # Generate the javascript for the page header sub make_javascript(%) { my($js); my(%opa,%opb); my($ua,$ub); return("function LoadMenu() { }") if($q->param('nomenu')); %opa = ( page=>"menu" ); foreach ( keys %{$_[0]} ) { $opa{$_}=$_[0]->{$_}; } if( $twinmenu ) { %opb = %opa; $opa{xmtype} = "routers"; $opb{page} = "menub"; $opb{xmtype} = "options"; $ua = "$meurlfull?".optionstring(\%opa)."#top"; $ub = "$meurlfull?".optionstring(\%opb)."#top"; # $js = " #function LoadMenu() #{ # if(parent.menu){ # parent.menub.location.href = \"$ub\"; # if( parent.menu.location.href != \"$ua\" ) { # parent.menu.location.href = \"$ua\"; # } # } #}"; $js = " function LoadMenu() { parent.setlocationb(\"$ub\"); parent.setlocationa(\"$ua\"); } "; } else { # not twinmenu mode $opa{xmtype}="routers" if($router eq "none" or (defined $opa{rtr} and $opa{rtr} eq "none")); $ua = "$meurlfull?".optionstring(\%opa)."#top"; # $js = " #function LoadMenu() #{ # if(parent.menu){ # if( parent.menu.location.href != \"$ua\" ) { # parent.menu.location.href = \"$ua\"; # } # } #}"; $js = " function LoadMenu() { parent.setlocationa(\"$ua\"); } "; } return $js; } ################################# # Create a bar graph, as requested by the CGI parameters. # This should be given two CGI parameters: IN and OUT. Use GD libraries if # available to make a simple bar with green bar and blue line. IN and OUT are # supposed to be percentages. sub do_bar() { my( $gd, $black, $white, $green, $blue, $grey ); my( $w, $h ) = (400,10); my($x); eval { require GD; }; if($@) { # GD libraries not available. So, redirect to error message graphic. print $q->redirect($config{'routers.cgi-iconurl'}."error.gif"); return; } if( defined $q->param('L') ) { $w = $q->param('L') if($q->param('L') >100); } # We have GD. So, make up a simple bar graphic and print it - after # giving the correct HTML headers of course. $gd = new GD::Image($w,$h); $black = $gd->colorAllocate(0,0,0); $white = $gd->colorAllocate(255,255,255); $green = $gd->colorAllocate(0,255,0); $blue = $gd->colorAllocate(0,0,255); $grey = $gd->colorAllocate(192,192,192); if( $q->param('IN') < 0 and $q->param('OUT') < 0) { # unknown data $gd->fill(1,1,$grey); # background } else { $gd->fill(1,1,$white); # background $x = $w * $q->param('IN') /100.0 ; $gd->rectangle(0,0,$x-1,($h/2)-1,$green) if($x>1); $gd->fill(1,1,$green) if($x > 2); $x = $w * $q->param('OUT') /100.0 ; #$gd->line($x,0,$x,$h-1,$blue) if($x>0); $gd->rectangle(0,$h/2,$x-1,$h-1,$blue) if($x>1); $gd->fill(1,$h-2,$blue) if($x > 2); } $gd->rectangle(0,0,$w-1,$h-1,$black); # box around it if( defined $config{'web-png'} and $config{'web-png'}=~/[1y]/i ) { print $q->header({ -type=>"image/png", -expires=>"+6min" }); binmode STDOUT; print $gd->png(); } else { print $q->header({ -type=>"image/gif", -expires=>"+6min" }); binmode STDOUT; print $gd->gif(); } } ################################# # Read in language file sub readlang($) { my($l) = $_[0]; my($f,$sec); return "Cached" if( defined $lang{$l} ); # already read it if(defined $config{'web-langdir'}) { $f = $config{'web-langdir'} ; } else { $f = dirname($conffile); } $f .= $pathsep."lang_$l.conf"; return "Language file not present" if(! -r $f); # no language file defined open LFH,"<$f" or return; $lang{$l} = { file=>$f }; $sec = ""; while( ) { /^\s*#/ && next; /\[(.*)\]/ && do { $sec = lc $1; }; chomp; /^\s*(\S+)\s*=\s*(\S.*?)\s*$/ and $lang{$l}{"$sec-$1"}=$2; } close LFH; return 0; } sub langmsg($$) { my($code,$default) = @_; return $default if(!$language); # no language defined return $default if(!defined $lang{$language}); # language not loaded return $lang{$language}{"messages-$code"} if($lang{$language}{"messages-$code"}); return $default; } sub langinfo { return "None" if(!$language); return "Language $language not loaded" if(!defined $lang{$language}); return $lang{$language}{"global-description"} ." Ver ".$lang{$language}{"global-version"}.", " .$lang{$language}{"global-author"}; } sub langhtml($$) { my($m); $m = langmsg($_[0],$_[1]); $m =~ s/ / /g; $m =~ s//>/g; return $m; } sub initlang { my($l) = $_[0]; my($rv); initlabels(); if($l) { $language = $l; } else { $language = ''; $language = $config{'routers.cgi-language'} if(defined $config{'routers.cgi-language'}); $language = $q->cookie('lang') if($q->cookie('lang')); } return if(!$language); $rv = readlang($language); $debugmessage .= "Lang=[$rv] "; return if(!defined $lang{$language}); # load the per-language defaults foreach ( qw/windowtitle iconurl charset weeknumber hournumber/ ) { $config{"routers.cgi-$_"} = $lang{$language}{"global-$_"} if(defined $lang{$language}{"global-$_"}); } foreach ( qw/shortdateformat longdateformat/ ) { $config{"web-$_"} = $lang{$language}{"global-$_"} if(defined $lang{$language}{"global-$_"}); } $config{'routers.cgi-iconurl'} .= "/" if( $config{'routers.cgi-iconurl'} !~ /\/$/ ); foreach ( keys %gtypes ) { $gtypes{$_} = $lang{$language}{"types-$_"} if( defined $lang{$language}{"types-$_"} ); } foreach ( keys %gstyles ) { $gstyles{$_} = $lang{$language}{"styles-$_"} if( defined $lang{$language}{"styles-$_"} ); } } ################################# # Special start_html sub start_html_ss($) { my($opts) = $_[0]; $opts->{-encoding} = $charset if($charset); if(!defined $opts->{'-link'}) { $opts->{'-link'}=$linkcolour; $opts->{'-vlink'}=$linkcolour; $opts->{'-alink'}=$linkcolour; } $opts->{'-text'}=$deffgcolour if(!defined $opts->{'-text'}); $opts->{'-bgcolor'}=$defbgcolour if(!defined $opts->{'-bgcolor'}); $opts->{'-title'}=$windowtitle if(!defined $opts->{'-title'}); print $q->start_html($opts)."\n"; } ################################# # Read in configuration file # readconf: pass it a list of section names # This should really be cached, keyed on $extra$myname$authuser sub readconf(@) { my ($inlist, $i, @secs, $sec, $usersec); @secs = @_; %config = (); $usersec = "\177"; $usersec = "user-".(lc $authuser) if( $authuser ); # set defaults %config = ( 'routers.cgi-confpath' => ".", 'routers.cgi-cfgfiles' => "*.conf *.cfg", 'web-png' => 0 ); ( open CFH, "<".$conffile ) || do { print $q->header({-expires=>"now"}); start_html_ss({ -title => langmsg(8999,"Error"), -bgcolor => "#ffd0d0" }); print $q->h1(langmsg(8999,"Error")) .$q->p(langmsg(3002,"Cannot read config file")." $conffile."); print $q->end_html(); exit(0); }; $inlist=0; $sec = ""; while( ) { /^\s*#/ && next; /\[(.*)\]/ && do { $sec = lc $1; $inlist=0; foreach $i ( @secs ) { if ( (lc $i) eq $sec ) { $inlist=1; last; } } # override for additional sections # put it here so people cant break things easily if( !$inlist and ( $sec eq $extra or $sec eq $myname or $sec eq $usersec ) ) { $sec = 'routers.cgi'; $inlist = 1; } next; }; # note final \s* to strip all trailing spaces (which works because # the *? operator is non-greedy!) This should also take care of # stripping trailing CR if file created in DOS mode (yeuchk). if ( $inlist ) { /(\S+)\s*=\s*(\S.*?)\s*$/ and $config{"$sec-$1"}=$2; } } close CFH; # legacy support for old dbdrive directive if(defined $config{'routers.cgi-dbdrive'} and $config{'routers.cgi-dbdrive'}) { $pathsep = "\\"; # and use the DOS path separator if( $config{'routers.cgi-dbpath'} !~ /^\w:/ ) { # backwards compatibility to add DB drive on, if not there already $config{'routers.cgi-dbpath'} = $config{'routers.cgi-dbdrive'} .":".$config{'routers.cgi-dbpath'}; } } # Activate NT compatibility options. # $^O is the OS name, NT usually produces 'MSWin32'. By checking for 'Win' # we should be able to cover most possibilities. if ( (defined $config{'web-NT'} and $config{'web-NT'}=~/[1y]/i) or $^O =~ /Win/ or $^O =~ /DOS/i ) { $dailylabel = "%H"; # Activeperl cant support %k option to strftime $monthlylabel = "%W"; # Activeperl cant support %V option either.... $pathsep = "\\"; $NT = 1; } # backwards compatibility for old v1.x users $config{'routers.cgi-iconurl'} = $config{'routers.cgi-iconpath'} if( !defined $config{'routers.cgi-iconurl'} and defined $config{'routers.cgi-iconpath'} ); # some path corrections: remove trailing path separators on f/s paths foreach ( qw/dbpath confpath graphpath graphurl/ ) { $config{"routers.cgi-$_"} =~ s/[\/\\]$//; } # and add a trailing path separator on URL paths... $config{'routers.cgi-iconurl'} = "/rrdicons/" if(!defined $config{'routers.cgi-iconurl'} ); $config{'routers.cgi-smalliconurl'} = $config{'routers.cgi-iconurl'} if( !defined $config{'routers.cgi-smalliconurl'}); $config{'routers.cgi-iconurl'} = $config{'routers.cgi-alticonurl'} if( defined $config{'routers.cgi-alticonurl'}); $config{'routers.cgi-iconurl'} .= "/" if( $config{'routers.cgi-iconurl'} !~ /\/$/ ); $config{'routers.cgi-smalliconurl'} .= "/" if( $config{'routers.cgi-smalliconurl'} !~ /\/$/ ); # get list of configuration files @cfgfiles = (); if( $config{'routers.cgi-cfgfiles'} ne 'none' ) { foreach ( split " ", $config{'routers.cgi-cfgfiles'} ) { # this may push a 'undef' onto the list, if the glob doesnt match # anything. We avoid this later... push @cfgfiles, glob($config{'routers.cgi-confpath'}.$pathsep.$_); } } # fix defaultinterface, if not specified correctly if( defined $config{'routers.cgi-defaulttarget'} and ! defined $config{'routers.cgi-defaultinterface'} ) { $config{'routers.cgi-defaultinterface'} = $config{'routers.cgi-defaulttarget'} ; } if( defined $config{'routers.cgi-defaultinterface'} and $config{'routers.cgi-defaultinterface'} !~ /^_/ ) { $config{'routers.cgi-defaultinterface'} = "__".$config{'routers.cgi-defaultinterface'}; $config{'routers.cgi-defaultinterface'} = "_outgoing" if( $config{'routers.cgi-defaultinterface'} eq "__outgoing" ); $config{'routers.cgi-defaultinterface'} = "_incoming" if( $config{'routers.cgi-defaultinterface'} eq "__incoming" ); $config{'routers.cgi-defaultinterface'} = "_summary_" if( $config{'routers.cgi-defaultinterface'} eq "__summary" ); } # escaping if( $NT ) { $config{'routers.cgi-defaultrouter'} =~ s/\\/\//g if( defined $config{'routers.cgi-defaultrouter'} ); } # allow [routers.cgi] section to override [web] section for some # parameters $config{'web-backurl'} = $config{'routers.cgi-backurl'} if(defined $config{'routers.cgi-backurl'}); $CACHE = 1 if ( defined $config{'routers.cgi-cache'} and $config{'routers.cgi-cache'} =~ /[y1]/i ); push @INC, (split /[\s,]+/,$config{'web-libadd'}) if(defined $config{'web-libadd'}); } ########################## sub do_footer() { if($uopts !~ /s/) { print $q->hr."\n\n"; print "
" .$q->a( { href=>$APPURL, target=>"_new" } , $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}routers2.gif", alt=>"Routers2.cgi", border=>0, width=>120, height=>40 }) ).""; print $q->small("routers.cgi Version $VERSION : © " .$q->a({href=>$APPMAIL},"Steve Shipway") ." 2000-2005 : ".$q->a({ href=>$APPURL, target=>"_top" },$APPURL) ).$q->br."\n"; if($language) { print "Language pack [$language]"; print ": ".$lang{$language}{'global-description'} if($lang{$language}{'global-description'}); print " Version ".$lang{$language}{'global-version'} if($lang{$language}{'global-version'}); print " by ".$lang{$language}{'global-author'} if($lang{$language}{'global-author'}); print "\n"; } print "" .$q->a( { href=>"http://www.rrdtool.org/", target=>"_new" } , $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}rrdtool.gif", alt=>"RRDTool", border=>0 }) )."
\n"; } # uopts print "\n"; print "\n" if($debugmessage); print "\n"; print "\n"; print "\n"; print "\n" if($archiveme); print "\n"; print $q->end_html(); } sub do_simple_footer() { print $q->hr."\n"; print $q->small("routers.cgi Version $VERSION : © " .$q->a({href=>$APPMAIL},"Steve Shipway") ." 2000-2005 : ".$q->a({ href=>$APPURL, target=>"_top" },$APPURL) )."\n"; print "\n"; print "\n" if($debugmessage); print $q->end_html(); } ########################################################################### # for security - create login page, verify username/password/cookie # routers.conf: # # verify_id -- reads cookies and params, returns verified username sub verify_id { my($uname,$cookie,$checksum, $token); $uname = $q->user_name(); # set by web server return $uname if($uname); # now taste cookie $cookie = $q->cookie('auth'); return '' if(!$cookie); # not defined return '' if($cookie !~ /^\s*([^:]+):(.*)$/); # bad format ($uname, $checksum) = ($1,$2); $token = $uname.$q->remote_host(); $token .= $CHOCOLATE_CHIP; # secret information # Can't do this because we havent read in the config file yet # $token .= $config{'web-auth-key'} if(defined $config{'web-auth-key'}); $token = unpack('%32C*',$token); # checksum if( $config{'web-auth-debug'} ) { $debugmessage .= "\ncookie[given[$uname:$checksum],test[$token]]\n"; } return $uname if( $token eq $checksum ); # yummy # bleah, nasty taste return ''; } # call appropriate verification routine sub user_verify($$) { my($rv) = 0; # default: refuse my($u,$p) = @_; # get the auth configuration info readconf( 'web' ); if( defined( $config{'web-ldaps-server'} ) ) { $rv = ldap_verify($u,$p,1); return $rv if($rv); } if( !$rv and defined( $config{'web-ldap-server'} ) ) { $rv = ldap_verify($u,$p,0); return $rv if($rv); } if( defined( $config{'web-password-file'} ) ) { $rv = file_verify($config{'web-password-file'},$u,$p,0); return $rv if($rv); } if( defined( $config{'web-htpasswd-file'} ) ) { $rv = file_verify($config{'web-htpasswd-file'},$u,$p,1); return $rv if($rv); } if( defined( $config{'web-md5-password-file'} ) ) { $rv = file_verify($config{'web-md5-password-file'},$u,$p,2); return $rv if($rv); } if( defined( $config{'web-unix-password-file'} ) ) { $rv = file_verify($config{'web-unix-password-file'},$u,$p,3); return $rv if($rv); } return 0; } # verify against a password file: username:password sub file_verify($$$$) { my($pwfile,$u,$p,$encmode) = @_; my($fp,$salt,$cp); $debugmessage .= " file_verify($pwfile,$u,$p,$encmode)\n" if( $config{'web-auth-debug'} ); open PW, "<$pwfile" or return 0; while( ) { if( /([^\s:]+):([^:]+)/ ) { if($1 eq $u) { $fp = $2; chomp $fp; close PW; # we are returning whatever if($encmode == 0) { # unencrypted. eek! return 1 if($p eq $fp); } elsif ($encmode == 1) { # htpasswd (unix crypt) if($crypthack) { require Crypt::UnixCrypt; $Crypt::UnixCrypt::OVERRIDE_BUILTIN = 1; } $salt = substr($fp,0,2); $cp = crypt($p,$salt); return 1 if($fp eq $cp); } elsif ($encmode == 2) { # md5 digest require Digest::MD5; return 1 if($fp eq Digest::MD5::md5($p)); } elsif ($encmode == 3) { # unix crypt if($crypthack) { require Crypt::UnixCrypt; $Crypt::UnixCrypt::OVERRIDE_BUILTIN = 1; } $salt = substr($fp,0,2); $cp = crypt($p,$salt); return 1 if($fp eq $cp); } # add new ones here... if( $config{'web-auth-debug'} ) { $debugmessage .= "Mismatch password [$u][$p]:[$fp]!=[$cp]\n"; } return 0; } elsif( $config{'web-auth-debug'} ) { $debugmessage .= "Mismatch user [$1][$u]\n"; } } elsif( $config{'web-auth-debug'} ) { $debugmessage .= "Bad format line $_"; } } close PW; return 0; # not found } # LDAP verify a username sub ldap_verify($$$) { my($u, $p, $sec) = @_; my($dn,$context,$msg); my($ldap); my($attr,@attrlist); if($sec) { # load the LDAPS module eval { require IO::Socket::SSL; require Net::LDAPS; }; if($@) { return 0; } # no Net::LDAPS installed } else { # load the LDAP module eval { require Net::LDAP; }; if($@) { return 0; } # no Net::LDAP installed } # Connect to LDAP and verify username and password if($sec) { $ldap = new Net::LDAPS($config{'web-ldaps-server'}); } else { $ldap = new Net::LDAP($config{'web-ldap-server'}); } if(!$ldap) { return 0; } @attrlist = ( 'uid','cn' ); @attrlist = split( " ", $config{'web-ldap-attr'} ) if( $config{'web-ldap-attr'} ); foreach $context ( split ":", $config{'web-ldap-context'} ) { foreach $attr ( @attrlist ) { $dn = "$attr=$u,".$context; $msg = $ldap->bind($dn, password=>$p) ; if(!$msg->is_error) { $ldap->unbind(); return 1; } } } return 0; # not found } # generate_cookie -- returns a cookie with current usrname, expiry sub generate_cookie { my($cookie); my($exp) = "+10min"; # note this stops wk/mon/yrly autoupdate from working my($token); return "" if(!$authuser); $exp = $config{'web-auth-expire'} if(defined $config{'web-auth-expire'}); $exp = "+10min" if(!$exp); # some checking for format $token = $authuser.$q->remote_host; # should really have time here also $token .= $CHOCOLATE_CHIP; # secret information # $token .= $config{'web-auth-key'} if(defined $config{'web-auth-key'}); $token = $authuser.':'.unpack('%32C*',$token); # checksum $cookie = $q->cookie( -name=>'auth', -value=>$token, -path=>$q->url(-absolute=>1), -expires=>$exp ) ; return $cookie; } # login_page -- output HTML login form that submits to top level sub login_page { # this is sent if auth = y and page = top (or blank), # or if page = login print $q->header({ -target=>'_top', -expires=>"now" })."\n"; start_html_ss({ -title =>langmsg(1000,"Login Required"), -onload => "document.login.username.focus();", -expires => "now" }); print $q->h1(langmsg(1000,"Authentication required"))."\n"; print "
\n"; print $q->p(langmsg(1001,"Please log in with your appropriate username and password in order to get access to the system."))."\n"; print "\n"; print $q->Tr($q->td($q->b(langmsg(1002,"Username"))) .$q->td($q->textfield({name=>'username'}) ))."\n"; print $q->Tr($q->td($q->b(langmsg(1003,"Password"))) .$q->td($q->password_field({name=>'password'}) ))."\n"; print $q->Tr($q->td("") .$q->td($q->submit({name=>'login',value=>'Login'}) ))."\n"; print "
\n"; do_simple_footer; #print $q->end_html; } # force_login -- output HTML that sends top level to login page sub force_login { my($javascript); my($err) = shift; # Javascript that sets window.location to login URL # This is created if auth = y and page != login and !authuser $javascript = "function redir() { "; $javascript .= "alert('$err'); " if($err); $javascript .= " window.location = '$meurlfull?page=login'; }"; $javascript = "function redir() {} " if($config{'web-auth-debug'}); print $q->header({ -target=>'_top', -expires=>"now" })."\n"; start_html_ss({ -title =>langmsg(1000,"Login Required"), -expires => "now", -script => $javascript, -onload => "redir()"}); print $q->h1(langmsg(1000,"Authentication required"))."\n"; print "Please ".$q->a({href=>"$meurl?page=login"},"login") ." before continuing.\n"; print "\n"; do_simple_footer; #print $q->end_html; } # logout -- set auth cookie to blank, expire now, and redirect to top sub logout_page { my($cookie,$javascript); # Javascript that sets window.location to login URL $javascript = "function redir() { window.location = '$meurlfull?page=main'; }"; $cookie = $q->cookie( -name=>'auth', -value=>'', -path=>$q->url(-absolute=>1), -expires=>"now" ) ; print $q->header({ -target=>'_top', -expires=>"now", -cookie=>[$cookie] })."\n"; start_html_ss({ -title =>langmsg(1004,"Logout complete"), -expires => "now", -script => $javascript, -onload => "redir()" }); print $q->h1(langmsg(1004,"Logged out of system"))."\n"; print "Please ".$q->a({href=>"$meurl?page=main"},"go back to the front page") ." to continue.\n"; do_simple_footer; #print $q->end_html; } ################################# # Read in files ########################################################################### # identify the type of file/interface and set up defaults sub inlist($@) { my($pat) = shift @_; return 0 if(!defined $pat or !$pat or !@_); foreach (@_) { return 1 if( $_ and /$pat/i ); } return 0; } sub routerdefaults($) { my( $key, $k, %identify ); $k = $_[0]; %identify = (); $identify{icon} = guess_icon(1,$k, $routers{$k}{shdesc}, $routers{$k}{hostname} ); foreach $key ( keys %identify ) { $routers{$k}{$key} = $identify{$key} if(!$routers{$k}{$key} ); } } # possible MODEs: interface, cpu, memory, generic (more to come) sub identify($) { my( $key, %identify, $k, @d, $mode ); my($unit,$totunit,$okfile); my($timel, $times); $k = $_[0]; # description defaults if(defined $config{"targetnames-$k"}) { $interfaces{$k}{shdesc} = $config{"targetnames-$k"}; } if(defined $config{"targettitles-$k"}) { $interfaces{$k}{desc} = $config{"targettitles-$k"}; } if(!defined $interfaces{$k}{shdesc}) { if(!defined $config{'targetnames-ifdefault'} or $config{'targetnames-ifdefault'} !~ /target/ ) { if(defined $interfaces{$k}{ipaddress}) { $interfaces{$k}{shdesc} = $interfaces{$k}{ipaddress}; } elsif(defined $interfaces{$k}{ifdesc}) { $interfaces{$k}{shdesc} = $interfaces{$k}{ifdesc}; } elsif(defined $interfaces{$k}{ifno}) { $interfaces{$k}{shdesc} = "#".$interfaces{$k}{ifno}; } else { # $interfaces{$k}{desc} =~ /^(\S+)/; # $interfaces{$k}{shdesc} = $1; $interfaces{$k}{shdesc} = $interfaces{$k}{desc}; } } if(defined $config{'targetnames-ifdefault'} and $config{'targetnames-ifdefault'} =~ /cfgmaker/i ) { if( $interfaces{$k}{pagetop} =~ /Port Name:[^<]*<\/TD>\s*]*>\s*([^<>\s][^<>]+)\s*]*>\s*([^\s<>][^<>]+)\s*]*>\s*([^\s<>][^<>]+) 3599 ) { $timel = langmsg(2402,"hour"); $times = "hr"; if($interfaces{$k}{mult} > 3600) { $totunit = "bytes"; } } elsif($interfaces{$k}{mult} >59 ) { $timel = langmsg(2401,"minute"); $times = "min"; if($interfaces{$k}{mult} > 60) { $totunit = "bytes"; } } elsif($interfaces{$k}{mult} > 1) { $totunit = "bytes"; } $unit = "$totunit/$times"; $unit = "bps" if($unit eq "bits/s" or $unit eq "bytes/s"); $identify{ylegend} = "per $timel"; $identify{background} = $defbgcolour; $identify{legendi} = langmsg(6403,"In: "); $identify{legendo} = langmsg(6404,"Out:"); $identify{legend1} = langmsg(6405,"Incoming") ; $identify{legend2} = langmsg(6406,"Outgoing"); $identify{legend3} = langmsg(6407,"Peak inbound"); $identify{legend4} = langmsg(6408,"Peak outbound"); $identify{total} = 1; $identify{percentile} = 1; $identify{percent} = 1; $identify{unit} = $unit; $identify{totunit} = $totunit; $identify{unscaled} = ""; if($mode eq "interface") { $identify{ylegend} = "traffic in $unit"; $identify{legendi} = langmsg(6403,"In: "); $identify{legendo} = langmsg(6404,"Out:"); $identify{legend1} = langmsg(6405,"Incoming traffic") ; $identify{legend2} = langmsg(6406,"Outgoing traffic"); $identify{legend3} = langmsg(6407,"Peak inbound traffic"); $identify{legend4} = langmsg(6408,"Peak outbound traffic"); $identify{icon} = "interface-sm.gif"; $identify{background} = $defbgcolour; #"#ffffff"; $identify{unscaled} = "6dwmy"; $identify{total} = 1; } elsif( $mode eq "cpu" ) { $identify{ylegend} = "Percentage use"; $identify{legendi} = "CPU"; $identify{unit} = "%"; $identify{fixunits} = 1; $identify{totunit} = ""; $identify{legend1} = "CPU usage"; $identify{legend3} = "Peak CPU usage"; $identify{legend2} = ""; $identify{legend4} = ""; $identify{icon} = "cpu-sm.gif"; $identify{background} = $defbgcolour; #"#ffffd0"; $identify{unscaled} = "6dwmy"; $identify{percent} = 0; $identify{total} = 0; } elsif( $mode eq "memory" ) { $identify{ylegend} = "Bytes used"; $identify{legendi} = "MEM"; $identify{legendo} = "MEM"; $identify{legend1} = "Memory usage"; $identify{legend3} = "Peak memory usage"; $identify{legend2} = "Sec. memory usage"; $identify{legend4} = "Peak sec memory usage"; $identify{icon} = "cpu-sm.gif"; $identify{background} = $defbgcolour; #"#d0d0ff"; $identify{total} = 0; $identify{unit} = "bytes"; $identify{unit} = "bits" if($interfaces{$k}{bits}); $identify{totunit} = ""; } elsif( $mode eq "ping" ) { $identify{totunit} = ""; $identify{unit} = "ms"; $identify{fixunits} = 1; $identify{ylegend} = "milliseconds"; $identify{legendi} = "High:"; $identify{legendo} = "Low:"; $identify{legend1} = "Round trip time range"; $identify{legend2} = "Round trip time range"; $identify{legend3} = "High peak 5min RTT"; $identify{legend4} = "Low peak 5min RTT"; $identify{icon} = "clock-sm.gif"; $identify{background} = $defbgcolour; #"#ffffdd"; $identify{total} = 0; $identify{percent} = 0; $identify{percentile} = 0; $identify{unscaled} = ""; } elsif( $mode eq "percent" ) { $identify{totunit} = ""; $identify{unit} = "%"; $identify{fixunits} = 1; $identify{ylegend} = langmsg(2409,"percentage"); $identify{total} = 0; $identify{percent} = 0; $identify{percentile} = 0; } elsif( $mode eq "relpercent" ) { $identify{totunit} = ""; $identify{unit} = "%"; $identify{fixunits} = 1; $identify{ylegend} = langmsg(2409,"percentage"); $identify{total} = 0; $identify{percent} = 0; $identify{percentile} = 0; $identify{legendi} = langmsg(2410,"ratio:"); $identify{legend1} = langmsg(2411,"Inbound as % of outbound"); $identify{legend3} = langmsg(2412,"Peak Inbound as % of peak outbound"); if( defined $interfaces{$k}{ifno} or defined $interfaces{$k}{ifdesc} or $interfaces{$k}{isif} or defined $interfaces{$k}{ipaddress} ) { $identify{icon} = "interface-sm.gif"; } } # unscaled default option if( defined $config{'routers.cgi-unscaled'} ) { if( $config{'routers.cgi-unscaled'} =~ /y/i ) { $identify{unscaled} = "6dwmy" ; } else { $identify{unscaled} = "" ; } } # set icon $identify{icon} = guess_icon( 0, $k, $interfaces{$k}{desc}, $interfaces{$k}{shdesc} ) if(!defined $identify{icon}); # different default for totunit # if we have a custom 'unit' but no custom 'totunit', then try to be # a bit more clever. if( defined $interfaces{$k}{unit} ) { my( $u ) = $interfaces{$k}{unit}; if( $u =~ /^(.*)\// ) { $identify{totunit} = $1; } elsif( $u =~ /^(.*)ps$/ ) { $identify{totunit} = $1; } else { $identify{totunit} = $u; } } # set the defaults foreach $key ( keys %identify ) { $interfaces{$k}{$key} = $identify{$key} if(!defined $interfaces{$k}{$key} ); } $interfaces{$k}{mult} = 1 if(!defined $interfaces{$k}{mult}); $interfaces{$k}{maxbytes} = 0 if(!defined $interfaces{$k}{maxbytes}); $interfaces{$k}{max} = $interfaces{$k}{maxbytes} * $interfaces{$k}{mult}; $interfaces{$k}{max1} = $interfaces{$k}{maxbytes1} * $interfaces{$k}{mult} if(defined $interfaces{$k}{maxbytes1}); $interfaces{$k}{max2} = $interfaces{$k}{maxbytes2} * $interfaces{$k}{mult} if(defined $interfaces{$k}{maxbytes2}); # Multiply thresholds by appropriate amount foreach ( qw/threshmini threshmaxi threshmino threshmaxo upperlimit lowerlimit/ ) { $interfaces{$k}{$_} *= $interfaces{$k}{mult} if(defined $interfaces{$k}{$_}); } $interfaces{$k}{max} = $interfaces{$k}{max1} if(defined $interfaces{$k}{max1} and $interfaces{$k}{max1} > $interfaces{$k}{max} ); $interfaces{$k}{max} = $interfaces{$k}{max2} if(defined $interfaces{$k}{max2} and $interfaces{$k}{max2} > $interfaces{$k}{max} ); $interfaces{$k}{absmax} = $interfaces{$k}{absmaxbytes} * $interfaces{$k}{mult} if(defined $interfaces{$k}{absmaxbytes}); if(defined $interfaces{$k}{factor} ) { $interfaces{$k}{max} *= $interfaces{$k}{factor}; $interfaces{$k}{absmax} *= $interfaces{$k}{factor} if(defined $interfaces{$k}{absmax}); $interfaces{$k}{max1} *= $interfaces{$k}{factor} if(defined $interfaces{$k}{max1}); $interfaces{$k}{max2} *= $interfaces{$k}{factor} if(defined $interfaces{$k}{max2}); } $interfaces{$k}{noo} = 1 if(!$interfaces{$k}{legend2}); $interfaces{$k}{noi} = 1 if(!$interfaces{$k}{legend1}); # catch the stupid people if($interfaces{$k}{noo} and $interfaces{$k}{noi}) { $interfaces{$k}{inmenu} = 0; $interfaces{$k}{insummary} = 0; $interfaces{$k}{inout} = 0; } } # guess an appropriate icon. 1st param is 1 for devices menu, 0 for targets # other parameters are a list of attributes to check sub guess_icon($@) { my($m) = shift @_; if($m) { # these tests for devices menu only return "cisco-sm.gif" if( inlist "cisco",@_ ); return "3com-sm.gif" if( inlist "3com",@_ ); return "intel-sm.gif" if( inlist "intel",@_ ); return "router-sm.gif" if( inlist "router",@_ ); return "switch-sm.gif" if( inlist "switch",@_ ); return "firewall-sm.gif" if( inlist "firewall",@_ ); return "ibm-sm.gif" if( inlist "ibm",@_ ); return "linux-sm.gif" if( inlist "linux",@_ ); return "freebsd-sm.gif" if( inlist "bsd",@_ ); return "novell-sm.gif" if( inlist "novell",@_ ); # these commented out as patterns are too short to be reliable # return "mac-sm.gif" if( inlist "mac|apple",@_ ); # return "sun-sm.gif" if( inlist "sun",@_ ); # return "hp-sm.gif" if( inlist "hp",@_ ); return "win-sm.gif" if( inlist "windows",@_ ); } return "mail-sm.gif" if( inlist 'mail|messages',@_ ); return "web-sm.gif" if( inlist 'internet',@_ or inlist 'proxy',@_ ); return "phone-sm.gif" if( inlist 'phone',@_ ); return "modem-sm.gif" if( inlist 'modem',@_ ); return "disk-sm.gif" if( inlist 'nfs\w',@_ or inlist 'dsk',@_ ); return "globe-sm.gif" if( inlist 'dns\w',@_ ); return "people-sm.gif" if( inlist 'user[s ]',@_ ); return "server-sm.gif" if( inlist 'server|host',@_ ); return "web-sm.gif" if( inlist 'web',@_ ); return "traffic-sm.gif" if( inlist 'traffic',@_ ); return "chip-sm.gif" if( inlist 'memory|cpu',@_ ); return "interface-sm.gif" if(!$m and inlist 'interface|serial',@_ ); return "disk-sm.gif" if( inlist 'dis[kc]|filesystem',@_ ); return "clock-sm.gif" if( inlist 'time|rtt|ping',@_ ); return "temp-sm.gif" if( inlist 'temp|climate|environment|heat',@_ ); return "menu-sm.gif" if( inlist '\wlog',@_ ); return "interface-sm.gif" if(!$m and inlist 'BRI|eth|tok|ATM|hme',@_ ); return "load-sm.gif" if( inlist 'load|weight',@_ ); return "web-sm.gif" if( inlist 'www',@_ ); if($m) { # last chance with these less reliable ones return "mac-sm.gif" if( inlist "mac|apple",@_ ); return "sun-sm.gif" if( inlist "sun",@_ ); return "hp-sm.gif" if( inlist "hp",@_ ); return "win-sm.gif" if( inlist "win|pdc|bdc",@_ ); } if($m) { return $config{'targeticons-filedefault'} if(defined $config{'targeticons-filedefault'}); return "menu-sm.gif"; } else { return $config{'targeticons-ifdefault'} if(defined $config{'targeticons-ifdefault'}); return "target-sm.gif"; } } # Parse an extension parameters sub parse_ext($) { my ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = ("","","cog-sm.gif","graph",0,0,0 ); my( @tok ) = quotewords('\s+',0,$_[0]); # $desc = shift @tok; # $url = shift @tok; foreach (@tok) { if( /^(https?:|ftp|telnet:)?\// and !$url ) { $url = $_; next; } if( /\.(gif|png|jpg)$/ ) { $icon = $_; next; } if(!$desc) { $desc = $_ ; next; } if( /^\d+$/ ) { $level = $_; next; } if( /^insec(ure)?$/ ) { $insec = 1; next; } if( /^noopt(ion)?s?$/ ) { $noop = 1; next; } if(!$url) { $url = $_ ; next; } # must be a strange URL $targ = $_; # Must be a target frame name } $desc = "Extension" if(!$desc); $url = "/" if(!$url); return ($desc, $url, $icon, $targ, $level, $insec, $noop); } sub parse_link($) { my ( $desc, $url, $icon, $targ, $level ) = ("Link",$q->url,"link-general-sm.gif","",0 ); my( @tok ) = quotewords('\s+',0,$_[0]); $desc = shift @tok; $url = shift @tok; foreach (@tok) { if( /^\d+$/ ) { $level = $_; next; } if( /\.(gif|png|jpg)$/ ) { $icon = $_; next; } $targ = $_; # Must be a target frame name } return ($desc, $url, $icon, $targ, $level); } # read in all routers files. # routers hash: key= filename (within confpath) # data: hash: # keys: filename (full), shdesc, desc, inmenu, hasinout # group, icon sub read_routers() { my( $matchstr, $curfile, $curpat, $key, $bn, $group, $f ); my( $arg, $desc, $url, $icon, $targ, $insec, $level, $noop, $targfile ); my( $rckey ); my( $optimise ) = 0; if($CACHE) { # cache key: people may have different cfg file sets! $rckey = $config{'routers.cgi-confpath'} .'/'.$config{'routers.cgi-cfgfiles'}; if(defined $routerscache{$rckey}) { $debugmessage .= "cache(routers) "; %routers = %{$routerscache{$rckey}}; $readinrouters = 1; return; } } $optimise = 1 if( defined $config{'routers.cgi-optimise'} and $config{'routers.cgi-optimise'} =~ /[y1]/i ); %routers = (); # for $curpat ( split " ",$config{'routers.cgi-cfgfiles'} ) { #FILE: for $curfile (glob($config{'routers.cgi-confpath'}.$pathsep.$curpat)) { FILE: for $curfile ( @cfgfiles ) { next if(! -f $curfile or ! -r $curfile); $key = $curfile; $matchstr = $config{'routers.cgi-confpath'}.$pathsep; $matchstr =~ s/\\/\\\\/g; $key =~ s/^$matchstr//; $f = $bn = basename($curfile,''); $f =~ s/\.c(fg|onf)$//; $group = dirname($curfile); # set the defaults $routers{$key} = { file=>$curfile, inmenu=>1, group=>$group, icon=>"", interval=>5, hastarget=>0 }; # read the file for any overrides open CFG,"<$curfile" || do { # $routers{$key}{inmenu}=0; $routers{$key}{desc}="Error opening file"; $routers{$key}{icon}="alert-sm.gif"; next; }; LINE: while( ) { /^#\s+System:\s+(\S.*)/ and do { $routers{$key}{desc} = $1 if( defined $config{'targetnames-routerdefault'} and $config{'targetnames-routerdefault'} =~ /cfgmaker/i ); next; }; /^\s*#/ && next; if( /^\s*(routers2?\.cgi\*)?Target\[\S+\]\s*:.*:([^\s@]+)@([^:\s]+)/i ) { $routers{$key}{community}=$2 if(!$routers{$key}{community}); $routers{$key}{hostname}=$3 if(!$routers{$key}{hostname}); $routers{$key}{hastarget}=1; next; } if( /^\s*(routers2?\.cgi\*)?Target\[\S+\]/i ) { $routers{$key}{hastarget}=1; next; } if( /^\s*Include\s*:/i ) { $routers{$key}{hastarget}=1; # make the assumption next; } if( /^\s*Title\[\S+\]\s*:\s*(.*)/i ) { $routers{$key}{firsttitle}=$1; last if($optimise); next; } if( /^\s*WorkDir\s*:\s*(.*)/i ) { $routers{$key}{workdir}=$1; next; } if( /^\s*Interval\s*:\s*(\d+)/i ) { $routers{$key}{interval}=$1; next; } next unless( /^\s*routers2?\.cgi\*/i ); # Optimise! if( /^\s*routers2?\.cgi\*Options\s*:\s*(.*)/i ) { $routers{$key}{inmenu} = 0 if($1 =~ /ignore/i ); next; } if( /^\s*routers2?\.cgi\*(Descr?|Name|Description)\s*:\s*(.*)/i ) { $routers{$key}{desc} = $2; next; } if( /^\s*routers2?\.cgi\*Short(Descr?|Name|Description)\s*:\s*(.*)/i ) { $routers{$key}{shdesc} = $2; next; } if( /^\s*routers2?\.cgi\*Icon\s*:\s*(.*)/i ) { $routers{$key}{icon}=$1; next; } if( /^\s*routers2?\.cgi\*Ignore\s*:\s*(\S+)/i ) { $arg = $1; if($arg =~ /y/i) { delete $routers{$key}; close CFG; next FILE; } next; } if( /^\s*routers2?\.cgi\*InMenu\s*:\s*(\S+)/i ) { $arg = $1; $routers{$key}{inmenu}=0 if($arg =~ /n/i); next; } if( /^\s*routers2?\.cgi\*RoutingTable\s*:\s*(\S+)/i ) { $arg = $1; $routers{$key}{routingtable}="n" if($arg =~ /[0n]/i); $routers{$key}{routingtable}="y" if($arg =~ /[1y]/i); next; } if( /^\s*routers2?\.cgi\*ClearExtensions?\s*:\s*(\S.*)/i ) { $arg = $1; $routers{$key}{extensions} = [] if($arg =~ /[y1]/i); next; } if( /^\s*routers2?\.cgi\*Extensions?\s*:\s*(\S.*)/i ) { $arg = $1; ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = parse_ext($arg); next if(!$url or !$desc); $routers{$key}{extensions} = [] if(!defined $routers{$key}{extensions}); my( $lasthostname,$lastcommunity ) = ( '','' ); $lasthostname = $routers{$key}{hostname} if( defined $routers{$key}{hostname} ); $lastcommunity= $routers{$key}{community} if( defined $routers{$key}{community} ); push @{$routers{$key}{extensions}}, {desc=>$desc, url=>$url, icon=>$icon, target=>$targ, hostname=>$lasthostname, community=>$lastcommunity, insecure=>$insec, level=>$level, noopts=>$noop }; next; } if( /^\s*routers2?\.cgi\*Link\s*:\s*(\S.*)/i ) { $arg = $1; ( $desc, $targfile, $icon, $targ, $level ) = parse_link($arg); next if(!$targfile or !$desc); $icon = "link-general-sm.gif" if(!$icon); $url = $meurl."?rtr=".$q->escape($targfile) ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; $routers{$key}{extensions} = [] if(!defined $routers{$key}{extensions}); push @{$routers{$key}{extensions}}, { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", level=>$level, insecure=>0, noopts=>1 }; next; } if( /^\s*routers2?\.cgi\*Redirect\s*:\s*(\S+)/i ) { $arg = $1; $routers{$key}{redirect} = $arg; $routers{$key}{inmenu} = 1; $routers{$key}{hastarget} = 1; next; } } close CFG; # desc default if(!$routers{$key}{shdesc}) { if($config{'targetnames-routerdefault'} =~ /hostname/ ) { if(defined $routers{$key}{hostname} ) { $routers{$key}{shdesc} = $routers{$key}{hostname}; } else { $routers{$key}{shdesc} = $f; } } elsif($config{'targetnames-routerdefault'} =~ /ai/ and defined $routers{$key}{firsttitle} ) { $routers{$key}{firsttitle} =~ /([^\s:\(]+)/; $routers{$key}{shdesc} = $1; $routers{$key}{desc} = $routers{$key}{firsttitle}; } else { $routers{$key}{shdesc} = $f; # $routers{$key}{desc} = $curfile if(!$routers{$key}{desc}); } } $routers{$key}{desc} = $routers{$key}{shdesc} if(!$routers{$key}{desc}); # check routers.conf for any overrides if(defined $config{"targetnames-$bn"}) { $routers{$key}{shdesc} = $config{"targetnames-$bn"}; $routers{$key}{desc} = $config{"targetnames-$bn"}; } $routers{$key}{desc} = $config{"targettitles-$bn"} if(defined $config{"targettitles-$bn"}); $routers{$key}{icon} = $config{"targeticons-$bn"} if(defined $config{"targeticons-$bn"}); routerdefaults $key; # } # files # } # patterns } # files foreach $key ( keys %routers ) { $routers{$key}{inmenu} = 0 if(!$routers{$key}{hastarget}); } if( $config{'routers.cgi-servers'} =~ /[yY1]/ ) { foreach ( keys %config ) { if( /^servers-(\S+)/i ) { $routers{"#SERVER#$1"} = { file=>"", inmenu=>1, group=>"SERVERS", icon=>"server-sm.gif", server=>$1, interval=>5, hastarget=>1, inmenu=>1, desc=>$config{$_}, shdesc=>$config{$_} }; $routers{"#SERVER#$1"}{icon} = $config{"targeticons-$1"} if(defined $config{"targeticons-$1"}); } } } # we need to copy the hash, not a hashref, since %routers will be # re-used in future invocations if($CACHE) { $routerscache{$rckey} = { %routers }; $debugmessage .= "cached[routers] "; } else { $debugmessage .= "NOCACHE[routers] "; } $readinrouters = 1 ; # for people without caching } ########################################################################### # set pseudointerfaces for a server target sub set_svr_ifs() { my( $server ); %interfaces = (); $server = $router; $server =~ s/^#SERVER#//; $interfaces{"CPU"} = { file=>"", icon=>"chip-sm.gif", rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), shdesc=>"CPU Usage", mult=>1, unit=>"%", fixunits=>1, legendi=>"User:", legendo=>"System:", ylegend=>"Percentage", legendx=>"Wait:", legend1=>"User processes", legend2=>"System Processes", legend3=>"Max User Processes", legend4=>"Max System processes", legend5=>"System Wait", legend6=>"Max system wait", desc=>"CPU Usage on $server", mode=>"SERVER", hostname=>$server, insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, interval=>5, nomax=>1, noabsmax=>1, maxbytes=>100, max=>100, available=>1 }; $interfaces{"Users"} = { file=>"", mult=>1,icon=>"people-sm.gif", rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), shdesc=>"Users", noo=>1, integer=>1, percent=>0, fixunits=>1, ylegend=>"User count", legendi=>"Users:", legend1=>"User count", legend3=>"Max user count", desc=>"User count on $server", mode=>"SERVER", hostname=>$server, insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, interval=>5, nomax=>1, noabsmax=>1, maxbytes=>10000, available=>1 }; $interfaces{"Page"} = { file=>"", mult=>1, icon=>"disk-sm.gif", rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), shdesc=>"Paging", noo=>1, unit=>"pps", fixunits=>1, legendi=>"Activity:", legend1=>"Paging activity", legend3=>"Max paging activity", percent=>0, ylegend=>"Pages per second", desc=>"Paging activity on $server", mode=>"SERVER", hostname=>$server, insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, interval=>5, nomax=>1, noabsmax=>1, maxbytes=>10000, available=>1 }; } ########################################################################### # read in a specified cfg file (default to current router file) # interfaces hash: key= targetname # data: hash: # keys: lots. sub read_cfg_file($$) { my($cfgfile,$makespecial) = @_; my($opts, $graph, $key, $k, $fd, $buf, $curif, @myifs, $arg, $argb, $rrd); my($ifcnt, @ifarr, $t, $desc, $url, $icon, $targ, $newfile, $targfile); my( $lasthostname, $lastcommunity ) = ("",""); my($level, $insec, $noop, $logdir); my( $inpagetop, $inpagefoot ) = (0,0); return if(!$cfgfile); $debugmessage .= "$cfgfile "; $fd = new FileHandle ; if(! $fd->open( "<$cfgfile" )) { $interfaces{$cfgfile} = { shdesc=>"Error", desc=>"Cannot open file $cfgfile", inmenu=>0, rrd=>"", insummary=>0, inout=>0, incompact=>0, mode=>"ERROR", icon=>"alert-sm.gif" }; return; } $key = ""; $curif = ""; @myifs = (); while ( $buf = <$fd> ) { next if( $buf =~ /^\s*#/ ); next if( $buf =~ /^\s*$/ ); # bit more efficient if( $inpagefoot ) { if( $curif and $buf =~ /^\s+\S/ ) { $interfaces{$curif}{pagefoot} .= $buf; next; } $inpagefoot = 0; } if( $inpagetop ) { if( $curif and $buf =~ /^\s+\S/ ) { $interfaces{$curif}{pagetop} .= $buf; next; } $inpagetop = 0; } if( $buf =~ /^\s*(routers2?\.cgi\*)?Target\[(.+?)\]\s*:\s*(.+)/i ) { $curif = $2; $arg = $3; push @myifs, $curif; # This ***MIGHT*** save people who put their .cfg files # out of sequence? if(!defined $interfaces{$curif}) { $interfaces{$curif} = { file=>$cfgfile, target=>$curif, insummary=>1, incompact=>1, inmenu=>1, isif=>0, interval=>$interval, nomax=>0, noabsmax=>0 }; } else { $interfaces{$curif} = { file=>$cfgfile, target=>$curif, insummary=>1, incompact=>1, inmenu=>1, isif=>0, interval=>$interval, nomax=>0, noabsmax=>0, %{$interfaces{$curif}} }; } if(defined $interfaces{_}{directory}) { $interfaces{$curif}{rrd} = $workdir.$pathsep.$interfaces{_}{directory} .$pathsep.(lc $curif).".rrd"; } else { $interfaces{$curif}{rrd} = $workdir.$pathsep.(lc $curif).".rrd"; } if( $arg =~ /^-?(\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) { # interface number $interfaces{$curif}{isif} = 1; $interfaces{$curif}{ifno} = $1; $interfaces{$curif}{community} = $2; $interfaces{$curif}{hostname} = $3; $interfaces{$curif}{mode} = "interface"; } elsif( $arg =~ /^-?\/(\d+\.\d+\.\d+\.\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) { # IP address $interfaces{$curif}{isif} = 1; $interfaces{$curif}{ipaddress} = $1; $interfaces{$curif}{community} = $2; $interfaces{$curif}{hostname} = $3; $interfaces{$curif}{mode} = "interface"; } elsif( $arg =~ /^-?[\\#!](\S.*?):([^\@:\s]+)\@([\w\-\.]+)/ ) { $interfaces{$curif}{isif} = 1; $interfaces{$curif}{ifdesc} = $1; $interfaces{$curif}{community} = $2; $interfaces{$curif}{hostname} = $3; $interfaces{$curif}{mode} = "interface"; $interfaces{$curif}{ifdesc} =~ s/\\(.)/$1/g ; } elsif( $arg =~ /&\w*[\d\.]+:(\S+)\@([\w\-\.]+)/ ) { # explicit OIDs $interfaces{$curif}{community} = $1; $interfaces{$curif}{hostname} = $2; } elsif( $arg =~ /mrtg.ping.probe/ ) { # special for the mrtg-ping-probe.pl $interfaces{$curif}{mode} = "ping"; $interfaces{$curif}{graphstyle} = "range"; $interfaces{$curif}{incompact} = 1; $interfaces{$curif}{ifdesc} = langmsg(2413,"Response time") ; } elsif( $arg =~ /`/ ) { # external program $interfaces{$curif}{insummary} = 1; $interfaces{$curif}{incompact} = 1; } else { # a target of some sort we dont yet know $interfaces{$curif}{insummary} = 0; $interfaces{$curif}{incompact} = 0; } $interfaces{$curif}{inout} = $interfaces{$curif}{isif}; foreach $k ( qw/isif inout incompact insummary inmenu/ ) { $interfaces{$curif}{$k} = $interfaces{'_'}{$k} if(defined $interfaces{'_'}{$k}); } $lasthostname = $interfaces{$curif}{hostname} if(defined $interfaces{$curif}{hostname}); $lastcommunity= $interfaces{$curif}{community} if(defined $interfaces{$curif}{community}); next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?(Title|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $3; $arg = $4; if(!defined $interfaces{$curif}) { if(defined $interfaces{"_$curif"}) { $curif = "_$curif"; } else { $interfaces{$curif} = {note=>"Out of sequence"}; } } $interfaces{$curif}{desc} = $arg; next; } if( $buf =~ /^\s*Options\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; next if(!defined $interfaces{$curif}); $interfaces{$curif}{options} = "" if(!$interfaces{$curif}{options}); $interfaces{$curif}{options} .= ' '.$2; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?PageTop\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $2; $arg = $3; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{pagetop} = $arg; $inpagetop = 1; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?PageFoot\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $2; $arg = $3; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{pagefoot} = $arg; $inpagefoot = 1; next; } if( $buf =~ /^\s*SetEnv\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $arg = $2; next if(!defined $interfaces{$curif}); foreach $k ( quotewords('\s+',0,$arg) ) { if( $k =~ /MRTG_INT_IP=\s*(\d+\.\d+\.\d+\.\d+)/ ) { $interfaces{$curif}{ipaddress}=$1 if(!defined $interfaces{$curif}{ipaddress}); next; } if( $k =~ /MRTG_INT_DESCR?=\s*(\S.*)/ ) { $interfaces{$curif}{shdesc}=$1 if(!defined $interfaces{$curif}{shdesc}); next; } } next; } if( $buf =~ /^\s*routers2?\.cgi\*Short(Name|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $2; $arg = $3; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{shdesc} = $arg if($arg); next; } if( $buf =~ /^\s*routers2?\.cgi\*Options\[(.+?)\]\s*:\s*(\S.*)/i ) { next if(!defined $interfaces{$1}); $interfaces{$1}{cgioptions}="" if(!$interfaces{$1}{cgioptions}); $interfaces{$1}{cgioptions} .= " ".$2; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?MaxBytes\[(.+?)\]\s*:\s*(\d+)/i ) { next if(!defined $interfaces{$2}); $interfaces{$2}{maxbytes} = $3; next; } if($buf=~ /^\s*(routers2?\.cgi\*)?Unscaled\[(.+?)\]\s*:\s*([6dwmy]*)/i){ next if(!defined $interfaces{$2}); $interfaces{$2}{unscaled} = $3; next; } if($buf=~ /^\s*(routers2?\.cgi\*)?WithPeaks?\[(.+?)\]\s*:\s*([dwmy]*)/i) { next if(!defined $interfaces{$2}); $interfaces{$2}{withpeak} = $3; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?YLegend\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{ylegend} = $3; next; } if($buf=~ /^\s*(routers2?\.cgi\*)?ShortLegend\[(.+?)\]\s*:\s*(.*)/i){ next if(!defined $interfaces{$2}); $interfaces{$2}{unit} = $3; $interfaces{$2}{unit} =~ s/ / /g; next; } if($buf=~ /^\s*routers2?\.cgi\*TotalLegend\[(.+?)\]\s*:\s*(.*)/i){ $curif = $1; $arg = $2; next if(!defined $interfaces{$curif}); $arg =~ s/ / /g; $interfaces{$curif}{totunit} = $arg; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?(Legend[IO1234TA][IO]?)\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $3; $key = lc $2; $arg = $4; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $arg =~ s/ / /; $interfaces{$curif}{$key} = $arg; next; } if( $buf =~ /^\s*routers2?\.cgi\*Mode\[(.+?)\]\s*:\s*(\S+)/i ) { next if(!defined $interfaces{$1}); $interfaces{$1}{mode} = $2; next; } if( $buf =~ /^\s*routers2?\.cgi\*RoutingTable\s*:\s*(\S.*)/i ) { $arg = $1; $routers{$router}{routingtable} = "y" if($arg =~ /y/i); $routers{$router}{routingtable} = "n" if($arg =~ /n/i); next; } if( $buf =~ /^\s*routers2?\.cgi\*ClearExtensions?\s*:\s*(\S.*)/i and !$readinrouters) { $arg = $1; $routers{$router}{extensions} = [] if($arg =~ /[y1]/i); next; } if( !$readinrouters and $buf =~ /^\s*routers2?\.cgi\*Extensions?\s*:\s*(\S.*)/i ) { $arg = $1; ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = parse_ext($arg); next if(!$url or !$desc); $routers{$router}{extensions} = [] if(!defined $routers{$router}{extensions}); push @{$routers{$router}{extensions}}, {desc=>$desc, url=>$url, icon=>$icon, target=>$targ, hostname=>$lasthostname, community=>$lastcommunity, insecure=>$insec, level=>$level, noopts=>$noop }; next; next; } if( !$readinrouters and $buf =~ /^\s*routers2?\.cgi\*Link\s*:\s*(\S.*)/i ) { $arg = $1; ( $desc, $targfile, $icon, $targ, $level ) = parse_link($arg); next if(!$targfile or !$desc); $icon = "link-general-sm.gif" if(!$icon); $url = $meurl."?rtr=".$q->escape($targfile) ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; $routers{$router}{extensions} = [] if(!defined $routers{$router}{extensions}); push @{$routers{$router}{extensions}}, { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", level=>$level, insecure=>0, noopts=>1 }; next; } if( $buf =~ /^\s*routers2?\.cgi\*Extensions?\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $arg = $2; ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = parse_ext($arg); $interfaces{$curif}{extensions} = [] if(!defined $interfaces{$curif}{extensions}); push @{$interfaces{$curif}{extensions}}, { desc=>$desc, url=>$url, icon=>$icon, target=>$targ, hostname=>$interfaces{$curif}{hostname}, community=>$interfaces{$curif}{community}, level=>$level, insecure=>$insec, noopts=>$noop }; next; } if( $buf =~ /^\s*routers2?\.cgi\*Link\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $arg = $2; # ( $desc, $targfile, $targ, $icon ) = quotewords('\s+',0,$arg); ( $desc, $targfile, $icon, $targ, $level ) = parse_link($arg); next if(!$targfile or !$desc); # if( $targ =~ /\.(gif|png)$/ and !$icon ) { # $icon = $targ; $targ = ""; # } $icon = "link-general-sm.gif" if(!$icon); $url = $meurl."?rtr=".$q->escape($targfile) ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; $interfaces{$curif}{extensions} = [] if(!defined $interfaces{$curif}{extensions}); push @{$interfaces{$curif}{extensions}}, { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", level=>$level, insecure=>0 }; next; } if( $buf =~ /^\s*routers2?\.cgi\*(Graph|Summary)\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $2; $arg = $3; $argb = (lc $1); next if( $curif eq '_' ); # not allowed if(!defined $interfaces{$curif}) { if( $argb eq "summary") { $curif = "_$curif" ; } else { # Create a dummy target... $interfaces{$curif} = { file=>$cfgfile, target=>$curif, insummary=>0, incompact=>0, inmenu=>0, isif=>0, interval=>$interval, nomax=>0, noabsmax=>0 }; if(defined $interfaces{_}{directory}) { $interfaces{$curif}{rrd} = $workdir.$pathsep.$interfaces{_}{directory} .$pathsep.(lc $curif).".rrd"; } else { $interfaces{$curif}{rrd} = $workdir.$pathsep.(lc $curif).".rrd"; } } } next if(!defined $interfaces{$curif}); if( $arg =~ /^"/ ) { $arg =~ /^"([^"]+)"\s*:?(.*)/; $opts = $2; $graph = $1; } else { $arg =~ /^(\S+)\s*:?(.*)/; $opts = $2; $graph = $1; } next if(!$graph); $interfaces{$curif}{usergraphs} = [] if(!defined $interfaces{$curif}{usergraphs}); push @{$interfaces{$curif}{usergraphs}}, $graph; if( defined $interfaces{"_$graph"} ) { push @{$interfaces{"_$graph"}{targets}}, $curif if(!inlist("^$curif\$",@{$interfaces{"_$graph"}{targets}})); $interfaces{"_$graph"}{cgioptions} .= " $opts"; } else { if( $argb eq "summary" ) { $interfaces{"_$graph"} = { shdesc=>$graph, targets=>[$curif], cgioptions=>$opts, mode=>"\177_USERSUMMARY", usergraph=>1, icon=>"summary-sm.gif", inout=>0, incompact=>0, withtotal=>0, withaverage=>0, insummary=>0, inmenu=>1, desc=>"Summary $graph", issummary=>1 }; } else { $interfaces{"_$graph"} = { shdesc=>$graph, targets=>[$curif], cgioptions=>$opts, mode=>"\177_USER", usergraph=>1, icon=>"cog-sm.gif", inout=>0, incompact=>0, insummary=>0, inmenu=>1, desc=>"User defined graph $graph", withtotal=>0, withaverage=>0, issummary=>0 }; $interfaces{"_$graph"}{rrd} = $interfaces{$curif}{rrd}; } $interfaces{"_$graph"}{withtotal} = 1 if( defined $config{'routers.cgi-showtotal'} and $config{'routers.cgi-showtotal'}=~/y/i); push @myifs, "_$graph"; } next; } if( $buf =~ /^\s*routers2?\.cgi\*Icon\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{icon} = $arg; next; } if( $buf =~ /^\s*routers2?\.cgi\*Ignore\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); if( $arg =~ /y/i ) { $interfaces{$curif}{insummary} = 0; $interfaces{$curif}{inmenu} = 0; $interfaces{$curif}{inout} = 0; $interfaces{$curif}{isif} = 0; } next; } if( $buf =~ /^\s*routers2?\.cgi\*InSummary\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); if( $arg =~ /[1y]/i ) { $interfaces{$curif}{insummary} = 1; } else { $interfaces{$curif}{insummary} = 0; } next; } if( $buf =~ /^\s*routers2?\.cgi\*InMenu\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); if( $arg =~ /[1y]/i ) { $interfaces{$curif}{inmenu} = 1; } else { $interfaces{$curif}{inmenu} = 0; } next; } if( $buf =~ /^\s*routers2?\.cgi\*InOut\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; next if(!defined $interfaces{$curif}); if( $arg =~ /[1y]/i ) { $interfaces{$curif}{inout} = 1; } else { $interfaces{$curif}{inout} = 0; } next; } if( $buf =~ /^\s*routers2?\.cgi\*InCompact\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; next if(!defined $interfaces{$curif}); if( $arg =~ /[1y]/i ) { $interfaces{$curif}{incompact} = 2; } else { $interfaces{$curif}{incompact} = 0; } next; } if( $buf =~ /^\s*Background\[(.+?)\]\s*:\s*(#[a-f\d]+)/i ) { next if(!defined $interfaces{$1}); $interfaces{$1}{background} = $2; next; } if( $buf =~ /^\s*Timezone\[(.+?)\]\s*:\s*(\S.*)/i ) { next if(!defined $interfaces{$1}); $interfaces{$1}{timezone} = $2; next; } if( $buf =~ /^\s*Directory\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $arg = $2; next if(!defined $interfaces{$curif}); $arg =~ s/[\s\\\/]+$//; # trim trailing spaces and path separators! $interfaces{$curif}{rrd} = $workdir.$pathsep.$arg.$pathsep.(lc $curif).".rrd"; $interfaces{$curif}{directory} = $arg; next; } if( $buf =~ /^\s*Logdir\s*:\s*(\S+)/i ) { $logdir = $1; $logdir =~ s/[\\\/]+$//; $workdir = $logdir; next; } if( $buf =~ /^\s*Workdir\s*:\s*(\S+)/i and !$logdir ) { $workdir = $1; $workdir =~ s/[\\\/]+$//; next; } if( $buf =~ /^\s*Interval\s*:\s*(\d+)/i ) { $interval = $1; next; } if( $buf =~ /^\s*Include\s*:\s*(\S+)/i ) { $newfile = $1; $newfile = (dirname $cfgfile).$pathsep.$newfile if( $newfile !~ /^([a-zA-Z]:)?[\/\\]/ ); read_cfg_file($newfile,0); next; } if( $buf =~ /^\s*LibAdd\s*:\s*(\S+)/i ) { push @INC, $1; next; } if($buf=~ /^\s*(routers2?\.cgi\*)?MaxBytes(\d)\[(.+?)\]\s*:\s*(\d+)/i ){ $curif = $3; $arg = $4; next if(!defined $interfaces{$curif}); $interfaces{$curif}{"maxbytes$2"} = $arg; $interfaces{$curif}{maxbytes} = $arg if(!$interfaces{$curif}{maxbytes}); next; } # the regexp from hell if( $buf =~ /^\s*(routers2?\.cgi\*)?Colou?rs\[(.+?)\]\s*:\s*[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})/i ) { $curif = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{colours} = [ $3,$4,$5,$6 ]; next; } if( $buf =~ /^\s*routers2?\.cgi\*MBLegend\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $curif = "_$curif" if(!defined $interfaces{$curif}); $interfaces{$curif}{mblegend} = $2; next; } if( $buf =~ /^\s*routers2?\.cgi\*AMLegend\[(.+?)\]\s*:\s*(\S.*)/i ) { $curif = $1; $curif = "_$curif" if(!defined $interfaces{$curif}); $interfaces{$curif}{amlegend} = $2; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?AbsMax\[(.+?)\]\s*:\s*(\d+)/i ) { next if(!defined $interfaces{$2}); $interfaces{$2}{absmaxbytes} = $3; next; } if( $buf =~ /^\s*WeekFormat(\[.+?\])?\s*:\s*%?([UVW])/i ) { # yes I know this is ugly, it is being retrofitted $monthlylabel = "%".$2; next; } if( $buf =~ /^\s*routers2?\.cgi\*GraphStyle\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{graphstyle} = $arg; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?Factor\[(.+?)\]\s*:\s*(-?[\d\.]+)/i ) { $curif = $2; $arg = $3; next if(!defined $interfaces{$curif}); $interfaces{$curif}{factor} = $arg if($arg != 0); next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?Supp?ress?\[(.+?)\]\s*:\s*(\S+)/i ) { $curif = $2; $arg = $3; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{suppress} = $arg; next; } if( $buf =~ /^\s*routers2?\.cgi\*UpperLimit\[(.+?)\]\s*:\s*(\d+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{upperlimit} = $arg; next; } if( $buf =~ /^\s*routers2?\.cgi\*LowerLimit\[(.+?)\]\s*:\s*(\d+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{lowerlimit} = $arg; next; } if( $buf =~ /^\s*(routers2?\.cgi\*)?(Thresh(Max|Min)[IO])\[(.+?)\]\s*:\s*(\d+)(%?)/i ) { $curif = $4; $arg = $5; $argb = $6; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); if( $argb ) { # Its a percentage! # This is ugly. We should really do this afterwards, since if # you have the maxbytes line later it all screws up. if( $interfaces{$curif}{maxbytes} ) { $interfaces{$curif}{(lc $2)} = $interfaces{$curif}{maxbytes} * $arg / 100.0; } else { $interfaces{$curif}{(lc $2)} = $interfaces{'_'}{maxbytes} * $arg / 100.0; } } else { $interfaces{$curif}{(lc $2)} = $arg; } next; } if( $buf =~ /^\s*routers2?\.cgi\*FixUnits?\[(.+?)\]\s*:\s*(\d+)/i ) { $curif = $1; $arg = $2; $curif = "_$curif" if(!defined $interfaces{$curif}); next if(!defined $interfaces{$curif}); $interfaces{$curif}{exponent} = $arg; $interfaces{$curif}{fixunits} = 1; # Implied next; } } $fd->close; # now take the current file defaults foreach $key ( keys %{$interfaces{'_'}} ) { foreach $curif ( @myifs ) { $interfaces{$curif}{$key} = $interfaces{'_'}{$key} if(!defined $interfaces{$curif}{$key}); } } foreach $key ( keys %{$interfaces{'^'}} ) { foreach $curif ( @myifs ) { $interfaces{$curif}{$key} = $interfaces{'^'}{$key}.' '.$interfaces{$curif}{$key}; } } foreach $key ( keys %{$interfaces{'$'}} ) { foreach $curif ( @myifs ) { $interfaces{$curif}{$key} .= ' '.$interfaces{'$'}{$key}; } } # now process the options foreach $curif ( @myifs ) { next if(!$curif); if(defined $interfaces{$curif}{options} ) { foreach $k ( split /[\s,]+/,$interfaces{$curif}{options} ) { if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; } $interfaces{$curif}{noo} = 1 if( $k eq "noo"); $interfaces{$curif}{noi} = 1 if( $k eq "noi"); if( $k eq "bits") { $interfaces{$curif}{bytes} = 0; $interfaces{$curif}{bits} = 1; } if( $k eq "perminute") { $interfaces{$curif}{perminute} = 1 if(!defined $interfaces{$curif}{perhour} and !defined $interfaces{$curif}{perminute}); } if( $k eq "perhour") { $interfaces{$curif}{perhour} = 1 if(!defined $interfaces{$curif}{perhour} and !defined $interfaces{$curif}{perminute}); } if( $k eq "nopercent") { $interfaces{$curif}{percent} = 0 ; # default incompact to NO if target has nopercent set $interfaces{$curif}{incompact} = 0 if($interfaces{$curif}{incompact} == 1); } if( $k eq "dorelpercent") { $interfaces{$curif}{noo} = 1; $interfaces{$curif}{dorelpercent} = 1; $interfaces{$curif}{fixunits} = 1; $interfaces{$curif}{percent} = 0; $interfaces{$curif}{bytes} = 1; $interfaces{$curif}{bits} = 0; $interfaces{$curif}{total} = 0; $interfaces{$curif}{percentile} = 0; $interfaces{$curif}{perminute} = 0; $interfaces{$curif}{perhour} = 0; $interfaces{$curif}{withtotal} = 0; $interfaces{$curif}{noabsmax} = 1; $interfaces{$curif}{nomax} = 0; $interfaces{$curif}{mblegend} = 'Equality'; $interfaces{$curif}{unit} = '%'; $interfaces{$curif}{totunit} = ''; $interfaces{$curif}{ylegend} = 'percentage'; $interfaces{$curif}{mode} = 'relpercent'; } $interfaces{$curif}{integer} = 1 if( $k eq "integer"); } } # if defined options if ( defined $interfaces{$curif}{cgioptions} ) { foreach $k ( split /[\s,]+/,$interfaces{$curif}{cgioptions} ) { $interfaces{$curif}{available} = 1 if( $k eq "available"); $interfaces{$curif}{available} = 0 if( $k eq "noavailable"); $interfaces{$curif}{noo} = 1 if( $k eq "noo"); $interfaces{$curif}{noi} = 1 if( $k eq "noi"); $interfaces{$curif}{noo} = 0 if( $k eq "o"); $interfaces{$curif}{noi} = 0 if( $k eq "i"); $interfaces{$curif}{c2fi} = 1 if( $k eq "c2fi"); $interfaces{$curif}{c2fo} = 1 if( $k eq "c2fo"); # $interfaces{$curif}{mult} = 8 if( $k eq "bits"); # $interfaces{$curif}{mult} = 1 if( $k eq "bytes"); if( $k eq "bytes") { $interfaces{$curif}{bytes} = 1; $interfaces{$curif}{bits} = 0; next; } if( $k eq "bits") { $interfaces{$curif}{bits} = 1; $interfaces{$curif}{bytes} = 0; next; } if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; } if( $k eq "perminute") { $interfaces{$curif}{perminute} = 1 if(!defined $interfaces{$curif}{perhour} and !defined $interfaces{$curif}{perminute}); next; } if( $k eq "perhour") { $interfaces{$curif}{perhour} = 1 if(!defined $interfaces{$curif}{perhour} and !defined $interfaces{$curif}{perminute}); next; } $interfaces{$curif}{isif} = 1 if($k eq "interface"); if( $k eq "ignore") { $interfaces{$curif}{inmenu} = 0 ; $interfaces{$curif}{insummary} = 0 ; $interfaces{$curif}{inout} = 0 ; $interfaces{$curif}{incompact} = 0 ; next; } $interfaces{$curif}{unscaled} = "" if( $k eq "scaled"); if( $k eq "nototal") { if($interfaces{$curif}{usergraph}) { $interfaces{$curif}{withtotal} = 0 ; } else { $interfaces{$curif}{total} = 0 ; } next; } $interfaces{$curif}{percentile} = 0 if( $k eq "nopercentile"); if( $k eq "summary" ) { $interfaces{$curif}{summary} = 1; $interfaces{$curif}{compact} = 0; $interfaces{$curif}{withtotal} = 0; $interfaces{$curif}{withaverage} = 0; $interfaces{$curif}{insummary} = 0 ; $interfaces{$curif}{incompact} = 0 ; next; } if( $k eq "compact" ) { $interfaces{$curif}{summary} = 0; $interfaces{$curif}{compact} = 1; $interfaces{$curif}{withtotal} = 0; $interfaces{$curif}{withaverage} = 0; $interfaces{$curif}{insummary} = 0; $interfaces{$curif}{incompact} = 0; next; } if( $k eq "total") { if($interfaces{$curif}{usergraph}) { $interfaces{$curif}{withtotal} = 1 ; } else { $interfaces{$curif}{total} = 1 ; } next; } if( $k eq "aspercent") { $interfaces{$curif}{aspercent} = 1; $interfaces{$curif}{fixunits} = 1; $interfaces{$curif}{percent} = 0; $interfaces{$curif}{bytes} = 1; $interfaces{$curif}{bits} = 0; $interfaces{$curif}{total} = 0; $interfaces{$curif}{percentile} = 0; $interfaces{$curif}{perminute} = 0; $interfaces{$curif}{perhour} = 0; $interfaces{$curif}{withtotal} = 0; $interfaces{$curif}{noabsmax} = 1; $interfaces{$curif}{mblegend} = ''; $interfaces{$curif}{unit} = '%'; $interfaces{$curif}{totunit} = ''; $interfaces{$curif}{ylegend} = 'percentage'; $interfaces{$curif}{mode} = 'percent'; next; } $interfaces{$curif}{withaverage} = 1 if( $k eq "average"); $interfaces{$curif}{nolegend} = 1 if( $k eq "nolegend"); $interfaces{$curif}{nodetails} = 1 if( $k eq "nodetails"); $interfaces{$curif}{nomax} = 1 if( $k eq "nomax"); $interfaces{$curif}{noabsmax} = 1 if( $k eq "noabsmax"); $interfaces{$curif}{percent} = 0 if( $k eq "nopercent"); $interfaces{$curif}{integer} = 1 if( $k eq "integer"); $interfaces{$curif}{'reverse'} = 1 if( $k eq "reverse"); $interfaces{$curif}{rigid} = 1 if( $k eq "rigid"); if( $k =~ /^#[\da-fA-F]{6}$/ ) { $interfaces{$curif}{colours} = [] if(!defined $interfaces{$curif}{colours}); push @{$interfaces{$curif}{colours}}, $k; next; } $interfaces{$curif}{fixunits} = 1 if( $k =~ /^fixunits?/i or $k =~ /^nounits?/i ); } } # fix the mult if($interfaces{$curif}{bytes}) { $interfaces{$curif}{mult} = 1; } elsif($interfaces{$curif}{bits} ) { $interfaces{$curif}{mult} = 8; } if($interfaces{$curif}{perminute}) { $interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult}); $interfaces{$curif}{mult} *= 60; } elsif($interfaces{$curif}{perhour}) { $interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult}); $interfaces{$curif}{mult} *= 3600; } # sanity check if( $interfaces{$curif}{incompact} and !$interfaces{$curif}{maxbytes}){ $interfaces{$curif}{incompact} = 0; } # calculate RRD filename if(!$interfaces{$curif}{usergraph}) { $rrd = $workdir; $rrd .= $pathsep.$interfaces{$curif}{directory} if($interfaces{$curif}{directory}); $rrd .= $pathsep.lc($interfaces{$curif}{target}).".rrd"; $interfaces{$curif}{rrd} = $rrd; } } # now read the corresponding .ok file, if it exists $cfgfile =~ s/\.conf$/.ok/; $cfgfile =~ s/\.cfg$/.ok/; if( open OK, "<$cfgfile" ) { my( %ifdesc ) = (); my( %ifip ) = (); while( ) { if( /\tDescr\t(.+)\t(\d+)/ ) { $ifdesc{$2} = $1; $ifdesc{$1} = $2; } if( /\tIp\t(.+)\t(\d+)/ ) { $ifip{$2} = $1; $ifip{$1} = $2; } } close OK; foreach $curif ( @myifs ) { if(!defined $interfaces{$curif}{ifno}) { $interfaces{$curif}{ifno} = $ifdesc{$interfaces{$curif}{ifdesc}} if(defined $interfaces{$curif}{ifdesc} and defined $ifdesc{$interfaces{$curif}{ifdesc}}); $interfaces{$curif}{ifno} = $ifip{$interfaces{$curif}{ipaddress}} if(defined $interfaces{$curif}{ipaddress} and defined $ifip{$interfaces{$curif}{ipaddress}}); } if(defined $interfaces{$curif}{ifno}) { $key = $interfaces{$curif}{ifno}; $interfaces{$curif}{ifdesc} = $ifdesc{$key} if(defined $ifdesc{$key} and !defined $interfaces{$curif}{ifdesc}); $interfaces{$curif}{ipaddress} = $ifip{$key} if(defined $ifip{$key} and !defined $interfaces{$curif}{ipaddress}); } } } # ok file exists # Creation of special interfaces moved to read_cfg } sub read_cfg() { my($cfgfile) = $_[0]; my($l,$key,$k); my($ifcnt,$curif,@ifarr); $cfgfile = $routers{$router}{file} if(!$cfgfile and $router and defined $routers{$router}); $cfgfile = $config{'routers.cgi-confpath'}.$pathsep.$router if(!$cfgfile and $router); return if (!$cfgfile); # now, have we done $cfgfile before? if( $CACHE and defined $ifstore{$cfgfile} ) { # yes! %interfaces = %{$ifstore{$cfgfile}}; $routers{$router}{extensions} = [@{$ifstore{"R:$cfgfile"}}] if(defined $ifstore{"R:$cfgfile"}); $debugmessage .= "cache($cfgfile)\n"; return; } %interfaces = ( '_'=>{x=>0}, '^'=>{x=>0}, '$'=>{x=>0} ); $interval = 5; $workdir = $config{'routers.cgi-dbpath'}; read_cfg_file($cfgfile,1); # recursive # zap defaults delete $interfaces{'_'}; delete $interfaces{'$'}; delete $interfaces{'^'}; delete $interfaces{''} if(defined $interfaces{''}); # now set up userdefined graphs for Incoming and Outgoing, if it is # necessary. $ifcnt = 0; @ifarr = (); $curif=""; foreach ( keys %interfaces ) { $curif = $_ if(!$curif and $interfaces{$_}{community} and $interfaces{$_}{hostname} ); if($interfaces{$_}{inout}) { $ifcnt++; push @ifarr, $_; } } $debugmessage .= "ifcnt=$ifcnt \n"; if($ifcnt) { my($t); $t = ""; $t = $routers{$router}{shdesc}.": " if($router and defined $routers{$router} and defined $routers{$router}{shdesc}); if( defined $interfaces{'_incoming'} ) { push @{$interfaces{'_incoming'}{targets}},@ifarr if( $interfaces{'_incoming'}{mode} =~ /_AUTO/ ); } else { $interfaces{'_incoming'} = { usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, shdesc=>langmsg(2405,"Incoming"), targets=>[@ifarr], noo=>1, mult=>8, icon=>"incoming-sm.gif", mode=>"\177_AUTO", desc=>$t.langmsg(2414,"Incoming traffic"), withtotal=>0, withaverage=>0, issummary=>0 }; if(defined $config{'routers.cgi-showtotal'} and $config{'routers.cgi-showtotal'}=~ /y/i ) { $interfaces{'_incoming'}{withtotal} = 1; } } if( defined $interfaces{'_outgoing'} ) { push @{$interfaces{'_outgoing'}{targets}},@ifarr if( $interfaces{'_outgoing'}{mode} =~ /_AUTO/ ); } else { $interfaces{'_outgoing'} = { usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, shdesc=>langmsg(2406,"Outgoing"), targets=>[@ifarr], noi=>1, mult=>8, icon=>"outgoing-sm.gif", mode=>"\177_AUTO", desc=>$t.langmsg(2415,"Outgoing traffic"), withtotal=>0, withaverage=>0, issummary=>0 }; if(defined $config{'routers.cgi-showtotal'} and $config{'routers.cgi-showtotal'}=~ /[1y]/i ) { $interfaces{'_outgoing'}{withtotal} = 1; } } } # Now set up default userdefined summary, if anything is insummary @ifarr = (); foreach ( keys %interfaces ) { push @ifarr, $_ if($interfaces{$_}{insummary}); # first pass for interfaces identify $_ if(!$interfaces{$_}{usergraph}); } if(@ifarr) { if( defined $interfaces{'_summary_'} ) { push @{$interfaces{'_summary_'}{targets}},@ifarr if( $interfaces{'_summary_'}{mode} =~ /_AUTOSUMMARY/ ); } else { $interfaces{'_summary_'} = { usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, shdesc=>langmsg(2416,"Summary"), targets=>[@ifarr], noo=>1, mult=>8, icon=>"summary-sm.gif", mode=>"\177_AUTOSUMMARY", withtotal=>0, withaverage=>0, issummary=>1 }; } } # Can we call out to the routingtable.cgi program? if( defined $config{'routers.cgi-routingtableurl'} and $curif and ( !defined $routers{$router}{routingtable} or $routers{$router}{routingtable} =~ /[1y]/i )) { $routers{$router}{extensions} = [] if( !defined $routers{$router}{extensions} ); push @{$routers{$router}{extensions}}, { url=>$config{'routers.cgi-routingtableurl'}, desc=>langmsg(2417,"Routing Table"), icon=>"router-sm.gif", community=>$interfaces{$curif}{community}, hostname=>$interfaces{$curif}{hostname}, level=>0, insecure=>1 }; } # second pass for user graphs foreach $key ( keys %interfaces ) { if($interfaces{$key}{usergraph}) { $k = $key; $k=~ s/^_//; # chop off initial _ prefix $interfaces{$key}{shdesc} = $config{"targetnames-$k"} if(defined $config{"targetnames-$k"}); $interfaces{$key}{desc} = $config{"targettitles-$k"} if(defined $config{"targettitles-$k"}); $interfaces{$key}{icon} = $config{"targeticons-$k"} if(defined $config{"targeticons-$k"}); foreach $k ( keys %{$interfaces{$interfaces{$key}{targets}->[0]}} ) { $interfaces{$key}{$k} = $interfaces{$interfaces{$key}{targets}->[0]}{$k} if(($k ne 'extensions') and !defined $interfaces{$key}{$k}); } } else { # Can we call out to the trend.cgi program? (undocumented) if( defined $config{'routers.cgi-trendurl'} and !$interfaces{$key}{usergraph} ) { $interfaces{$key}{extensions} = [] if(!defined $interfaces{$key}{extensions}); push @{$interfaces{$key}{extensions}}, { url=>$config{'routers.cgi-trendurl'}, desc=>langmsg(2418,"Trend Analysis"), icon=>"graph-sm.gif", target=>"graph", level=>0, insecure=>0 }; } } } # at this point, %interfaces is set up. if($CACHE) { # cache it $ifstore{$cfgfile} = { %interfaces }; $debugmessage .= "cached[$cfgfile] "; if(defined $routers{$router}{extensions}) { $ifstore{"R:$cfgfile"} = [ @{$routers{$router}{extensions}} ]; $debugmessage .= "cached[$cfgfile:X] "; } if( $archdate ) { # clean up mess before caching foreach my $tmpif ( keys %interfaces ) { $ifstore{$cfgfile}{$tmpif}{rrd} = $ifstore{$cfgfile}{$tmpif}{origrrd} if($ifstore{$cfgfile}{$tmpif}{origrrd}); } } } else { $debugmessage .= "NOCACHE"; } } ############################################################################# # reformat to look nice # params -- number, fix flag, integer flag sub doformat($$$) { my( $sufx ) = ""; my( $val, $fix, $intf ) = @_; return "???" if(!defined $val or $val !~ /\d/ ); return $val if( $val == 0 ); if(!$fix) { if( $val >= $G ) { $val /= $G; $sufx = "G"; } elsif( $val >= $M ) { $val /= $M; $sufx = "M"; } elsif( $val >= $k ) { $val /= $k; $sufx = $ksym; } } return sprintf "%.0f %s",$val,$sufx if( $intf or ( int($val*100) == (100*int($val)) ) ); return sprintf "%.2f %s",$val,$sufx; } # Round the number to a set no of decimal places sub dp($$) { my($num,$dcp) =@_; my($rv); return '0' if(!$num); $rv = sprintf '%.'.$dcp.'f',$num; $rv =~ s/\.0+$//; # remove trailing .0 return $rv; } ################################# # Calculate nth percentile (bits), and total bandwidth (bits), for current rrd # and for specified interval (d,w,m,y) # Returns ( desc, [inpercentile,intotal,emsg], [outpercentile,outtotal,emsg] ) sub calc_percentile($$$) { my( $thisif, $pcinterval, $percentile ) = @_; # interface, dwmy, 95 my( @rv, $e, @opts ); my( $rrd, $ds ); my( $resolution, $startpoint, $desc ); # fetch input values my( $datastart, $datastep, $dsnames, $dsdata ); # fetch return values my( $pc, $row, $totalbits, @pcarray, $idx, $pcidx ); return ("",["-","-","No interface"],["-","-",""]) if(!$thisif); # just in case $rrd = $interfaces{$thisif}{rrd}; foreach ( $pcinterval ) { /y/ and do { $resolution = 3600; $startpoint = "-1y"; $desc = langmsg(2420,"rolling last year"); last; }; /m/ and do { $resolution = 1800; $startpoint = "-1month"; $desc = langmsg(2421,"rolling last month"); last; }; /w/ and do { $resolution = 300; $startpoint = "-7d"; $desc = langmsg(2422,"last 7 days"); last; }; /6/ and do { $resolution = 60*$interfaces{$thisif}{interval}; $desc = langmsg(2423,"last 6 hours"); $startpoint = "-6h"; last; }; $resolution = 60*$interfaces{$thisif}{interval}; # interval $startpoint = "-24h"; # 1 day $desc = langmsg(2424,"last 24 hours"); } $desc =~ s/last/previous/ if($pcinterval =~ /-/); $resolution = 300 if(!$resolution); push @rv, $desc; # fetch the data eval { require 'RRDs.pm'; }; if( $@ ) { return ("", ["-","-","No RRDs.pm"],["-","-",""]) ; } if( $pcinterval =~ /-/ ) { @opts = ( $rrd,"AVERAGE","-e","now$startpoint","-s","end$startpoint" ); } elsif( $uselastupdate ) { @opts = ( $rrd,"AVERAGE","-e",$lastupdate,"-s","end$startpoint" ); } else { @opts = ( $rrd, "AVERAGE", "-s", $startpoint ); } ( $datastart, $datastep, $dsnames, $dsdata ) = RRDs::fetch( @opts ); $e = RRDs::error(); if ( $e ) { @rv = ("",["?","?",$e], ["?","?","fetch ".(join " ",@opts)]); return @rv; } # now we do two calculations: the total traffic ( $datastep*sum(value) ) # for both in and out, and the percentile (95% into sorted array ) foreach $idx ( 0..1 ) { $totalbits = 0; @pcarray = (); foreach $row ( @$dsdata ) { # ???? Is this correctly skipping UNKN values? # This needs to be checked, we should avoid UNKN in %ile next if(!defined $row->[$idx]); if( $row->[$idx] =~ /\d/ ) { # $totalbits += $row->[$idx]*$interfaces{$thisif}{mult}*$datastep; # We no longer multiply by {mult} since we DO NOT want to multiple for # permin/perhour totals (datastep takes care of that) and we want bits to # be totalled in bytes. $totalbits += $row->[$idx]*$datastep; push @pcarray, ( $row->[$idx] * $interfaces{$thisif}{mult} ); } } @pcarray = sort numerically @pcarray if($#pcarray>0); $pcidx = int($#pcarray * $percentile / 100); # Now, at this point, if $thisif is a RANGE, we should do percentile and # 100-percentile , ie, the opposite for the 'from'. if( $idx and $interfaces{$thisif} and $interfaces{$thisif}{graphstyle} and $interfaces{$thisif}{graphstyle} eq "range" ) { $pcidx = int($#pcarray * (100-$percentile) / 100); } $pc = $pcarray[$pcidx]; # multiply by the factor : we did the mult previously $pc *= $interfaces{$thisif}{factor} if($interfaces{$thisif}{factor}); $totalbits *= $interfaces{$thisif}{factor} if($interfaces{$thisif}{factor}); push @rv, [ $pc, $totalbits, "" ]; # push @rv, [ $pc, $totalbits, $$dsnames[$idx]." $idx: 0=[".$pcarray[0] # ."] $#pcarray=[".$pcarray[$#pcarray]."] , i=$pcidx, st=$datastep, s=" # .localtime($datastart).", e=".localtime($datastart+($datastep*$#pcarray))]; } return @rv; } ################################# # Top menu sub do_head() { my($iconsuffix) = ""; my($loginbuttons) = ""; my($colwid) = 115; my($logo); $iconsuffix = "-bw" if( $gstyle =~ /b/ ); start_html_ss({ -bgcolor => $menubgcolour, -text => $menufgcolour }); if( $config{'web-auth-required'} =~ /^[yo]/i ) { if( $authuser ) { $loginbuttons = $q->td({ -align=>"LEFT", -width=>1, -valign=>"TOP" }, $q->a({href=>"$meurl?page=logout", target=>'_top'}, $q->img({src=>"${config{'routers.cgi-iconurl'}}logout$iconsuffix.gif", alt=>langmsg(5000,"Logout"), border=>"0", width=>100, height=>20})) .$q->br.langmsg(1002,"User").": ".$q->small($authuser)); } else { $loginbuttons = $q->td({ -align=>"LEFT", -width=>1, -valign=>"TOP" }, $q->a({href=>"$meurl?page=login", target=>'_top'}, $q->img({src=>"${config{'routers.cgi-iconurl'}}login$iconsuffix.gif", alt=>langmsg(5001,"Login"), border=>"0", width=>100, height=>20})) ); } $colwid = 225; } # Page top logo, may be overridden if($config{'routers.cgi-logourl'}) { $logo = $q->img({ src=>$config{'routers.cgi-logourl'}, border=>0}); } else { $logo = $q->a( { href=>$APPURL, target=>"_new" } , $q->img({ src=>($config{'routers.cgi-smalliconurl'}."routers2.gif"), alt=>"Routers2.cgi", border=>0, width=>120, height=>40 })); } print "\n".$q->table( { -border=>"0", -width=>"100%", cellspacing=>0, cellpadding=>1 }, $q->Tr( { -valign=>"TOP", -width=>"100%" }, "\n". $q->td({ -align=>"LEFT", -width=>$colwid, -valign=>"TOP" }, ($config{'web-backurl'}?( "
". $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." ". $q->a({ href=>$config{'web-backurl'}, target=>"_top"}, $q->img({ src=>"${config{'routers.cgi-iconurl'}}mainmenu$iconsuffix.gif", alt=>langmsg(5002,"Main Menu"), border=>0, width=>100, height=>20 }))."
"."\n" ):"")."
" .$q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." " .$q->a({href=>"javascript:parent.graph.location.reload(true)"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh$iconsuffix.gif",alt=>langmsg(5003,"Refresh"), border=>"0", width=>100, height=>20}))."
" )."\n" .$loginbuttons .$q->td({ -align=>"CENTER", -valign=>"TOP" }, $toptitle)."\n" .$q->td({ -align=>"RIGHT", -width=>1, -valign=>"TOP" }, $logo)."\n" ) ),"\n"; # Finish off the page print $q->end_html(); } ########################### # Side menu # $mtype specified 'routers' (list routers) or 'options' (list options) sub do_menu() { my ($iflabel); my ($target) = "graph"; my ($rtrdesc,$gs,$adesc); my ($iconsuffix) = ""; my ($groupdesc, $lastgroup, $thisgroup); #my ($hassummary) = 0; my ($hascompact) = 0; my ($explore) = "y"; my (@archive) = (); my ($archivepat); my ($timeframe); my ($lurl); # link URL my ($menulevel) = 0; my ($multilevel) = 0; $multilevel = 1 if( defined $config{'routers.cgi-multilevel'} and $config{'routers.cgi-multilevel'}=~/[y1]/i ); # explore will contain either y, n, or i $explore = $config{'routers.cgi-allowexplore'} if( defined $config{'routers.cgi-allowexplore'} ); $mtype = "options" if( $explore !~ /y/i ); $iconsuffix = "-bw" if( $gstyle =~ /b/ ); $target = "_top" if( $gstyle =~ /p/ ); # Start it off start_html_ss({ -bgcolor => $menubgcolour, -text => $menufgcolour, nowrap => "yes"}); print "
\n"; # top link for other stuff #if( $mtype eq "options" or !$router or $router eq "none" # or $router eq "__none" or $interface eq "__none" ) { # print $q->a({name=>"top"},""); #} print "\n" if( defined $config{'routers.cgi-menufontsize'} ); # Main stuff and links if ( $mtype eq "options" ) { # check for inout graphs foreach ( keys %interfaces ) { # if( $interfaces{$_}{insummary} ) { $hassummary = 1; } if( $interfaces{$_}{incompact} ) { $hascompact = 1; } } # check for archive if( defined $config{'routers.cgi-archive'} and $config{'routers.cgi-archive'} !~ /^n/i ) { $archivepat = $router; $archivepat =~ s/[\?#\\\/]//g; $archivepat = $config{'routers.cgi-graphpath'}.$pathsep .$archivepat.$pathsep.$interface.$pathsep."*.*"; # do this in an eval because some Perl implementations treat a null # glob as an error (why??) eval { @archive = glob($archivepat); }; } # now show it all if( !$twinmenu ) { print "" .$q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." " .$q->a({ href=>"$meurl?".optionstring( { page=>"menu",xmtype=>"routers" }), target=>"_self", onMouseOver=>"if(devices){devices.src='${config{'routers.cgi-iconurl'}}devices-dn-w.gif'; window.status='Show list of routers';}", onmouseout=>"if(devices){devices.src='${config{'routers.cgi-iconurl'}}devices-dn$iconsuffix.gif'; window.status='';}" }, $q->img({ src=>"${config{'routers.cgi-iconurl'}}devices-dn$iconsuffix.gif", alt=>langmsg(5004,"Devices"), border=>0 , name=>"devices", width=>100, height=>20}))."\n".$q->br."\n" if( $explore =~ /y/i ); } # list options if( $explore !~ /n/i and $router ne "none") { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." " .$q->img({ src=>"${config{'routers.cgi-iconurl'}}targets$iconsuffix.gif", alt=>langmsg(5005,"Targets"),width=>100, height=>20 }) ."".$q->br."\n"; foreach ( sort byifdesc keys( %interfaces ) ) { next if(!$_); # avoid the '#' interface... next if(!$interfaces{$_}{inmenu}); # if not in menu... $iflabel = $interfaces{$_}{shdesc} if(defined $interfaces{$_}{shdesc}); $iflabel = "#$_" unless ( $iflabel ); $iflabel =~ s/ /\ /g; # get rid of spaces... print ""; if( $_ eq $interface ) { my(@k) = (keys %interfaces); print $q->a({name=>"top"},"") if($#k>25); } if( $interfaces{$_}{icon} ) { print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$interfaces{$_}{icon}), width=>15, height=>15, alt=>$interfaces{$_}{desc} })," "; } elsif( $interfaces{$_}{isif} ) { print $q->img({ src=>($config{'routers.cgi-smalliconurl'}."interface-sm.gif"), width=>15, height=>15, alt=>$interfaces{$_}{desc} })," "; } else { print $q->img({ src=>($config{'routers.cgi-smalliconurl'}."target-sm.gif"), width=>15, height=>15, alt=>$interfaces{$_}{desc} })," "; } if ( $interface eq $_ ) { print $q->b($iflabel); } else { if( $gstyle =~ /p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main", if=>"$_" }), target=>"_top" }, $iflabel ); } else { print $q->a({ href=>"$meurl?".optionstring( { if=>"$_" }), target=>"graph" }, $iflabel ); } } print "".$q->br."\n"; } # special targets - summary, compact, info, userdefined if( $router ne "none" and $router ne "__none" ) { if($hascompact) { if( ! defined $config{'routers.cgi-compact'} or $config{'routers.cgi-compact'} !~ /n/i ) { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}compact-sm.gif", width=>15, height=>15 })," "; if( $interface eq "__compact" ) { print $q->b(langhtml(2000,"Compact summary")); } else { if( $gstyle =~ /p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main", if=>"__compact" }), target=>"_top" }, langhtml(2000,"Compact summary")); } else { print $q->a({ href=>"$meurl?".optionstring( { if=>"__compact" }), target=>"graph" }, langhtml(2000,"Compact summary")); } } print "".$q->br."\n"; } # compact option } # hascompact if( $router !~ /^#/ ) { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}menu-sm.gif", width=>15, height=>15 })," "; if( $interface eq "__info" ) { print $q->b(langhtml(2001,"Information")),$q->br,"\n"; } else { if( $gstyle =~ /p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main",if=>"__info"}), target=>"_top"}, langhtml(2001,"Information")),$q->br,"\n"; } else { print $q->a({ href=>"$meurl?".optionstring( { if=>"__info" }), target=>"graph" }, langhtml(2001,"Information")),$q->br,"\n"; } } } # not system special #SERVER# # any userdefined's for this router? if ( defined $routers{$router}{extensions} ) { my( $u, $ext, $targ ); foreach $ext ( @{$routers{$router}{extensions}} ) { if($seclevel<$ext->{level}) { # print $ext->{desc}." (".$ext->{level}.")".$q->br."\n"; next; } $targ = "graph"; $targ = $ext->{target} if( defined $ext->{target} ); $u = $ext->{url}; if(!$ext->{noopts}) { $u .= "?x=1" if( $u !~ /\?/ ); $u .= "&fi=".$q->escape($router) ."&url=".$q->escape($q->url()); $u .= "&t=".$q->escape($targ); $u .= "&L=".$seclevel; $u .= "&r=".$q->escape($ext->{hostname}) ."&h=".$q->escape($ext->{hostname}) if(defined $ext->{hostname}); $u .= "&c=".$q->escape($ext->{community}) if(defined $ext->{community} and $ext->{insecure}); $u .= "&b=".$q->escape("javascript:history.back();history.back()") ."&conf=".$q->escape($conffile); } print "".$q->img({ src=>(${config{'routers.cgi-smalliconurl'}} .$ext->{icon}), width=>15, height=>15 })," "; print $q->a({ href=>$u, target=>$targ }, $ext->{desc} )."".$q->br."\n"; } } # extensions defined } # not 'none' router print $q->br; } # explore print "\n"; if( !$archive and $interface ne "__none" and $interface ne "__info" ) { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->img({ src=>"${config{'routers.cgi-iconurl'}}graphs$iconsuffix.gif", alt=>langmsg(5006,"Graphs"), width=>100, height=>20 })."". $q->br."\n"; # First we list all the archived RRD files, if available. my($archroot) = ''; if($interface and defined $interfaces{$interface}) { if($interfaces{$interface}{origrrd}) { $archroot = dirname($interfaces{$interface}{origrrd}) .$pathsep.'archive'; } elsif($interfaces{$interface}{rrd}) { $archroot = dirname($interfaces{$interface}{rrd}) .$pathsep.'archive'; } } if( -d $archroot ) { # An archive exists! my($rrdfilename); if(defined $interfaces{$interface}{origrrd}) { $rrdfilename = basename($interfaces{$interface}{origrrd}); } else { $rrdfilename = basename($interfaces{$interface}{rrd}); } my(@days) = ( '0' ); my(%descs); $descs{0} = langmsg(5007,'Live data'); # caching code for speedycgi people if( defined $cachedays{$rrdfilename} ) { @days = @{$cachedays{$rrdfilename}}; # If we get the list from the cache, we still need to build descs foreach ( @days ) { if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { $descs{$_} = "$4/$3/$2"; # Should call function for this } } } else { # Maybe find a better way to do this -- glob is SLOW # foreach ( sort rev glob( $archroot.$pathsep."*".$pathsep.$rrdfilename ) ) { # if( /[\\\/](\d\d)(\d\d)-(\d\d)-(\d\d)[\\\/]/ ) { foreach ( sort rev findarch( $archroot,$rrdfilename ) ) { if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { push @days, "$1$2-$3-$4"; $descs{"$1$2-$3-$4"} = "$4/$3/$2"; # Should call function } } $cachedays{$rrdfilename} = [ @days ]; # Cache for later } if( $#days > 0 ) { print "
"; print "
"; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}calendar-sm.gif", width=>15, height=>15 })," "; # spacer my($curd) = $q->param('arch'); $curd = '0' if(!$curd); print $q->popup_menu( -name=>"arch", -values=>\@days, -default=>$curd, -labels=>\%descs, -onChange=>'archform.submit();' ); print $q->hidden(-name=>'rtr', -default=>"$router", -override=>1); print $q->hidden(-name=>'if', -default=>"$interface", -override=>1); print $q->hidden(-name=>'page', -default=>'graph', -override=>1); print $q->hidden(-name=>'xpage', -default=>'graph', -override=>1); # grr print $q->hidden(-name=>'xgtype', -default=>"$gtype", -override=>1); print $q->hidden(-name=>'xgstyle', -default=>"$gstyle", -override=>1); print $q->hidden(-name=>'xgopts', -default=>"$gopts", -override=>1); print $q->hidden(-name=>'bars', -default=>"$baropts", -override=>1); print $q->hidden(-name=>'extra', -default=>"$extra", -override=>1); print $q->hidden(-name=>'uopts', -default=>"$uopts", -override=>1); print "
\n"; print "
"; } else { print ""; } } else { print "\n"; } # Now all the different daily/weekly/etc graph types foreach ( @gorder ) { if( defined $interfaces{$interface} and defined $interfaces{$interface}{suppress} ) { $timeframe = $_; $timeframe =~ s/-//g; next if( $interfaces{$interface}{suppress} =~ /$timeframe/ ); } print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}clock-sm.gif", width=>15, height=>15 })," "; if($gtype eq $_) { print $q->b($gtypes{$_}),$q->br,"\n"; } elsif((($interface eq "__compact") and (length > 2 )) or ( $router eq "none" )) { print $gtypes{$_},$q->br,"\n"; } else { if( $gstyle =~ /p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main", xgtype=>"$_" }), target=>"_top" }, $gtypes{$_} ), $q->br,"\n"; } else { print $q->a({ href=>"$meurl?".optionstring( { xgtype=>"$_" }), target=>"graph" }, $gtypes{$_} ),$q->br,"\n"; } } } print $q->br; } # ! viewing archive print "\n"; if( @archive ) { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->img({ src=>"${config{'routers.cgi-iconurl'}}archive-h$iconsuffix.gif", alt=>langmsg(5008,"Archive"), width=>100, height=>20 }),"".$q->br."\n"; if($archive) { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}graph-sm.gif", width=>15, height=>15 })," "; $adesc = langhtml(5007,"Live graph"); if( $gstyle=~/p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main" }), target=>"_top" }, $adesc ); } else { print $q->a({ href=>"$meurl?".optionstring( { page=>"graph" }), target=>"graph" }, $adesc ); } print "".$q->br."\n"; } foreach ( sort @archive ) { if(/(\d+)-(\d+)-(\d+)-(\d+)-(\d+)-(\S+)\.(gif|png)$/) { # try to get local formatting # $adesc = "$4:$5 $3/$2/$1 (".$gtypes{$6}.")"; my( $dformat ) = "%c"; $dformat = $config{'web-shortdateformat'} if(defined $config{'web-shortdateformat'}); eval { require POSIX; }; if($@) { $adesc = "$4:$5 $3/$2/$1 (".$gtypes{$6}.")"; } else { $adesc = POSIX::strftime($dformat, 0,$5,$4,$3,($2-1),($1-1900))." (".$gtypes{$6}.")"; $adesc =~ s/ /\ /g; } print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}graph-sm.gif", width=>15, height=>15 })," "; if( $gstyle=~/p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main", archive=>(basename $_), xgtype=>"$6"}), target=>"_top" }, $adesc ); } else { print $q->a({ href=>"$meurl?".optionstring( { page=>"graph", archive=>(basename $_), xgtype=>"$6"}), target=>"graph" }, $adesc ); } print "".$q->br."\n"; } else { print "\n"; } } print $q->br."\n"; } if( !$archive and $interface ne "__none" and $interface ne "__info" ) { print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->img({ src=>"${config{'routers.cgi-iconurl'}}styles$iconsuffix.gif", alt=>langmsg(5009,"Styles"), width=>100, height=>20 })."".$q->br."\n"; foreach ( @sorder ) { next if (!defined $gstyles{$_}); print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}pbrush-sm.gif", width=>15, height=>15 })," "; $gs = $gstyles{$_}; $gs =~ s/ /\ /g; if($gstyle eq $_) { print $q->b($gs); } elsif( $router eq "none" ) { print $gs; } else { # PDAs cant be relied on to have javascript support if( /p/ ) { print $q->a({ href=>"$meurl?".optionstring( { page=>"main", xgstyle=>"$_"}), target=>"_top" }, $gs ); } else { print $q->a({ href=>"$meurl?".optionstring( { xgstyle=>"$_"}), target=>"graph" }, $gs ); } } print "".$q->br."\n"; } print $q->br; } # ! archive viewing print ""; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->img({ src=>"${config{'routers.cgi-iconurl'}}otherstuff$iconsuffix.gif", alt=>langmsg(5010,"Other Stuff"), width=>100, height=>20 })."". $q->br."\n"; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}prefs-sm.gif", width=>15, height=>15 })," "; print $q->a({href=>"$meurl?".optionstring( { page=>"config" }) , target=>"graph"}, langmsg(5011,"Preferences")),$q->br,"\n"; print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}info-sm.gif" })," "; print $q->a({href=>"$meurl?".optionstring({page=>"help"}), target=>"graph"}, langmsg(5012,"Information")),$q->br,"\n"; # print $q->img({ src=>"${config{'routers.cgi-iconurl'}}error-sm.gif" })," "; # print $q->a({href=>("$meurl?page=verify&rtr=" # .$q->escape($router)),target=>"_new"},"Configuration check") # .$q->br."\n"; # twin menu print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}menu-sm.gif" }), " "; if( $twinmenu ) { $uopts=~ s/[tT]//g; $uopts .= "T"; print $q->a({ href=>"$meurl?".optionstring({ page=>"main"}), target=>"_top" },langhtml(5013,"Close second menu") ) } else { $uopts=~ s/[tT]//g; $uopts .= "t"; print $q->a({ href=>"$meurl?".optionstring({page=>"main"}), target=>"_top" }, langhtml(5014,"Twin menu view") ) } print $q->br."\n"; } else { # Devices (Routers) menu list # if( ! $twinmenu ) { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->a({ href=>"$meurl?".optionstring( { page=>"menu", xmtype=>"options" }), target=>"_self" , onMouseOver=>"if(options){options.src='${config{'routers.cgi-iconurl'}}options-dn-w.gif'; window.status='Show display options';}", onmouseout=>"if(options){options.src='${config{'routers.cgi-iconurl'}}options-dn$iconsuffix.gif'; window.status='';}" }, $q->img({ src=>"${config{'routers.cgi-iconurl'}}options-dn$iconsuffix.gif", alt=>langmsg(5015,"Options"), border=>0, name=>"options", height=>20, width=>100 }))."\n".$q->br."\n"; } # list devices print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", border=>0, width=>15, height=>15})." "; print $q->img({ src=>"${config{'routers.cgi-iconurl'}}devices$iconsuffix.gif", alt=>langmsg(5004,"Devices"), height=>20, width=>100 }), $q->br,"\n"; # The 'Find' box if( !defined $config{'routers.cgi-showfindbox'} or $config{'routers.cgi-showfindbox'} =~ /[Yy1]/ ) { print "
"; print $q->img({src=>"${config{'routers.cgi-smalliconurl'}}search-sm.gif", border=>0, width=>15, height=>15})." "; print $q->textfield({-name=>'searchhost', -value=>langmsg(5004,"Device"), -size=>9}); print $q->hidden(-name=>'page', -default=>"graph", -override=>1); print $q->hidden(-name=>'xgtype', -default=>"$gtype", -override=>1); print $q->hidden(-name=>'xgstyle', -default=>"$gstyle", -override=>1); print $q->hidden(-name=>'xgopts', -default=>"$gopts", -override=>1); print $q->hidden(-name=>'bars', -default=>"$baropts", -override=>1); print $q->hidden(-name=>'extra', -default=>"$extra", -override=>1); print $q->hidden(-name=>'uopts', -default=>"$uopts", -override=>1); print $q->submit({ name=>"search", value=>"?" }); print "

\n"; } # grouping $grouping = 1 if( defined $config{'routers.cgi-group'} and $config{'routers.cgi-group'} =~ /[Yy1]/ ); if($grouping) { $group=$lastgroup=""; $group=$routers{$router}{group} if(defined $routers{$router}); } my($lastgroupdesc,$activegroupdesc); if($multilevel) { if( defined $config{"targetnames-$group"} ) { $activegroupdesc = $config{"targetnames-$group"}; } elsif( defined $config{("targetnames-".(lc $group))} ) { $activegroupdesc = $config{("targetnames-".(lc $group))}; } else { $activegroupdesc = basename( $group,'' ).$pathsep; } } foreach ( sort byshdesc keys(%routers) ) { next if(!$routers{$_}{inmenu}); if( $grouping ) { $thisgroup = $routers{$_}{group}; if( $thisgroup ne $lastgroup ) { my(@grps); if( defined $config{"targetnames-$thisgroup"} ) { $groupdesc = $config{"targetnames-$thisgroup"}; } elsif( defined $config{("targetnames-".(lc $thisgroup))} ) { $groupdesc = $config{("targetnames-".(lc $thisgroup))}; } else { $groupdesc = basename( $thisgroup,'' ).$pathsep; } if($multilevel) { @grps = getgroups($activegroupdesc,$groupdesc,$lastgroupdesc); } else { @grps = ( [ $groupdesc,1,(($thisgroup eq $group)?1:0) ] ); } foreach my $gg ( @grps ) { print ""; $menulevel = $gg->[1]; print "  " # print $q->img({ # src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", # border=>0, width=>15, height=>15}) x $menulevel if($menulevel); if( $gg->[2] ) { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}g-sm.gif", width=>15, height=>15, alt=>$gg->[0] })," "; print $q->b($gg->[0]); } else { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}plus-sm.gif", width=>15, height=>15, alt=>$gg->[0] })," "; $lurl = $meurl; $lurl = $routers{$_}{redirect} if(defined $routers{$_}{redirect}); if( $gstyle =~ /p/ ) { print $q->a({href=>"$lurl?" .optionstring({page=>"main",if=>"",rtr=>"$_"}), target=>"_top" },$q->b($gg->[0]) ); } else { print $q->a({ href=>"$lurl?" .optionstring({ rtr=>"$_", if=>"" }), target=>"graph" },$q->b($gg->[0]) ); } } print "".$q->br."\n"; } # foreach $lastgroup = $thisgroup; $lastgroupdesc = $groupdesc; } # if in new group next if( $thisgroup ne $group ); } # if grouping $rtrdesc = $routers{$_}{shdesc}; $rtrdesc = $_ if(! $rtrdesc ); $rtrdesc =~ s/ /\ \;/g; # stop breaking of line on spaces print ""; # print ($q->img({ # src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", # border=>0, width=>15, height=>15}) print ( "  " x $menulevel) if($grouping); print "  " if($grouping); if( $_ eq $router ) { print $q->a({name=>"top"},""); } print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$routers{$_}{icon}), width=>15, height=>15, alt=>"$rtrdesc" })," "; if( $_ eq $router ) { print $q->b($rtrdesc); } else { if( $gstyle =~ /p/ ) { print $q->a({href=>"$meurl?".optionstring({page=>"main", rtr=>"$_", if=>""}), target=>"_top" },$rtrdesc ); } else { print $q->a({href=>"$meurl?".optionstring({ rtr=>"$_", if=>"" }), target=>"graph" },$rtrdesc ); } } print "".$q->br."\n"; } # Now add any site links my($mkey,$marg,$mdesc,$micon,$murl,$targ,$level,$insec,$noop); # my($itemx) = 1; # while ( defined $config{"menu-item$itemx"} ) { # $marg = $config{"menu-item$itemx"}; # $mkey = "Item $itemx"; # $itemx += 1; ## This way is slower, but more user-friendly foreach ( sort keys %config ) { if( /^menu-(\S+)/i ) { $mkey = $1; $marg = $config{$_}; ( $mdesc, $murl, $micon, $targ, $level, $insec, $noop ) = parse_ext($marg); if($seclevel >= $level ) { # Are we high enough security level? if( !$micon and $mdesc =~ /\.gif$/ ) { $micon = $mdesc; $mdesc = $mkey; } $mdesc = $mkey if(!$mdesc); #default $micon = "cog-sm.gif" if(!$micon); #default if(!$noop and $murl !~ /\.html?$/ ) { if( $murl =~ /\?/ ) { $murl .= '&'; } else { $murl .= '?'; } $murl .= "fi=".$q->escape($router) ."&url=".$q->escape($q->url()) ."&t=".$q->escape($targ)."&L=".$seclevel; } print ""; print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$micon), width=>15, height=>15, alt=>"$mdesc" })," "; print $q->a({href=>$murl, target=>$targ },$mdesc ); print "".$q->br."\n"; } # security level } # if } # foreach } # Finish off the page print "
\n" if( defined $config{'routers.cgi-menufontsize'} ); print "
\n\n"; print "\n"; print "\n" if($debugmessage); print $q->end_html(); } ############################ # Main frame set sub do_main() { my( $javascript, $framethree ); my( $urla, $urlb, $urlc, $urlh ); my( $menuwidth ) = 150; my( $frameopts ) = " marginwidth=2 marginheight=2 bgcolor=$menubgcolour "; my( $borderwidth ) = 1; $gtype = "" if(!defined $gtype); $mtype = "" if(!defined $mtype); $gstyle = "" if(!defined $gstyle); $gopts = "" if(!defined $gopts); $baropts = "cam" if(!defined $baropts); $borderwidth = $config{'routers.cgi-borderwidth'} if( defined $config{'routers.cgi-borderwidth'} ); $menuwidth = $config{'routers.cgi-menuwidth'} if( defined $config{'routers.cgi-menuwidth'} ); $menuwidth = 150 if ( $menuwidth < 100 or $menuwidth > 500 or $menuwidth !~ /^\d+$/ ); # Javasciript funtion to reload the page with a specified set of params. $javascript = " function makebookmark(rtr,rtrif,xgtype,xgstyle,xgopts,bars,extra,arch) { var newurl; newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif); if ( xgtype != '' ) { newurl = newurl + '&xgtype='+xgtype; } if ( xgstyle != '' ) { newurl = newurl + '&xgstyle='+xgstyle; } if ( xgopts != '' ) { newurl = newurl + '&xgopts='+xgopts ; } if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } if ( arch != '' ) { newurl = newurl + '&arch='+escape(arch) ; } if ( bars != '' && rtrif == '__compact' ) { newurl = newurl + '&bars='+bars ; } window.location = newurl; } function makearchmark(rtr,rtrif,extra,arch) { var newurl; newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif) +'&archive='+arch; if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } window.location = newurl; } var lastaurl; var lastburl; function setlocationa(url) { if( lastaurl != url ) { self.menu.location = url; lastaurl = url; } } function setlocationb(url) { if( self.menub ) { if( lastburl != url ) { self.menub.location = url; lastburl = url; } } } "; $urlb = $meurl."?".optionstring({ page=>"graph" }); if( $twinmenu ) { $urla = $meurl."?".optionstring({ page=>"menu", xmtype=>"routers", nomenu=>1 }) ."#top"; $urlc = $meurl."?".optionstring({ page=>"menub", xmtype=>"options", nomenu=>1 }) ."#top"; $framethree = " \n"; } else { $urla = $meurl."?".optionstring({ page=>"menu", nomenu=>1 })."#top"; $framethree = " \n"; } $urlh = $meurl."?".optionstring({ page=>"head" }); if($q->cookie('auth')) { print "\n"; } print <<"EOT" $windowtitle $framethree <BODY> Sorry, routers.cgi does not support non-frames browsers. Upgrade to Netscape 4.x or later, or MSIE 4.x or later. </BODY> EOT ; # now clean up the verify stuff if it's there # we cant do this in the do_verify subroutine because the file is required # by a future connection. unlink ($config{'routers.cgi-graphpath'}.$pathsep."redsquare.png") if( -f $config{'routers.cgi-graphpath'}.$pathsep."redsquare.png" ); } ########################## # Graph panel sub sinout($) { my($interface); my($sin,$sout,$sext); my($ssin,$ssout,$ssext); my($l,$escunit); $interface = $_[0]; $escunit = $interfaces{$interface}{unit}; $escunit =~ s/%/%%/g; $escunit =~ s/:/\\:/g; $escunit =~ s/ / /g; $sin=langmsg(6403,"In: "); $sout=langmsg(6404,"Out:"); $sext = "Ext:"; $ssext = $ssin = $ssout = ""; $sin = $interfaces{$interface}{legendi} if( defined $interfaces{$interface}{legendi} ); $sout= $interfaces{$interface}{legendo} if( defined $interfaces{$interface}{legendo} ); $sext = $interfaces{$interface}{legendx} if( defined $interfaces{$interface}{legendx} ); $l = length $sin; $l = length $sout if($l < length $sout); $sin = substr($sin.' ',0,$l); $sout= substr($sout.' ',0,$l); $sin =~ s/:/\\:/g; $sout =~ s/:/\\:/g; $sin =~ s/%/%%/g; $sout =~ s/%/%%/g; if( $interfaces{$interface}{integer} ) { $ssin = "%5.0lf"; $ssout = "%5.0lf"; $ssext = "%5.0lf"; } elsif( $interfaces{$interface}{fixunits} and !$interfaces{$interface}{exponent} ) { $ssin = "%7.2lf "; $ssout = "%7.2lf "; $ssext = "%7.2lf"; } else { $ssin = "%6.2lf %s"; $ssout = "%6.2lf %s"; $ssext = "%6.2lf %s"; } if( defined $config{'routers.cgi-legendunits'} and $config{'routers.cgi-legendunits'} =~ /y/i ) { $ssin .= $escunit; $ssout .= $escunit; } $sin .= $ssin; $sout .= $ssout; if( $interfaces{$interface}{mode} eq "SERVER" and $interface eq "CPU" ) { $sin = "usr\\:%6.2lf%%"; $sout = "sys\\:%6.2lf%%"; $sext = "wa\\: %6.2lf%%"; $ssin = $ssout = $ssext = "%6.2lf%%"; } return ( $sin,$sout,$sext, $ssin,$ssout,$ssext ); } sub usr_params(@) { my($ds0,$ds1,$mds0,$mds1); my($lin, $lout); my($dwmy,$interface) = @_; my($ssin, $ssout, $sin, $sout, $sext, $ssext); my($l,$defrrd, $curif); my($legendi,$legendo); my(@clr,$ifcnt, $c, $escunit); my($totindef,$totoutdef,$incnt, $outcnt); my($stacking) = 0; my($max1, $max2); my($greydef); my($havepeaks) = 0; my($workday, $timezone) = (0,0); my(@wdparams) = (); my($maxlbl,$avglbl,$curlbl,$lastlbl) = ('Max','Avg','Cur','Last'); my($gmaxlbl,$gavglbl,$gcurlbl,$glastlbl); $maxlbl = langmsg(2200,$maxlbl); $avglbl = langmsg(2201,$avglbl); $curlbl = langmsg(2202,$curlbl); $lastlbl = langmsg(2203,$lastlbl); $gmaxlbl = langmsg(6200,$maxlbl); $gavglbl = langmsg(6201,$avglbl); $gcurlbl = langmsg(6202,$curlbl); $glastlbl = langmsg(6203,$lastlbl); if( defined $config{'routers.cgi-daystart'} and defined $config{'routers.cgi-dayend'} and $config{'routers.cgi-daystart'}<$config{'routers.cgi-dayend'} and $dwmy !~ /y/ ){ $workday = 1; $timezone = 0; # Calculate timezone. We only need to do this if we're making a graph, # and we have a 'working day' defined. if( defined $config{'web-timezone'} ) { # If its been defined explicitly, then use that. $timezone = $config{'web-timezone'}; } else { # Do we have Time::Zone? eval { require Time::Zone; }; if ( $@ ) { my( @gm, @loc, $hourdif ); eval { @gm = gmtime; @loc = localtime; }; if( $@ ) { # Can't work out local timezone, so assume GMT $timezone = 0; } else { $hourdif = $loc[2] - $gm[2]; $hourdif += 24 if($loc[3]>$gm[3] or $loc[4]>$gm[4] ); $hourdif -= 24 if($loc[3]<$gm[3] or $loc[4]<$gm[4] ); $timezone = $hourdif; } } else { # Use the Time::Zone package since we have it $timezone = Time::Zone::tz_local_offset() / 3600; # it's in seconds so /3600 } } } # stacking? if( defined $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle} =~ /stack/i ) { $stacking = 1; # first is AREA, then STACK } # identify colours if( defined $interfaces{$interface}{colours} ) { @clr = @{$interfaces{$interface}{colours}}; } if(! @clr ) { if( $gstyle =~ /b/ ) { @clr = ( "#000000","#888888","#cccccc","#dddddd","#666666","#444444", "#222222", "#aaaaaa", "#eeeeee", "#bbbbbb", "#555555", "#333333" ); } else { @clr = ( "#0000ff","#00ff00","#ff0000","#00cccc","#cccc00","#cc00cc", "#8800ff", "#88ff00", "#ff8800", "#0088ff", "#ff0088", "#00ff88" ); } } $ifcnt = $#{$interfaces{$interface}{targets}}; # Now the workday highlights, if required if( $workday ) { # note we must have a DS in there even if it is not used push @wdparams, "CDEF:wdtest=in1,POP," ."TIME,3600,/,$timezone,+,DUP,24,/,7,%,DUP,4,LT,EXC,2,GE,+,2,LT," ."EXC,24,%,DUP," .trim($config{'routers.cgi-daystart'}).",GE,EXC," .trim($config{'routers.cgi-dayend'}).",LT,+,2,EQ,1," ."0,IF,0,IF"; # Set to 1 if i