1#!/usr/bin/perl 2# DONT FORGET TO CHANGE THE ABOVE PATH TO MATCH YOUR PERL LOCATION! 3#vim:ts=4 4############################################################################## 5# To use Speedycgi, you need to change the first line to this: 6##!/usr/bin/speedy -- -M20 -t3600 -gnone -r500 7# and then set the CACHE global variable (below) to 1. 8# To use mod_perl, you should be able to put the script directly into the 9# mod_perl directory and it will work. This is not very thoroughly tested 10# though. You also need to set the CACHE global below to 1. 11############################################################################## 12# routers.cgi : Version v2.23 13# Create router monitoring pages 14# 15# This code is covered by the Gnu GPL. See the README file, or the Gnu 16# web site for more details. 17# 18# Includes code derived from overlib (C) Eric Bosrup 19# 20# Developed and tested with RRDTool v1.4.4, Perl 5.8, under Linux (RHEL5) 21# Also partially tested with ActivePerl 5.6 with Apache under NT 22# Note - 95th percentile calcs DO NOT WORK under RRDTool v1.0.24 or earlier 23# Windows users should avoid RRDTool v1.0.33 - v1.0.39 due to a bug. 24# 25############################################################################## 26# DONT FORGET TO CHANGE THE LOCATION OF THE CONFIG FILE DEFINED BELOW! 27############################################################################## 28use strict; 29use CGI; # for CGI 30use File::Basename; # for identifying filenames under different OSs 31use Text::ParseWords; # for parsing MRTG .conf file 32use FileHandle; # to have multiple conf files in recursion 33use Getopt::Std; # For limited command line operation 34use POSIX qw(tzset strftime); # For timezone support 35#use Data::Dumper; # For persistent caching 36use Time::Local 'timelocal_nocheck'; # For time conversions 37##CONFIG#START################################################################ 38# You MUST set this to the location of the configuration file! 39my ($conffile) = '/u01/etc/routers2.conf'; 40############################################################################## 41# Are we running in speedycgi or mod_perl mode? Can we cache configs? 42# If you set this to 1 when you dont have speedycgi or mod_perl, it will 43# slightly slow things down, but will not break anything. 44# This can also be set in the routers2.conf with the cache=yes option 45my ($CACHE) = 0; 46############################################################################## 47# You should set this to something random and secret, if you are using 48# the script's internal authentication via cookies. It's called this because 49# it is embedded into a cookie... 50my ($CHOCOLATE_CHIP) = 'fh89647jnvhtg678gtfpo9fuku86yhgs'; 51##CONFIG#END################################################################## 52my ($VERSION) = 'v2.23'; 53my ($APPURL ) = 'http://www.steveshipway.org/software/'; 54my ($FURL ) = 'http://www.steveshipway.org/forum/'; 55my ($MLURL ) = 'http://www.steveshipway.org/mailman/listinfo/support_steveshipway.org'; 56my ($WLURL ) = 'http://www.steveshipway.org/software/wishlist.html'; 57my ($BURL ) = 'http://www.steveshipway.org/book/'; 58my ($APPMAIL) = 'mailto:steve@steveshipway.org'; 59##GLOBAL#START################################################################ 60# Global variables : uses 'use vars' for speeycgi and mod_perl 61use vars qw($opt_A $opt_D $opt_T $opt_r $opt_i $opt_s $opt_t $opt_I $opt_a $opt_U $opt_C $opt_G); 62use vars qw($meurl $meurlfull); 63use vars qw($mtype $gtype $defgopts $defgtype $defrouter $defif $cookie); 64($mtype,$gtype,$defgopts, $defgtype, $defrouter, $defif, $cookie) = 65 ('','','','','','',''); 66use vars qw(@cookies); 67@cookies=(); 68use vars qw($gopts $baropts $defbaropts $uopts); 69($gopts, $baropts, $defbaropts, $uopts) = ('','','',''); 70use vars qw(%routers %routerscache); %routers = (); # loaded from cache 71use vars qw(%cachedays); 72use vars qw($readinrouters); $readinrouters = 0; 73use vars qw(%interfaces %ifstore); 74use vars qw(%lang $language); $language = ''; 75use vars qw(%gtypes @gorder); 76use vars qw(%gstyles @sorder %gstylenames); 77use vars qw($gstyle $defgstyle $archdate); 78($gstyle, $defgstyle, $archdate) = ('','',''); 79use vars qw(%headeropts); %headeropts = (); 80use vars qw(@cfgfiles); @cfgfiles = (); 81use vars qw($lastupdate $workdir $interval); 82($lastupdate, $workdir, $interval) = ('','',''); 83use vars qw($basetime); $basetime = 0; 84use vars qw($pagetype); $pagetype = ''; 85use vars qw($donecfg); $donecfg = 0; 86use vars qw(%config); 87use vars qw($bn); $bn = ''; 88use vars qw($graphsuffix); $graphsuffix = "gif"; 89use vars qw($NT); $NT = 0; # gets set to 1 if using NT 90use vars qw($pathsep); $pathsep = "/"; # gets set to "\\" if you have NT 91use vars qw($dailylabel); $dailylabel = "%k"; # set to "%H" if you have ActivePerl 92use vars qw($monthlylabel); 93$monthlylabel = "%V";# use "%W" for alternate week numbering method 94 # gets set to %W if you have ActivePerl 95use vars qw($usesixhour); $usesixhour = 0; 96use vars qw($twinmenu); $twinmenu = 0; 97use vars qw($rrdoutput); $rrdoutput = ""; 98use vars qw($rrdxsize $rrdysize); 99($rrdxsize, $rrdysize) = (0,0); 100use vars qw($router $interface); 101($router, $interface) = ('',''); 102use vars qw($uselastupdate $archivetime); $uselastupdate = 0; 103use vars qw($ksym $k $M $G $T); 104($ksym,$k,$M,$G,$T) = ("K",1024,1024000,1024000000,1024000000000); # mixed 105use vars qw($grouping); $grouping = 0; # Do we group when sorting routers? 106use vars qw($group); $group = ""; 107use vars qw($csvmime); 108$csvmime = "text/comma-separated"; # MIME type for CSV downloads 109use vars qw($windowtitle); $windowtitle = "Systems Monitor"; # Widow title 110use vars qw($toptitle); $toptitle = ""; # Title at top of page 111use vars qw($timezone); $timezone = 0; 112use vars qw($bits $factor); 113($bits, $factor) = ("!bits",8); 114use vars qw($defbgcolour); $defbgcolour = "#ffffff"; # default colours 115use vars qw($deffgcolour); $deffgcolour = "#000000"; 116use vars qw($menubgcolour); $menubgcolour = "#d0d0d0"; 117use vars qw($menufgcolour); $menufgcolour = "#000000"; 118use vars qw($authbgcolour); $authbgcolour = "#ffffff"; 119use vars qw($authfgcolour); $authfgcolour = "#000000"; 120use vars qw($linkcolour); $linkcolour = "#2020ff"; 121use vars qw($extra); $extra = ""; 122use vars qw($archiveme); $archiveme = 0; 123use vars qw($archive); $archive = ""; 124use vars qw($myname); $myname = 'routers2.cgi'; 125use vars qw($debugmessage); $debugmessage = "Instance: $$\n"; 126use vars qw($authuser); $authuser = ""; 127use vars qw($crypthack); $crypthack = 0; # compatibility for broken crypt 128use vars qw(@params); @params = (); 129use vars qw($traffic); $traffic = ""; 130use vars qw($seclevel); $seclevel = 0; 131use vars qw($comma); $comma = ','; # for CSV 132use vars qw(@pathinfo); @pathinfo = (); 133use vars qw($stime); $stime = (times)[0]; 134use vars qw($linewidth); $linewidth = 1; 135use vars qw($charset); $charset = ''; 136use vars qw($rrdcached); $rrdcached = ''; 137use vars qw(@rrdcached); @rrdcached = (); 138use vars qw($PERCENT); $PERCENT = 95; 139 140##GLOBAL#END############################################################ 141# You MAY configure the descriptions in the lines below if you require 142# or, remove some entries from the @sorder Styles list. 143######################################################################## 144sub initlabels { 145 %gtypes = ( 146 "d"=>"Daily", "w"=>"Weekly", 147 "m"=>"Monthly", "y"=>"Yearly", 148 "dwmy"=>"All Graphs", "6dwmy"=>"All Graphs", 149 "6dwmys"=>"Compact", "dwmys"=>"Compact", 150 "6"=>"6 hour", "6-"=>"Six hours ago", 151 "m-"=>"Last Month", "w-"=>"Last week", 152 "d-"=>"Yesterday", "y-"=>"Last Year", 153 "dw"=>"Short term", "my"=>"Long term", 154 "6s"=>"Compact 6 hour", 155 "ds"=>"Compact daily", "ws"=>"Compact weekly", 156 "ms"=>"Compact monthly", "ys"=>"Compact yearly", 157 "dm"=>"Day+Month", "wm"=>"Week+Month", 158 "dy"=>"Day+Year", 159 "x1"=>"X1", "x2"=>"X2", "x3"=>"X3", "x4"=>"X4" 160 ); 161 @gorder = qw/d w m y dwmy dwmys/; 162 # you might prefer to have the order reversed 163 # NOTE: first word of these is the key used in routers.conf for default 164 # base style: s t n l x y = widths; s t = half data width 165 # suffix: D = double data width, 2 3 = height multiplier 166 # p = no javascript (pda), b = monochrome (b&w) 167 # so for example, tD is the same as n 168 %gstyles = ( 169 s=>"Short (PDA)", n=>"Normal (640x480)", t=>"Stretch", l=>"Long", 170 n2=>"Tall", l2=>"Big (800x600)", x3=>"Huge (1024x768)", x=>"ExtraLong", 171 sbp=>"Palm III/V", nbp=>"Psion 3/3x/5", np=>"WinCE-1", sp=>"WinCE-2", 172 l2p=>"Web TV", x2=>"Very Big (1024x768)" , 173 y3=>"Vast (widescreen)", x3D=>"Huge extended", l2D=>"Big extended", 174 x3H=>"Huge stretch", l2H=>"Big stretch", 175 x3T=>"Huge triple", 176 ); 177 if(defined $config{'routers.cgi-sorder'} ) { 178 @sorder = (); 179 foreach ( split " ", $config{'routers.cgi-sorder'} ) { 180 push @sorder, $_ if(defined $gstyles{$_}); 181 } 182 } else { 183 # you might want to remove some of these 184 @sorder = qw/s t n n2 l l2 l2D x x3 x3D sbp nbp np l2p/; 185 } 186} 187 188##CODE#START############################################################ 189# Nothing else to configure after this line 190######################################################################## 191 192# initialize CGI 193use vars qw($q); 194$q = new CGI; # At this point, parameters are parsed 195 196$meurl = $q->url(-absolute=>1); # /cgi-bin/routers2.cgi 197$meurlfull = $q->url(-full=>1); # http://server/cgi-bin/routers2.cgi 198$meurlfull = "" if($meurlfull !~ /\/\/.*\//); # avoid IIS bug, maybe 199$router = $interface = ""; 200 201################################# 202# For RRD v1.2 compatibility: remove colons for COMMENT directive if 203# we are in v1.2 or later, else leave them there 204sub decolon($) { 205 my($s) = $_[0]; 206 return $s if($RRDs::VERSION < 1.2 ); 207 $s =~ s/:/\\:/g; 208 return $s; 209} 210 211################################# 212# For RRD archives: make 2chr subdir name from filename 213sub makehash($) { 214 my($x); 215# This is more balanced 216 $x = unpack( '%8C*',$_[0] ); 217# This is easier to follow 218# $x = substr($_[0],0,2); 219 return $x; 220} 221 222################################# 223# For expanding variables 224sub expandvars($) { 225 my($s) = $_[0]; 226 my($luh); 227 my($rv,$tmp); 228 my($comm) = ''; 229 my($dev) = ''; 230 my($snmp,$snmperr,$resp) = ('','',''); 231 232 # Process %INCLUDE(....)% symbols 233 while( $s =~ /\%INCLUDE\(\s*(\S+)\s*\)\%/ ) { 234 my($f) = $1; 235 my($d) = ""; 236 if( open INC,"<$f" ) { 237 while ( <INC> ) { $d .= $_; } 238 close INC; 239 } else { 240 $d = "Error: File $f: $!"; 241 } 242 $s =~ s/\%INCLUDE\(\s*$f\s*\)\%/$d/g; 243 } 244 245 # Process all standard symbols and their variants 246 $s =~ s/\%ROUTERS2?\%/$meurlfull/g; 247 $s =~ s/\%CFG(FILE)?\%/$routers{$router}{file}/g; 248 $s =~ s/\%INTERVAL\%/$routers{$router}{interval}/g; 249 $s =~ s/\%(ROUTER|DEVICE)\%/$router/g; 250 $s =~ s/\%(TARGET|INTERFACE)\%/$interface/g; 251 $s =~ s/\%STYLE\%/$gstyle/g; 252 $s =~ s/\%TYPE\%/$gtype/g; 253 $s =~ s/\%STYLENAME\%/$gstyles{$gstyle}/g; 254 $s =~ s/\%TYPENAME\%/$gtypes{$gtype}/g; 255 $s =~ s/\%L(U|ASTUPDATE)\%/$lastupdate/g; 256 if($lastupdate) { $luh = longdate($lastupdate); } 257 else { $luh = "Unknown"; } 258 $s =~ s/\%L(U|ASTUPDATE)H\%/$luh/g; 259 $s =~ s/\%ARCHDATE\%/$archdate/g; 260 $s =~ s/\%USER(NAME)?\%/$authuser/g; 261 $tmp = optionstring({page=>"image"}); 262 $s =~ s/\%GRAPHURL\%/$meurlfull?$tmp/g; 263 $tmp = 300; 264 if( $gtype =~ /y/ ) { $tmp = 24 * 3600; } 265 elsif( $gtype =~ /m/ ) { $tmp = 7200; } 266 elsif( $gtype =~ /w/ ) { $tmp = 1800; } 267 $s =~ s/\%AVGINT\%/$tmp/g; 268 269 270 $rv = $routers{$router}{'cfgmaker-system'}; $rv="" if(!defined $rv); 271 $s =~ s/\%CMSYSTEM\%/$rv/g; 272 $rv = $routers{$router}{'cfgmaker-description'}; $rv="" if(!defined $rv); 273 $s =~ s/\%CMDESC(RIPTION)?\%/$rv/g; 274 $rv = $routers{$router}{'cfgmaker-contact'}; $rv="" if(!defined $rv); 275 $s =~ s/\%CMCONTACT\%/$rv/g; 276 $rv = $routers{$router}{'cfgmaker-location'}; $rv="" if(!defined $rv); 277 $s =~ s/\%CMLOCATION\%/$rv/g; 278 279 if( defined $interfaces{$interface} ) { 280 $rv = $interfaces{$interface}{maxbytes}; $rv = "" if(!defined $rv); 281 $s =~ s/\%(MAXBYTES|BANDWIDTH)\%/$rv/g; 282 $rv = $interfaces{$interface}{ipaddress}; $rv = "" if(!defined $rv); 283 $s =~ s/\%IP(ADDR(ESS)?)?\%/$rv/g; 284 $rv = $interfaces{$interface}{community}; 285 $rv = $routers{$router}{community} if(! $rv); 286 $rv = "" if(!defined $rv); 287 $s =~ s/\%COMMUNITY\%/$rv/g; 288 $rv = $interfaces{$interface}{hostname}; 289 $rv = $routers{$router}{hostname} if(! $rv); 290 $rv = "" if(!defined $rv); 291 $s =~ s/\%HOST(NAME)?\%/$rv/g; 292 $rv = $interfaces{$interface}{rrd}; $rv = "" if(!defined $rv); 293 $s =~ s/\%RRD(FILE)?\%/$rv/g; 294 $rv = $interfaces{$interface}{ifno}; $rv = "" if(!defined $rv); 295 $s =~ s/\%(IFNO|INTNUM)?\%/$rv/g; 296 297 $rv = $interfaces{$interface}{'cfgmaker-description'}; 298 $rv = "" if(!defined $rv); 299 $s =~ s/\%CMIDESC(RIPTION)?\%/$rv/g; 300 301 if( defined $interfaces{$interface}{symbols} ) { 302 foreach my $sym ( keys %{$interfaces{$interface}{symbols}} ) { 303 my $v = $interfaces{$interface}{symbols}{$sym}; 304 $s =~ s/\%$sym\%/$v/g; 305 } 306 } 307 } else { 308 $rv = $routers{$router}{community}; $rv = "" if(!defined $rv); 309 $s =~ s/\%COMMUNITY\%/$rv/g; 310 $rv = $routers{$router}{hostname}; $rv = "" if(!defined $rv); 311 $s =~ s/\%HOST(NAME)?\%/$rv/g; 312 } 313 if( defined $routers{$router}{symbols} ) { 314 foreach my $sym ( keys %{$routers{$router}{symbols}} ) { 315 my $v = $routers{$router}{symbols}{$sym}; 316 $s =~ s/\%$sym\%/$v/g; 317 } 318 } 319 320 # Process %ENV(...)% symbols 321 while( $s =~ /\%ENV\(\s*(\S+)\s*\)\%/ ) { 322 my($a) = $1; 323 my($b) = $ENV{$a}; 324 $s =~ s/\%ENV\($a\)\%/$b/g; 325 } 326 327 # Process %OID(....)% symbols 328 while( $s =~ /\%OID\(\s*(\S+)\s*\)\%/ ) { 329 my($a) = $1; 330 my($b) = '[Not yet supported]'; 331 my($vb); 332 $comm = $routers{$router}{community} if($routers{$router}{community}); 333 $dev = $routers{$router}{hostname} if($routers{$router}{hostname}); 334 if($interface and $interfaces{$interface} ) { 335 $comm = $interfaces{$interface}{community} 336 if($interfaces{$interface}{community}); 337 $dev = $interfaces{$interface}{hostname} 338 if($interfaces{$interface}{hostname}); 339 $dev = $interfaces{$interface}{ipaddress} 340 if($interfaces{$interface}{ipaddress}); 341 } 342 if(! $comm) { 343 $b = "[No community: Cannot request OID]"; 344 } elsif(! $dev) { 345 $b = "[No hostname/IP known: Cannot request OID]"; 346 } else { 347 # look up the OID via SNMP 348 eval { require Net::SNMP; }; 349 if($@) { 350 $b = "[Net::SNMP not available]"; 351 } else { 352 if(!$snmp) { 353 ($snmp, $snmperr) = Net::SNMP->session( 354 -hostname=>$dev, -community=>$comm, -timeout=>4 ); 355 } 356 if($snmperr) { $b = "[SNMP Error: $snmperr]"; } 357 else { 358 $resp = $snmp->get_request( $a ); 359 if( defined $resp ) { 360 $vb = $snmp->var_bind_types( $a ); 361 $b = ""; 362 foreach ( keys %$resp ) { 363 if($vb->{$_} eq *TIMETICKS ) { 364 $b .= ticks_to_time($resp->{$_}); 365 } else { $b .= $resp->{$_}; } 366 } 367 } else { $b = "[SNMP Error:".$snmp->error()."]"; } 368 } 369 } 370 } 371 $s =~ s/\%OID\($a\)\%/$b/; 372 } 373 $snmp->close() if($snmp); 374 375 # Process %EXEC(...)% symbol 376 if(defined $config{'web-allow-execs'} 377 and $config{'web-allow-execs'}=~/[y1]/) { 378 while( $s =~ /\%EXEC\(([^\)]+)\)\%/ ) { 379 my($a) = $1; 380 my($b) = `$a`; # DANGER WILL ROBINSON! 381 $s =~ s/\%EXEC\($a\)\%/$b/; 382 } 383 } 384 return $s; 385} 386 387################################# 388# For sorting 389 390sub rev { $b cmp $a; } 391sub numerically { 392 return ($a cmp $b) if( $a !~ /\d/ or $b !~ /\d/ ); 393 $a <=> $b; 394} 395sub bytraffic { 396 return -1 if(!$a or !$b or !$traffic); 397# return -1 if(!defined $interfaces{$a}{$traffic} 398# or !defined $interfaces{$b}{$traffic}); 399 $interfaces{$b}{$traffic} <=> $interfaces{$a}{$traffic}; 400} 401sub byiflongdesc { 402 my ( $da, $db ) = ( "#$a","#$b" ); 403 # is this an invalid interface? 404 return 0 if(!defined $interfaces{$a} or !defined $interfaces{$b}); 405 return 1 if(!$interfaces{$a}{inmenu} and $interfaces{$b}{inmenu}); 406 return -1 if(!$interfaces{$b}{inmenu} and $interfaces{$a}{inmenu}); 407 if( defined $config{'targetnames-ifsort'} ) { 408 if( $config{'targetnames-ifsort'} eq 'icon' ) { 409 return $interfaces{$a}{icon} cmp $interfaces{$b}{icon} 410 if($interfaces{$a}{icon} ne $interfaces{$b}{icon}); 411 } elsif( $config{'targetnames-ifsort'} eq 'mode' ) { 412 return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} 413 if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); 414 } 415 } else { 416 return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} 417 if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); 418 } 419 # we always sort by description in the end 420 $da = $interfaces{$a}{shdesc} if( defined $interfaces{$a}{shdesc} ); 421 $db = $interfaces{$b}{shdesc} if( defined $interfaces{$b}{shdesc} ); 422 $da = $interfaces{$a}{desc} if( defined $interfaces{$a}{desc} ); 423 $db = $interfaces{$b}{desc} if( defined $interfaces{$b}{desc} ); 424 (lc $da) cmp (lc $db); 425} 426sub byifdesc { 427 my ( $da, $db ) = ( "#$a","#$b" ); 428 # is this an invalid interface? 429 return 0 if(!defined $interfaces{$a} or !defined $interfaces{$b}); 430 return 1 if(!$interfaces{$a}{inmenu} and $interfaces{$b}{inmenu}); 431 return -1 if(!$interfaces{$b}{inmenu} and $interfaces{$a}{inmenu}); 432 433 if( defined $config{'targetnames-ifsort'} ) { 434 if( $config{'targetnames-ifsort'} eq 'icon' ) { 435 return $interfaces{$a}{icon} cmp $interfaces{$b}{icon} 436 if($interfaces{$a}{icon} ne $interfaces{$b}{icon}); 437 } elsif( $config{'targetnames-ifsort'} eq 'mode' ) { 438 return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} 439 if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); 440 } 441 } else { 442 return $interfaces{$a}{mode} cmp $interfaces{$b}{mode} 443 if($interfaces{$a}{mode} ne $interfaces{$b}{mode}); 444 } 445 # we always sort by description in the end 446 $da = $interfaces{$a}{shdesc} if( defined $interfaces{$a}{shdesc} ); 447 $db = $interfaces{$b}{shdesc} if( defined $interfaces{$b}{shdesc} ); 448 (lc $da) cmp (lc $db); 449} 450sub bydesc { 451 my ( $da, $db ) = ($routers{$a}{desc}, $routers{$b}{desc}); 452 $da = $a if ( ! $da ); 453 $db = $b if ( ! $db ); 454 (lc $da) cmp (lc $db); 455} 456# Sorting function for devices menu 457sub byshdesc { 458 my ( $da, $db ) = ($routers{$a}{shdesc}, $routers{$b}{shdesc}); 459 if( $grouping ) { 460 my ( $ga ) = $routers{$a}{group}; 461 my ( $gb ) = $routers{$b}{group}; 462 $ga=$config{"targetnames-$ga"} if(defined $config{"targetnames-$ga"}); 463 $gb=$config{"targetnames-$gb"} if(defined $config{"targetnames-$gb"}); 464 # Sort by group name first 465 my ( $c ) = $ga cmp $gb; 466 if($c) { return $c; } 467 } 468 # Sort by description of device 469 $da = $a if ( ! $da ); 470 $db = $b if ( ! $db ); 471 (lc $da) cmp (lc $db); 472} 473# For sorting component targets in a userdefined 474# sort option can be MAX, AVG, LAST 475sub byoption { 476 return($interfaces{$b}{sorttmp} <=> $interfaces{$a}{sorttmp}); 477} 478sub byoptionrev { 479 return($interfaces{$a}{sorttmp} <=> $interfaces{$b}{sorttmp}); 480} 481sub sorttargets($$$) { 482 my($interface,$dwmy,$option) = @_; 483 my($from,$rrd,$e); 484 my($resolution,$interval,$seconds); 485 my($curif); 486 my(@sorted) = (); 487 488 return if(!$interfaces{$interface}{targets}); 489 490 if( $option =~ /desc|name|title/i ) { 491 @sorted = 492 sort { (lc $interfaces{$a}{shdesc}) cmp (lc $interfaces{$b}{shdesc}); } 493 @{$interfaces{$interface}{targets}}; 494 return @sorted; 495 } 496 497 $resolution = 60; $interval = "6h"; $seconds = 6*3600; 498 if ( $dwmy=~/d/ ){$resolution=300; $interval="24h"; $seconds=86400; } 499 elsif($dwmy=~/w/){$resolution=1800; $interval="7d"; $seconds=7*86400; } 500 elsif($dwmy=~/m/){$resolution=7200; $interval="1month"; $seconds=30*86400;} 501 elsif($dwmy=~/y/){$resolution=86400; $interval="1y"; $seconds=365*86400;} 502 503 $curif = $interfaces{$interface}{targets}[0]; 504 $rrd = $interfaces{$curif}{rrd}; 505 if($basetime) { 506 $from = $basetime; 507 } elsif( $dwmy =~ /-/ ) { 508 $from = "now-$interval"; 509 } elsif($uselastupdate > 1 and $archivetime) { 510 $from = $archivetime; 511 } elsif($uselastupdate) { 512 $from = RRDs::last($rrd,@rrdcached); 513 $e = RRDs::error(); 514 if($e) { 515 $from = "now"; 516 $interfaces{$curif}{errors}.= $q->br.$q->small(langmsg(8999,"Error").": $e")."\n"; 517 } 518 } else { 519 $from = "now-5min"; 520 } 521 522 foreach $curif ( @{$interfaces{$interface}{targets}} ) { 523 $interfaces{$curif}{sorttmp} = 0; 524 $rrd = $interfaces{$curif}{rrd}; 525 if( $option =~ /max/i ) { 526 my ( $start, $step, $names, $values ) = 527 RRDs::fetch($rrd,"MAX","-s","$from-$interval", 528 "-e",$from,"-r",$seconds,@rrdcached); 529 $e = RRDs::error(); 530 if($e) { 531 $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); 532 } else { 533 my ($maxin, $maxout) = get_max($values); 534 $interfaces{$curif}{sorttmp}=(($maxin>$maxout)?$maxin:$maxout); 535 } 536 } elsif( $option =~ /last/i ) { 537 } else { # avg 538 my ( $start, $step, $names, $values ) = 539 RRDs::fetch($rrd,"AVERAGE","-s","$from-$interval", 540 "-e",$from,"-r",$seconds,@rrdcached); 541 $e = RRDs::error(); 542 if($e) { 543 $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); 544 } else { 545 my ($avgin, $avgout) = get_avg($values); 546 $interfaces{$curif}{sorttmp}=(($avgin>$avgout)?$avgin:$avgout); 547 } 548 } 549 } 550 551 if($option=~/rev/) { 552 @sorted = sort byoptionrev @{$interfaces{$interface}{targets}}; 553 } else { 554 @sorted = sort byoption @{$interfaces{$interface}{targets}}; 555 } 556 return @sorted; 557} 558##################### 559# Timezone calculations 560# Calculate timezone. We don't need to do this again if its already been 561# done in a previous iteration. Now, we need this if we're making a graph 562# with working day intervals, or if we're on a graph/summary page with a 563# time popup - but we may as well do it every time. 564sub calctimezone() { 565 my( @gm, @loc, $hourdif ); 566$timezone = 0; 567if( defined $config{'web-timezone'} ) { 568 # If its been defined explicitly, then use that. 569 $timezone = $config{'web-timezone'}; 570} else { 571 # Do we have Time::Zone? 572 eval { require Time::Zone; }; 573 if ( $@ ) { 574 eval { @gm = gmtime; @loc = localtime; }; 575 if( $@ ) { 576 # Can't work out local timezone, so assume GMT 577 $timezone = 0; 578 } else { 579 $hourdif = $loc[2] - $gm[2]; 580 $hourdif += 24 if($loc[3]>$gm[3] or $loc[4]>$gm[4] ); 581 $hourdif -= 24 if($loc[3]<$gm[3] or $loc[4]<$gm[4] ); 582 $timezone = $hourdif; 583 } 584 } else { 585 # Use the Time::Zone package since we have it 586 $timezone = Time::Zone::tz_local_offset() / 3600; 587 # it's in seconds so /3600 588 } 589} 590} 591 592###################### 593# For grouping multilevel. Work out which groups we need to display. 594# (activegroup, thisgroup, lastgroup) 595# returns [ [groupname,depth,active], ... ] 596sub getgroups($$$) { 597 my(@rv) = (); 598 my($ag,$tg,$lg) = @_; 599 my(@ag,@tg,@lg); 600 my($gs) = ':'; 601 my($i) = 0; 602 my($actv) = 1; 603 604 $gs = $config{'routers.cgi-groupsep'} 605 if(defined $config{'routers.cgi-groupsep'}); 606 $gs =~ s/\//\\\//g; 607 608 @ag = split /$gs/,$ag; 609 @tg = split /$gs/,$tg; 610 @lg = split /$gs/,$lg; 611 612 while( $i <= $#tg ) { 613 $actv = 0 if( $tg[$i] ne $ag[$i] ); 614 615 if( $tg[$i] ne $lg[$i] ) { 616 $tg[$i] =~ s/^\s*//; # trim leading spaces 617 push @rv, [ $tg[$i], $i, $actv ]; 618 } 619 last if(!$actv); 620 $i += 1; 621 } 622 623# push @rv, [ $tg, 0, 0 ]; 624 return @rv; 625} 626 627###################### 628# Replacement for glob: find archives 629# return list of dates 630# This time, we also cache the list of archive dates, if we can 631sub findarch($$) 632{ 633 my(@files) = (); 634 my($path,$file) = @_; 635 636 if ($config{'routers.cgi-archive-mode'} and 637 $config{'routers.cgi-archive-mode'}=~/hash/i ) { 638 foreach ( glob( $path.$pathsep.makehash($file).$pathsep.$file.".d".$pathsep."*-*-*.rrd" ) ) { 639 push @files, $1 if( /(\d\d\d\d-\d\d-\d\d).rrd/ ); 640 } 641 } else { 642 opendir DIR, $path or return @files; 643 foreach ( readdir DIR ) { 644 push @files, $_ if( -f $path.$pathsep.$_ .$pathsep.$file ); 645 } 646 closedir DIR; 647 } 648 return @files; 649} 650 651###################### 652# calculate short date string from given time index 653 654sub shortdate($) 655{ 656 my( $dformat ) = "%c"; # windows perl doesnt have %R 657 my( $datestr, $fmttime ) = ("",0); 658 return "DATE ERROR 1" if(!$_[0]); 659 $fmttime = $_[0]; 660 $fmttime = time if(!$fmttime); 661 my( $sec, $min, $hour, $mday, $mon, $year ) = localtime($fmttime); 662 # try to get local formatting 663 $dformat = $config{'web-dateonlyformat'} 664 if(defined $config{'web-dateonlyformat'}); 665 $dformat = $config{'web-shortdateformat'} 666 if(defined $config{'web-shortdateformat'}); 667 $dformat =~ s/ / /g; 668 $datestr = POSIX::strftime($dformat, 669 0,$min,$hour,$mday,$mon,$year); 670 return "DATE ERROR 2" if(!$datestr); 671 return $datestr; 672} 673sub longdate($) { 674 # try to get local formatting 675 my( $dformat ) = "%c"; 676 my( $datestr, $fmttime ) = ("",$_[0]); 677 my( $sec, $min, $hour, $mday, $mon, $year ) = localtime($fmttime); 678 $dformat = $config{'web-shortdateformat'} 679 if(defined $config{'web-shortdateformat'}); 680 $dformat = $config{'web-longdateformat'} 681 if(defined $config{'web-longdateformat'}); 682 $datestr = POSIX::strftime($dformat,0,$min,$hour,$mday,$mon,$year); 683 return $datestr; 684} 685 686################################# 687# For string trims. Remove leading and trailing blanks 688sub trim($) 689{ 690 my($x)=$_[0]; 691 $x=~s/\s*$//; 692 $x=~s/^\s*//; 693 $x; 694} 695 696################################# 697# build up option string 698sub optionstring(%) 699{ 700 my(%o,$options); 701 %o = %{$_[0]}; 702 703 $o{page}="graph" if(!defined $o{page}); 704 $o{xgtype}="$gtype" if($gtype and !defined $o{xgtype}); 705 $o{xmtype}="$mtype" if($mtype and !defined $o{xmtype}); 706 $o{xgstyle}="$gstyle" if($gstyle and !defined $o{xgstyle}); 707 $o{xgopts}="$gopts" if($gopts and !defined $o{xgopts}); 708 $o{bars}="$baropts" if($baropts and !defined $o{bars}); 709 $o{rtr}="$router" if($router and !defined $o{rtr}); 710 $o{if}="$interface" if($interface and !defined $o{if}); 711 $o{extra}="$extra" if($extra and !defined $o{extra}); 712 $o{uopts}="$uopts" if($uopts and !defined $o{uopts}); 713 $o{arch}="$archdate" if($archdate and !defined $o{arch}); 714# This shouldnt be propagated, really. 715# $o{nomenu}=1 if($q->param('nomenu') and !defined $o{nomenu}); 716 717 $options = ""; 718 foreach ( keys %o ) { 719 if( $o{$_} ) { 720 $options .= "&" if ($options); 721 $options .= "$_=".$q->escape($o{$_}); 722 } 723 } 724 return $options; 725} 726 727################################# 728# Generate the javascript for the page header 729sub make_javascript(%) 730{ 731 my($js) = ""; 732 my(%opa,%opb); 733 my($ua,$ub); 734 735 return("function LoadMenu() { }") if($q->param('nomenu') or $gstyle=~/p/); 736 737 %opa = ( page=>"menu" ); 738 foreach ( keys %{$_[0]} ) { $opa{$_}=$_[0]->{$_}; } 739 740 $js = " 741 // these local versions are not optimised but avoid cross-site scripting 742 // problems when running in distributed mode 743 // Test for parent.menu in case someone is running graph frame standalone 744 function setlocationa(url) { 745 if(parent.makebookmark) { parent.setlocationa(url); } 746 } 747 function setlocationb(url) { 748 if(parent.makebookmark) { parent.setlocationb(url); } 749 } 750"; 751 if( $twinmenu ) { 752 %opb = %opa; 753 $opa{xmtype} = "routers"; $opa{'if'} = ""; 754 $opb{page} = "menub"; $opb{xmtype} = "options"; 755 $ua = "$meurlfull?".optionstring(\%opa)."#top"; 756 $ub = "$meurlfull?".optionstring(\%opb)."#top"; 757 $js .= "function LoadMenu() { setlocationb(\"$ub\"); setlocationa(\"$ua\"); }\n"; 758 } else { # not twinmenu mode 759 $opa{xmtype}="routers" 760 if($router eq "none" or (defined $opa{rtr} and $opa{rtr} eq "none")); 761 $opa{'if'}='' if($opa{xmtype}eq'routers'); 762 $ua = "$meurlfull?".optionstring(\%opa)."#top"; 763 $js .= "function LoadMenu() { setlocationa(\"$ua\"); } \n"; 764 } 765 766 return $js; 767} 768# Makes the javascript for a popup time window on graphs. 769# This goes into a hidden div called dpopup at the top of the page. 770# This incorporates bits of code copied from the overlib javascript library 771# which is (C) Eric Bosrup 772sub graphpopupscript() { 773 my($js,$xpad,$ypad); 774 my($stretch) = 1; 775 776 if(( defined $config{'routers.cgi-javascript'} 777 and $config{'routers.cgi-javascript'} =~ /[n0]/i ) 778 or $gstyle =~ /p/ ) { 779 $js = " function clearpopup() { } 780 function timepopup() { } 781 function mousemove() { } "; 782 } else { 783 eval { require RRDs; }; # just in case 784 return "" if($@); 785 if( $RRDs::VERSION >= 1.4 ) { $xpad = 66; $ypad = 33; } 786 elsif( $RRDs::VERSION >= 1.2 ) { $xpad = 69; $ypad = 33; } 787 else { $xpad = 75; $ypad = 30; } 788 $stretch *= 2 if ($gstyle=~/D/); 789 $stretch /= 2 if ($gstyle=~/H/); 790 $stretch /= 2 if ($gstyle=~/^t/); # for stretch style, t==nH 791 792 $js = "// Function for RRDs version ".$RRDs::VERSION."\n"; 793 $js .= " 794// This javascript code derived in part from Overlib by Eric Bosrup 795var tzoffset = 0; 796"; 797 if(defined $config{'routers.cgi-actuals'} 798 and $config{'routers.cgi-actuals'}=~/[y1]/i 799 and (!defined $config{'routers.cgi-javascript'} 800 or $config{'routers.cgi-javascript'}=~/[y1]/i)) { 801 # larger offset if we're using actuals 802 $js .= " 803var ooffsety = -40; // above the cursor, to the right 804var ooffsetx = 10; // offset of popup from cursor position 805"; 806 } else { 807 $js .= " 808var ooffsety = -25; // above the cursor, to the right 809var ooffsetx = 5; // offset of popup from cursor position 810"; 811 } 812 $js .= " 813var owidth = 100; // width of the popup 814var pop=null; 815var gx, gy, gw; 816var img=null; 817var interval = 0; 818var endtime = 0; 819var ns4=(document.layers)? true:false; 820var ns6=(document.getElementById)? true:false; 821var ie4=(document.all)? true:false; 822var ie5=false; 823var ie6=false; 824var dow=new Array(\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\",\"Sun\"); 825var actual=new Array(5); // to hold 6/d/w/m/y arrays of 400 items 826var xactual=new Array(5); // to hold 6/d/w/m/y flags 827xactual[0]=0; xactual[1]=0; xactual[2]=0; xactual[3]=0; xactual[4]=0; xactual[5]=0; 828if(ie4){ 829 if((navigator.userAgent.indexOf('MSIE 5')> 0) 830 ||(navigator.userAgent.indexOf('MSIE 6')> 0) 831 ||(navigator.userAgent.indexOf('MSIE 7')> 0) 832 ){ ie5=true; } 833 if((navigator.userAgent.indexOf('MSIE 6')> 0) 834 ||(navigator.userAgent.indexOf('MSIE 7')> 0) 835 ){ ie6=true; } 836 if(ns6){ ns6=false; } 837} 838 839function getextra(t) { 840 var idx; 841 var group; 842 var rv = \"\"; 843 if(interval<1)return rv; 844 if(interval == 1800) { // weeks have only 333 not 400 dp in graph image 845 idx = 400-Math.floor((endtime-t)/(1500*$stretch)); // array index 846 } else { 847 idx = 400-Math.floor((endtime-t)/(interval*$stretch)); // array index 848 } 849 group = 0; // 6 hourly 850 if ( interval > 61 ) { group = 1; } // daily 851 if ( interval > 301 ) { group = 2; } // weekly 852 if ( interval > 1801 ) { group = 3; } // monthly 853 if ( interval > 7201 ) { group = 4; } // yealy 854 // now, see if we have stored any data for this interval 855 if( xactual[group]>0 && (\"\"+actual[group][idx])!=\"undefined\" ) { rv = \"<BR>\"+actual[group][idx]; } 856 return rv; 857} 858function clearpopup() { 859 if(pop != null ) { 860 if(ns4)pop.visibility=\"hide\"; 861 else if(ie4)pop.visibility=\"hidden\"; 862 else if(ns6)pop.style.visibility=\"hidden\"; 863 } else { self.status = \"Error - no popup div defined.\"; } 864 endtime = 0; 865} 866function settext(s) { 867 if( pop != null ) { 868 if(ns4){ 869 pop.document.write(s); 870 pop.document.close(); 871 pop.visibility=\"show\"; 872 }else if(ie4){ 873 self.document.all['dpopup'].innerHTML=s; 874 pop.visibility=\"visible\"; 875 }else if(ns6){ 876 range=self.document.createRange(); 877 range.setStartBefore(pop); 878 domfrag=range.createContextualFragment(s); 879 while(pop.hasChildNodes()){ pop.removeChild(pop.lastChild); } 880 pop.appendChild(domfrag); 881 pop.style.visibility=\"visible\"; 882 } // else { self.status = \"Error - cannot determine brower\"; } 883 } else { self.status = \"Error - no popup div available\"; } 884} 885function repositionTo(obj,xL,yL){ 886 if((ns4)||(ie4)){ obj.left=xL; obj.top=yL; } 887 else if(ns6){ 888 obj.style.left=xL + \"px\"; 889 obj.style.top=yL+ \"px\"; 890 } 891} 892function fix(n) { var d = n; if(d<10) d=\"0\"+d; return d; } 893function findPosX(obj) 894{ 895 var curleft = 0; 896 if (obj.offsetParent) { 897 while (obj.offsetParent) { 898 curleft += obj.offsetLeft; 899 if( obj.scrollLeft ) curtop -= obj.scrollLeft; 900 obj = obj.offsetParent; 901 } 902 } 903 else { 904 if (obj.x) curleft += obj.x; 905 if( obj.scrollLeft ) curtop -= obj.scrollLeft; 906 } 907 return curleft; 908} 909 910// Here we have a problem - IE gives offset relative to window, Netscape 911// gives relative to frame. So a scrolled window doesnt work in IE. 912function findPosY(obj) 913{ 914 var curtop = 0; 915 if (obj.offsetParent) { 916 while (obj.offsetParent) { 917 curtop += obj.offsetTop; 918 if( obj.scrollTop ) curtop -= obj.scrollTop; 919 obj = obj.offsetParent; 920 } 921 } 922 else { 923 if (obj.y) curtop += obj.y; 924 if( obj.scrollTop ) curtop -= obj.scrollTop; 925 } 926 return curtop; 927} 928 929function mousemove(e) { 930 var msg, ox, oy, t, extra; 931 var placeX, placeY, winoffset, ohpos, ovpos, iwidth, iheight, scrollheight; 932 var scrolloffset, oaboveheight, d; 933 934 if( ! endtime ) return; 935 if(!e) { e=window.event; } 936 if( typeof(e.pageX)=='number' ) { 937 ox = e.pageX; oy=e.pageY; 938 winoffset = self.pageXOffset; 939 scrolloffset = self.pageYOffset; 940 } else if( typeof(e.clientX)=='number' ) { 941 if( document.documentElement) { 942 winoffset = document.documentElement.scrollLeft; 943 scrolloffset = document.documentElement.scrollTop; 944 ox = e.clientX + winoffset; 945 oy = e.clientY + scrolloffset; 946 } else { 947 winoffset = document.body.scrollLeft; 948 scrolloffset= document.body.scrollTop; 949 ox = e.clientX + winoffset; 950 oy = e.clientY + scrolloffset; 951 } 952 } else if(ie5) { 953 winoffset = self.document.body.scrollLeft; 954 scrolloffset = self.document.body.scrollTop; 955 ox=e.x+winoffset; 956 oy=e.y+scrolloffset; 957 } else { 958 ox = e.x; oy =e.y; 959 winoffset = 0; // guess 960 scrolloffset = 0; 961 } 962 963// ox,oy is where the mouse is. placeX,placeY is where the popup is going 964 965// now determine the frame size (inner width and height) 966 if(ie4){ iwidth=self.document.body.clientWidth; 967 iheight=self.document.body.clientHeight; } 968 else if(ns4){ iwidth=self.innerWidth; iheight=self.innerHeight; } 969 else if(ns6){ iwidth=self.outerWidth; iheight=self.outerHeight; } 970// iwidth is the actual page width. owidth is the bit outside. 971// winoffset is how much we've scrolled horizontally 972// X position for popup 973 placeX = ox+ooffsetx; 974 if(placeX > (iwidth-owidth+winoffset)){ 975 placeX = iwidth-owidth+winoffset ; 976 if(placeX < 0) placeX = 0; // should be impossible 977 } 978// y position for popup 979 if((oy - scrolloffset)> iheight){ ovpos=35; }else{ ovpos=36; } 980 if(ovpos==35){ 981 if(oaboveheight==0){ 982 var divref=(ie4)? self.document.all['dpopup'] : pop; 983 oaboveheight=(ns4)? divref.clip.height : divref.offsetHeight; 984 } 985 placeY=oy -(oaboveheight + ooffsety); 986 if(placeY < scrolloffset)placeY=scrolloffset; // why doesnt this work? 987 }else{ placeY=oy + ooffsety; } 988// relative to image 989 ox -= findPosX(img); oy -= findPosY(img); 990// calculate time at cursor 991 if(( ox >= $xpad ) && ( ox <= (gx+$xpad)) && ( oy >= $ypad ) && ( oy <= (gy+$ypad) )) { 992 if( interval == 1800 ) { // special for weekly 993 t = endtime - 1500 * ($xpad+gx-ox)*gw/gx; // may only be approximate? 994 } else { 995 t = endtime - interval * ($xpad+gx-ox)*gw/gx; // may only be approximate? 996 } 997 } else { t = 0; } 998 if( t ) { 999 // the problem is we want to display this in the timezone of the TARGET. 1000 // t is the UTC time, and the Javascript Date object will give everything 1001 // relative to the workstation timezone. So, we add the tz offset of 1002 // the Target, and subtract the tz offset of the workstation. 1003 // note that the passed tzoffset and that returned by getTimezoneOffset 1004 // seem to be different signs. 1005 d = new Date(t*1000); 1006 d.setTime((t+tzoffset+(d.getTimezoneOffset()*60))*1000); 1007 if( interval > 72000 ) { // dayofweek day/month (yearly graph) 1008"; 1009 # I tawt I taw a Mewwican! 1010 if( defined $config{"web-shortdateformat"} 1011 and $config{"web-shortdateformat"}=~ /\/\%d|\%D/ ) { 1012 # I did! I did taw a Mewwican! 1013 $js .= " msg = dow[d.getDay()]+\" \"+(d.getMonth()+1)+\"/\"+d.getDate();\n"; 1014 } else { 1015 $js .= " msg = dow[d.getDay()]+\" \"+d.getDate()+\"/\"+(d.getMonth()+1);\n"; 1016 } 1017 $js .= " 1018 } else if( interval > 4000 ) { // dayofweek day hour:00 (monthly graph) 1019 msg = dow[d.getDay()]+\" \"+d.getDate()+\" \"+fix(d.getHours())+\":00\"; 1020 } else if( interval > 1000 ) { // dayofweek day time (weekly graph) 1021 msg = dow[d.getDay()]+\" \"+d.getDate()+\" \"+fix(d.getHours())+\":\"+fix(d.getMinutes()); 1022 } else { // time (daily graph) 1023 msg = fix(d.getHours())+\":\"+fix(d.getMinutes()); 1024 } 1025// for debugging the amazingly difficult timezone calculations 1026// msg = msg + \" \" + d.getDay() + \"<BR>\" + endtime + \":\" + t + \"<BR>\" + tzoffset + \":\" + (d.getTimezoneOffset()*60); 1027 extra = getextra(t); 1028 settext(\"<STRONG>\"+msg+\"</STRONG>\"+extra); 1029 repositionTo(pop, placeX, placeY); 1030 } else { 1031 if(ns4)pop.visibility=\"hide\"; 1032 else if(ie4)pop.visibility=\"hidden\"; 1033 else if(ns6)pop.style.visibility=\"hidden\"; 1034 } 1035} 1036 1037function timepopup(o,n,px,py,i,t,dx,tzo) { 1038 divname = n; img = o; gx = px; gy = py; interval = i; endtime = t; gw = dx; 1039 tzoffset = tzo; 1040 if(ns4) { pop=self.document.dpopup; } 1041 else if(ie4) { if(self.dpopup) { pop=self.dpopup.style;} else { endtime=0;}} 1042 else if(ns6) { pop=self.document.getElementById(\"dpopup\"); } 1043 else { endtime = 0; } 1044}"; 1045 } 1046 return $js; 1047} 1048 1049################################# 1050# For persistent caching. This requires the settings in the routers2.conf 1051# to specify caching, and specify a caching file. 1052# Return 0 if worked, 1 if it didnt. 1053# When loading the cache, set $^T to the modify date of the cache file. 1054sub write_cache() 1055{ 1056 my($f); 1057 return 0 if(!defined $config{'routers.cgi-cachepath'}); 1058 $debugmessage .= "Saving cache file...\n"; 1059 eval { require Data::Dumper; }; return 1 if($@); 1060 $f = $config{'routers.cgi-cachepath'}."/routers2.cache"; 1061 open C,">$f" or return 1; 1062 print C Data::Dumper->Dump([\%routerscache], 1063 [qw(savrc)]); 1064# print C Data::Dumper->Dump([\%routerscache,\%cachedays,\%ifstore], 1065# [qw(savrc savcd savis)]); 1066 close C; 1067 $debugmessage .= "...done.\n"; 1068 return 0; 1069} 1070sub load_cache() 1071{ 1072 my(@s,$f,$d); 1073 my($savis,$savrc,$savcd); 1074 return 0 if(!defined $config{'routers.cgi-cachepath'}); 1075 $debugmessage .= "Checking Cache file\n"; 1076 return 0 if($readinrouters); 1077 $debugmessage .= "Attempting to load Cache file\n"; 1078 eval { require Data::Dumper; }; 1079 if($@) { $debugmessage .= "Unable to load: $@\n"; return 1; } 1080 $f = $config{'routers.cgi-cachepath'}."/routers2.cache"; 1081 open C,"<$f" or do { 1082 $debugmessage .= "Failed to open cache file: $!\n"; 1083 return 1; }; 1084 $d = ""; while( <C> ) { $d .= $_; }; 1085 @s = stat C; $^T = $s[9]; # in case the file is too old 1086 close C; 1087 $debugmessage .= "Trying to eval cache file contents\n"; 1088 eval $d; 1089# if($@) { %routerscache = (); %cachedays = (); %ifstore = (); return 1; } 1090# %routerscache = %$savrc; %cachedays = %$savcd; %ifstore = %$savis; 1091 if($@ or !$savrc) { %routerscache = (); 1092 $debugmessage .= "Failed to eval: $@\n"; 1093 return 1; } 1094 %routerscache = %$savrc; 1095 $debugmessage .= "Cache file loaded OK\n"; 1096 return 0; 1097} 1098################################# 1099# Create a bar graph, as requested by the CGI parameters. 1100# This should be given two CGI parameters: IN and OUT. Use GD libraries if 1101# available to make a simple bar with green bar and blue line. IN and OUT are 1102# supposed to be percentages. 1103sub do_bar() 1104{ 1105 my( $gd, $black, $white, $green, $blue, $grey ); 1106 my( $w, $h ) = (400,10); 1107 my($x1,$x2); 1108 1109 eval { require GD; }; 1110 if($@) { 1111 # GD libraries not available. So, redirect to error message graphic. 1112 print $q->redirect($config{'routers.cgi-iconurl'}."error.gif"); 1113 return; 1114 } 1115 1116 if( defined $q->param('L') ) 1117 { $w = $q->param('L') if($q->param('L') >100); } 1118 1119 # We have GD. So, make up a simple bar graphic and print it - after 1120 # giving the correct HTML headers of course. 1121 $gd = new GD::Image($w,$h); 1122 $black = $gd->colorAllocate(0,0,0); 1123 $white = $gd->colorAllocate(255,255,255); 1124 $green = $gd->colorAllocate(0,255,0); 1125 $blue = $gd->colorAllocate(0,0,255); 1126 $grey = $gd->colorAllocate(192,192,192); 1127 1128 if( $q->param('IN') < 0 and $q->param('OUT') < 0) { 1129 # unknown data 1130 $gd->fill(1,1,$grey); # background 1131 } else { 1132 $gd->fill(1,1,$white); # background 1133 $x1 = $w * $q->param('IN') /100.0 ; 1134 $x2 = $w * $q->param('OUT') /100.0 ; 1135 $gd->rectangle(0,0,$x1-1,(($x2>=0)?($h/2):$h)-1,$green) if($x1>1); 1136 $gd->fill(1,1,$green) if($x1 > 2); 1137 $gd->rectangle(0,(($x1>=0)?($h/2):0),$x2-1,$h-1,$blue) if($x2>1); 1138 $gd->fill(1,$h-2,$blue) if($x2 > 2); 1139 } 1140 $gd->rectangle(0,0,$w-1,$h-1,$black); # box around it 1141 1142 if(!$gd->can('gif') or( $gd->can('png') 1143 and defined $config{'web-png'} and $config{'web-png'}=~/[1y]/i )) { 1144 print $q->header({ -type=>"image/png", -expires=>"+6min" }); 1145 binmode STDOUT; 1146 print $gd->png(); 1147 } else { 1148 print $q->header({ -type=>"image/gif", -expires=>"+6min" }); 1149 binmode STDOUT; 1150 print $gd->gif(); 1151 } 1152} 1153# Thanks to Ciaran Anscomb for this idea 1154# Dont forget to add \n to help firefox and older browsers with line 1155# length limitations! 1156sub do_bar_html($$$$$) { 1157 my($barlen,$i,$o,$withi,$witho)=@_; 1158 my($bh)=4; 1159 1160 if( $config{'routers.cgi-stylesheet'} ) { 1161 $bh=8 if(!$witho or !$withi); 1162 print "<TD style='margin-left: 0.5em;'><SMALL>"; 1163 print "<div style='border: 1px solid black; margin: 0; padding: 0; width: ".($barlen-2)."px; height: 8px; background-color: white;'>\n"; 1164 print "<div style='width: $i\%; height: ${bh}px; background-color: #00ff00;'></div>\n" if($withi); 1165 print "<div style='width: $o\%; height: ${bh}px; background-color: #0000ff;'></div>\n" if($witho); 1166 print "</div></SMALL></TD>\n"; 1167 } else { 1168 print "<TD align=left><SMALL>"; 1169 print $q->img({border=>0,height=>10,width=>$barlen,src=>"$meurlfull?page=bar&L=$barlen&IN=$i&OUT=$o"}); 1170 print "</SMALL></TD>\n"; 1171 } 1172 1173} 1174 1175################################# 1176# Read in language file 1177sub readlang($) { 1178 my($l) = $_[0]; 1179 my($f,$sec); 1180 1181 return "Cached" if( defined $lang{$l} ); # already read it 1182 if(defined $config{'web-langdir'}) { 1183 $f = $config{'web-langdir'} ; 1184 } else { 1185 $f = dirname($conffile); 1186 } 1187 $f .= $pathsep."lang_$l.conf"; 1188 return "Language file not present" if(! -r $f); # no language file defined 1189 1190 open LFH,"<$f" or return; 1191 $lang{$l} = { file=>$f }; 1192 $sec = ""; 1193 while( <LFH> ) { 1194 /^\s*#/ && next; 1195 /\[(.*)\]/ && do { $sec = lc $1; }; 1196 chomp; 1197 /^\s*(\S+)\s*=\s*(\S.*?)\s*$/ and $lang{$l}{"$sec-$1"}=$2; 1198 } 1199 close LFH; 1200 return 0; 1201} 1202sub langmsg($$) { 1203 my($code,$default) = @_; 1204 return $default if(!$language); # no language defined 1205 return $default if(!defined $lang{$language}); # language not loaded 1206 return $lang{$language}{"messages-$code"} 1207 if($lang{$language}{"messages-$code"}); 1208 return $default; 1209} 1210sub langinfo { 1211 return "None" if(!$language); 1212 return "Language $language not loaded" if(!defined $lang{$language}); 1213 return $lang{$language}{"global-description"} 1214 ." Ver ".$lang{$language}{"global-version"}.", " 1215 .$lang{$language}{"global-author"}; 1216} 1217sub langhtml($$) { 1218 my($m); 1219 $m = langmsg($_[0],$_[1]); 1220 $m =~ s/ / /g; $m =~ s/</</g; $m =~ s/>/>/g; 1221 return $m; 1222} 1223sub initlang { 1224 my($l) = $_[0]; 1225 my($rv); 1226 1227 initlabels(); 1228 if($l) { 1229 $language = $l; 1230 } else { 1231 $language = ''; 1232 $language = $config{'routers.cgi-language'} 1233 if(defined $config{'routers.cgi-language'}); 1234 $language = $q->cookie('lang') if(!defined $l and $q->cookie('lang')); 1235 } 1236 return if(!$language); 1237 $rv = readlang($language); 1238 $debugmessage .= "Lang=[$rv] "; 1239 return if(!defined $lang{$language}); 1240 # load the per-language defaults 1241 foreach ( qw/windowtitle iconurl charset weeknumber hournumber/ ) { 1242 $config{"routers.cgi-$_"} = $lang{$language}{"global-$_"} 1243 if(defined $lang{$language}{"global-$_"}); 1244 } 1245 foreach ( qw/shortdateformat longdateformat dateonlyformat/ ) { 1246 $config{"web-$_"} = $lang{$language}{"global-$_"} 1247 if(defined $lang{$language}{"global-$_"}); 1248 } 1249 $config{'routers.cgi-iconurl'} .= "/" 1250 if( $config{'routers.cgi-iconurl'} !~ /\/$/ ); 1251 foreach ( keys %gtypes ) { 1252 $gtypes{$_} = $lang{$language}{"types-$_"} 1253 if( defined $lang{$language}{"types-$_"} ); 1254 } 1255 foreach ( keys %gstyles ) { 1256 $gstyles{$_} = $lang{$language}{"styles-$_"} 1257 if( defined $lang{$language}{"styles-$_"} ); 1258 } 1259} 1260 1261################################# 1262# Special start_html 1263# 1264# Attributes are defined at 4 levels. 1265# 1. style on element. Only used for the popup div to override everything. 1266# 2. style in page header. Used for user colour defaults in routers2.conf 1267# 3. stylesheet. Used for most stuff, unless... 1268# 4. element attributes. Only used if no stylesheet definitions 1269sub start_html_ss 1270{ 1271 my($opts,$bgopt) = @_; 1272 my($ssheet) = ""; 1273 my($bodies) = "body.summary, body.generic, body.compact, body.info, body.interface, body.cpu, body.memory"; 1274 1275 $opts->{-encoding} = $charset if($charset); 1276 1277 $opts->{-head} = [] if(!$opts->{-head}); 1278 push @{$opts->{-head}}, $q->meta({-http_equiv => 'Content-Type', 1279 -content => "text/html; charset=$charset"}) if($charset); 1280 push @{$opts->{-head}}, $q->meta({-http_equiv=>'Refresh',-content=>$headeropts{-Refresh}}) if($headeropts{-Refresh}); 1281 $opts->{-meta} = {charset=>$charset} if($charset); 1282 1283 if(!defined $opts->{'-link'}) { 1284 $opts->{'-link'}=$linkcolour; 1285 $opts->{'-vlink'}=$linkcolour; 1286 $opts->{'-alink'}=$linkcolour; 1287 } 1288 $opts->{'-text'}=$deffgcolour if(!defined $opts->{'-text'}); 1289 $opts->{'-bgcolor'}=$defbgcolour if(!defined $opts->{'-bgcolor'}); 1290 $opts->{'-title'}=$windowtitle if(!defined $opts->{'-title'}); 1291 1292 # If we have overridden things, then put it into the sheet here. 1293 # overriding style sheet using mrtg .cfg file options 1294 if( $bgopt and $opts->{-class}) { 1295 $ssheet .= "body.".$opts->{'-class'}." { background: $bgopt }\n"; 1296 $bodies = "body.compact, body.info"; 1297 } 1298 # overriding style sheet using routers2.conf options 1299 # default pages 1300 if( $config{"routers.cgi-bgcolour"} or $config{"routers.cgi-fgcolour"} ) { 1301 $ssheet .= "body, $bodies { "; 1302 $ssheet .= " color: ".$config{"routers.cgi-fgcolour"}."; " 1303 if($config{"routers.cgi-fgcolour"}); 1304 $ssheet .= " background: ".$config{"routers.cgi-bgcolour"} 1305 if($config{"routers.cgi-bgcolour"}); 1306 $ssheet .= "}\n"; 1307 } 1308 # Auth pages 1309 if( $config{"routers.cgi-authbgcolour"} or $config{"routers.cgi-authfgcolour"} ) { 1310 $ssheet .= "body.auth { "; 1311 $ssheet .= " color: ".$config{"routers.cgi-authfgcolour"}."; " 1312 if($config{"routers.cgi-authfgcolour"}); 1313 $ssheet .= " background: ".$config{"routers.cgi-authbgcolour"} 1314 if($config{"routers.cgi-authbgcolour"}); 1315 $ssheet .= "}\n"; 1316 } 1317 # Menus 1318 if( $config{"routers.cgi-menubgcolour"} or $config{"routers.cgi-menufgcolour"} ) { 1319 $ssheet .= "body.sidemenu, body.header { "; 1320 $ssheet .= " color: ".$config{"routers.cgi-menufgcolour"}."; " 1321 if($config{"routers.cgi-menufgcolour"}); 1322 $ssheet .= " background: ".$config{"routers.cgi-menubgcolour"} 1323 if($config{"routers.cgi-menubgcolour"}); 1324 $ssheet .= "}\n"; 1325 } 1326 # links 1327 $ssheet .= "A:link { color: ".$config{'routers.cgi-linkcolour'}. " }\n " 1328 ."A:visited { color: ".$config{'routers.cgi-linkcolour'}. " }\n " 1329 ."A:hover { color: ".$config{'routers.cgi-linkcolour'}. " } \n" 1330 if($config{'routers.cgi-linkcolour'}); 1331 1332 $opts->{'-style'} = [ { -code=>$ssheet } ]; 1333 if ( ! defined $opts->{'-script'} ) { 1334 $opts->{'-script'} = [ ]; 1335 } elsif(! ref $opts->{'-script'} ) { 1336 $opts->{'-script'} = [ $opts->{'-script'} ]; 1337 } 1338 if($config{'routers.cgi-stylesheet'}) { 1339 push @{$opts->{'-style'}}, { -src=>$config{'routers.cgi-stylesheet'} }; 1340 } 1341 if( $config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'}=~/f/i ) { 1342 push @{$opts->{'-style'}}, { -src=>'/JSCal2/css/jscal2.css' }; 1343# push @{$opts->{'-style'}}, { -src=>'/JSCal2/css/border-radius.css' }; 1344 push @{$opts->{'-style'}}, { -src=>'/JSCal2/css/reduce-spacing-more.css' }; 1345# push @{$opts->{'-style'}}, { -src=>'/JSCal2/css/gold/gold.css' }; 1346 push @{$opts->{'-script'}}, 1347 { -type=>'text/javascript', -src=>'/JSCal2/js/jscal2.js' }; 1348 push @{$opts->{'-script'}}, 1349 { -type=>'text/javascript', -src=>'/JSCal2/js/lang/en.js' }; 1350 if( $language =~ /^(..)/ and ($1 ne 'en')) { 1351 push @{$opts->{'-script'}}, 1352 { -type=>'text/javascript', -src=>"/JSCal2/js/lang/${1}.js" }; 1353 } 1354 } 1355 1356 print $q->start_html($opts)."\n"; 1357 print "<div id=\"dpopup\" style=\"position:absolute; visibility:hidden; z-index:1000;\" class=popup></div>\n"; 1358} 1359################################# 1360# Read in configuration file 1361 1362# readconf: pass it a list of section names 1363# This should really be cached, keyed on $extra$myname$authuser 1364sub readconf(@) 1365{ 1366 my ($inlist, $i, @secs, $sec, $usersec); 1367 1368 @secs = @_; 1369 %config = (); 1370 1371 $usersec = "\177"; 1372 if( $authuser ) { 1373 $usersec = "user-".(lc $authuser) ; 1374 } else { 1375 $usersec = "user-none"; 1376 } 1377 1378 # set defaults 1379 %config = ( 1380 'routers.cgi-confpath' => ".", 1381 'routers.cgi-cfgfiles' => "*.conf *.cfg", 1382 'web-png' => 0 1383 ); 1384 1385 ( open CFH, "<".$conffile ) || do { 1386 print $q->header({-expires=>"now"}); 1387 start_html_ss({ -title => langmsg(8999,"Error"), 1388 -bgcolor => "#ffd0d0", -class => 'error' }); 1389 print $q->h1(langmsg(8999,"Error")) 1390 .$q->p(langmsg(3002,"Cannot read config file")." $conffile."); 1391 print $q->end_html(); 1392 exit(0); 1393 }; 1394 1395 $inlist=0; 1396 $sec = ""; 1397 while( <CFH> ) { 1398 /^\s*#/ && next; 1399 /^\s*\[(.*)\]/ && do { 1400 $sec = lc $1; 1401 $inlist=0; 1402 foreach $i ( @secs ) { 1403 if ( (lc $i) eq $sec ) { $inlist=1; last; } 1404 } 1405 # override for additional sections 1406 # put it here so people cant break things easily 1407 if( !$inlist and 1408 ( $sec eq "extra-$extra" or $sec eq $myname 1409 or $sec eq $usersec ) ) { 1410 $sec = 'routers.cgi'; $inlist = 1; 1411 } 1412 next; 1413 }; 1414 # note final \s* to strip all trailing spaces (which works because 1415 # the *? operator is non-greedy!) This should also take care of 1416 # stripping trailing CR if file created in DOS mode (yeuchk). 1417 if ( $inlist ) { 1418 /^\s*(\S+)\s*=\s*(\S.*?)\s*$/ and $config{"$sec-$1"}=$2; 1419 } 1420 } 1421 close CFH; 1422 1423 # legacy support for old dbdrive directive 1424 if(defined $config{'routers.cgi-dbdrive'} 1425 and $config{'routers.cgi-dbdrive'}) { 1426 $pathsep = "\\"; # and use the DOS path separator 1427 if( $config{'routers.cgi-dbpath'} !~ /^\w:/ ) { 1428 # backwards compatibility to add DB drive on, if not there already 1429 $config{'routers.cgi-dbpath'} = $config{'routers.cgi-dbdrive'} 1430 .":".$config{'routers.cgi-dbpath'}; 1431 } 1432 } 1433 1434 # Activate NT compatibility options. 1435 # $^O is the OS name, NT usually produces 'MSWin32'. By checking for 'Win' 1436 # we should be able to cover most possibilities. 1437 if ( (defined $config{'web-NT'} and $config{'web-NT'}=~/[1y]/i) 1438 or $^O =~ /Win/ or $^O =~ /DOS/i ) { 1439 $dailylabel = "%H"; # Activeperl cant support %k option to strftime 1440 $monthlylabel = "%W"; # Activeperl cant support %V option either.... 1441 $pathsep = "\\"; 1442 $NT = 1; 1443 } 1444 1445 # backwards compatibility for old v1.x users 1446 $config{'routers.cgi-iconurl'} = $config{'routers.cgi-iconpath'} 1447 if( !defined $config{'routers.cgi-iconurl'} 1448 and defined $config{'routers.cgi-iconpath'} ); 1449 1450 # some path corrections: remove trailing path separators on f/s paths 1451 foreach ( qw/dbpath confpath graphpath graphurl/ ) { 1452 $config{"routers.cgi-$_"} =~ s/[\/\\]$//; 1453 } 1454 # and add a trailing path separator on URL paths... 1455 $config{'routers.cgi-iconurl'} = "/rrdicons/" 1456 if(!defined $config{'routers.cgi-iconurl'} ); 1457 $config{'routers.cgi-smalliconurl'} = $config{'routers.cgi-iconurl'} 1458 if( !defined $config{'routers.cgi-smalliconurl'}); 1459 $config{'routers.cgi-iconurl'} = $config{'routers.cgi-alticonurl'} 1460 if( defined $config{'routers.cgi-alticonurl'}); 1461 $config{'routers.cgi-iconurl'} .= "/" 1462 if( $config{'routers.cgi-iconurl'} !~ /\/$/ ); 1463 $config{'routers.cgi-smalliconurl'} .= "/" 1464 if( defined $config{'routers.cgi-smalliconurl'} 1465 and $config{'routers.cgi-smalliconurl'} !~ /\/$/ ); 1466 1467 # get list of configuration files 1468 @cfgfiles = (); 1469 if( $config{'routers.cgi-cfgfiles'} ne 'none' ) { 1470 foreach ( split " ", $config{'routers.cgi-cfgfiles'} ) { 1471 # this may push a 'undef' onto the list, if the glob doesnt match 1472 # anything. We avoid this later... 1473 push @cfgfiles, glob($config{'routers.cgi-confpath'}.$pathsep.$_); 1474 } 1475 } 1476 1477 # fix defaultinterface, if not specified correctly 1478 if( defined $config{'routers.cgi-defaulttarget'} 1479 and ! defined $config{'routers.cgi-defaultinterface'} ) { 1480 $config{'routers.cgi-defaultinterface'} = 1481 $config{'routers.cgi-defaulttarget'} ; 1482 } 1483 if( defined $config{'routers.cgi-defaultinterface'} 1484 and $config{'routers.cgi-defaultinterface'} !~ /^_/ 1485 ) { 1486 $config{'routers.cgi-defaultinterface'} = 1487 "__".$config{'routers.cgi-defaultinterface'}; 1488 $config{'routers.cgi-defaultinterface'} = "_outgoing" 1489 if( $config{'routers.cgi-defaultinterface'} eq "__outgoing" ); 1490 $config{'routers.cgi-defaultinterface'} = "_incoming" 1491 if( $config{'routers.cgi-defaultinterface'} eq "__incoming" ); 1492 $config{'routers.cgi-defaultinterface'} = "_summary_" 1493 if( $config{'routers.cgi-defaultinterface'} eq "__summary" ); 1494 } 1495 1496 # escaping 1497 if( $NT ) { 1498 $config{'routers.cgi-defaultrouter'} =~ s/\\/\//g 1499 if( defined $config{'routers.cgi-defaultrouter'} ); 1500 } 1501 1502 # allow [routers.cgi] section to override [web] section for some 1503 # parameters 1504 $config{'web-backurl'} = $config{'routers.cgi-backurl'} 1505 if(defined $config{'routers.cgi-backurl'}); 1506 1507 # We see if we have specified cache mode, or are in mod_perl, or 1508 # are using speedycgi or fastcgi. 1509 $CACHE = 1 if ( ( defined $config{'routers.cgi-cache'} 1510 and $config{'routers.cgi-cache'} =~ /[y1]/i ) 1511 or (!defined $config{'routers.cgi-cache'} and ( 1512 $ENV{MOD_PERL} or $ENV{FCGI_PROCESS_ID} 1513 or (eval {require CGI::SpeedyCGI} && CGI::SpeedyCGI->i_am_speedy) 1514 ))); 1515 1516 unshift @INC, (split /[\s,]+/,$config{'web-libadd'}) 1517 if(defined $config{'web-libadd'}); 1518} 1519 1520########################## 1521sub do_footer() 1522{ 1523 print "<DIV class=footer>"; 1524 if($uopts !~ /s/) { 1525 print $q->hr."\n<TABLE width=100% border=0 cellpadding=0 class=footer><TR class=footer>\n"; 1526 print "<TD align=left valign=top class=footer id=ftleft width=125px>" 1527 .$q->a( { href=>$APPURL, target=>"_new", class=>'footer' } , 1528 $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}routers2.gif", 1529 alt=>"Routers2.cgi web page", border=>0, width=>120, height=>40, class=>'footer' })).$q->br 1530 .$q->center($q->small($q->a({href=>$WLURL,target=>"_new",class=>'footer',style=>'@media print { display:none; }'},"Say Thanks!"))) 1531 ."</TD><TD valign=top align=left class=footer id=ftmiddle>"; 1532 print $q->small({class=>'footer'},"routers.cgi Version $VERSION : © " 1533 .$q->a({href=>$APPMAIL, class=>'footer'},"Steve Shipway") 1534 ." 2000-2008 : ".$q->a({ href=>$APPURL, target=>"_top", class=>'footer' },$APPURL) 1535 )."\n"; 1536 if($language) { 1537 print $q->br()."<SMALL class=footer>Language pack [$language]"; 1538 print ": ".$lang{$language}{'global-description'} 1539 if($lang{$language}{'global-description'}); 1540 print " Version ".$lang{$language}{'global-version'} 1541 if($lang{$language}{'global-version'}); 1542 print " by ".$lang{$language}{'global-author'} 1543 if($lang{$language}{'global-author'}); 1544 print "</SMALL>\n"; 1545 } 1546 if(!defined $config{'web-paranoia'} or $config{'web-paranoia'}!~/[1y]/i){ 1547 if( -r "/proc/loadavg" ) { 1548 open LA,"</proc/loadavg"; 1549 my($lal) = <LA> ; 1550 $lal =~ /^(\S+)\s+(\S+)\s+(\S+)/ ; 1551 print $q->br()."<SMALL class=footer><I class=footer>Current system load average: $1 $2 $3</I></SMALL>\n"; 1552 close LA; 1553 } 1554 print $q->br()."<SMALL class=footer>Page took ".(int(((times)[0]-$stime)*100)/100)."s to generate</SMALL>"; 1555 } 1556 print "</TD><TD align=right valign=top class=footer id=ftright width=125px>" 1557 .$q->a( { href=>"http://www.rrdtool.org/", target=>"_new", class=>'footer' } , 1558 $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}rrdtool.gif", 1559 alt=>"RRDTool", border=>0, class=>'footer' }) 1560 ).$q->br 1561 .$q->center($q->small($q->a({href=>"http://people.ee.ethz.ch/~oetiker/wish/",target=>"_new",class=>'footer',style=>'@media print { display:none; }'},"Say Thanks!"))) 1562 ."</TD><TR></TABLE>\n"; 1563 } # uopts 1564 if(!defined $config{'web-paranoia'} or $config{'web-paranoia'}!~/[1y]/i){ 1565 print "<!-- R:[$router]\n I:[$interface]\n A:[$archive]\n U:[$authuser] -->\n"; 1566 print "<!--\n$debugmessage-->\n" if($debugmessage); 1567 print "<!-- Refresh: ".$headeropts{-Refresh}." -->\n"; 1568 print "<!-- Expires: ".$headeropts{-expires}." -->\n"; 1569 print "<!-- Language: ".langinfo()." -->\n"; 1570 print "<!-- CF: ".($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"Not defined")." -->\n"; 1571 print "<!-- Archive requested -->\n" if($archiveme); 1572# print "<!-- rrdtool version ".$RRDs::VERSION." -->\n"; 1573 print "<!-- rrdcached=$rrdcached -->\n" if($rrdcached); 1574# print "<!-- \@INC\n".(join "\n",@INC)."\n-->\n"; 1575 print "<!-- Processing took ".((times)[0]-$stime)."s -->\n"; 1576 } 1577 print "</DIV>"; 1578 print $q->end_html(); 1579} 1580sub do_simple_footer() { 1581 print "<DIV class=footer>"; 1582 print $q->hr({class=>'footer'})."\n"; 1583 if(!defined $config{'web-paranoia'} 1584 or $config{'web-paranoia'}=~/[n0]/i) { 1585 print $q->small({class=>'footer'},"routers.cgi Version $VERSION : © " 1586 .$q->a({href=>$APPMAIL,class=>'footer'},"Steve Shipway") 1587 ." 2000-2008 : ".$q->a({ href=>$APPURL, target=>"_top",class=>'footer' },$APPURL) 1588 )."\n" ; 1589 print "<!-- U:[$authuser] -->\n"; 1590 print "<!-- $debugmessage\n-->\n" if($debugmessage); 1591 } 1592 print "</DIV>"; 1593 print $q->end_html(); 1594} 1595########################################################################### 1596# for security - create login page, verify username/password/cookie 1597# routers.conf: 1598# 1599# verify_id -- reads cookies and params, returns verified username 1600sub verify_id { 1601 my($uname,$cookie,$checksum, $token); 1602 1603 $uname = $q->remote_user(); # set by web server 1604 return $uname if($uname); 1605 1606 # now taste cookie 1607 $cookie = $q->cookie('auth'); 1608 return '' if(!$cookie); # no cookie! 1609 return '' if($cookie !~ /^\s*([^:]+):(.*)$/); # this isnt my cookie... 1610 ($uname, $checksum) = ($1,$2); 1611 $token = $uname.$q->remote_host(); 1612 $token .= $CHOCOLATE_CHIP; # secret information 1613# Can't do this because we havent read in the config file yet 1614# $token .= $config{'web-auth-key'} if(defined $config{'web-auth-key'}); 1615 $token = unpack('%32C*',$token); # checksum 1616 if( $config{'web-auth-debug'} ) { 1617 $debugmessage .= "\ncookie[given[$uname:$checksum],test[$token]]\n"; 1618 } 1619 return $uname if( $token eq $checksum ); # yummy cookie 1620 1621 # bleah, nasty taste 1622 return ''; 1623} 1624# call appropriate verification routine 1625sub user_verify($$) { 1626 my($rv) = 0; # default: refuse 1627 my($u,$p) = @_; 1628 1629 # get the auth configuration info 1630 readconf( 'web' ); 1631 1632 if( defined( $config{'web-ldaps-server'} ) ) { 1633 $rv = ldap_verify($u,$p,1); 1634 return $rv if($rv); 1635 } 1636 if( !$rv and defined( $config{'web-ldap-server'} ) ) { 1637 $rv = ldap_verify($u,$p,0); 1638 return $rv if($rv); 1639 } 1640 if( !$rv and defined( $config{'web-mysql-server'} ) ) { 1641 $rv = mysql_verify($u,$p); 1642 return $rv if($rv); 1643 } 1644 if( defined( $config{'web-password-file'} ) ) { 1645 $rv = file_verify($config{'web-password-file'},$u,$p,0); 1646 return $rv if($rv); 1647 } 1648 if( defined( $config{'web-htpasswd-file'} ) ) { 1649 $rv = file_verify($config{'web-htpasswd-file'},$u,$p,1); 1650 return $rv if($rv); 1651 } 1652 if( defined( $config{'web-md5-password-file'} ) ) { 1653 $rv = file_verify($config{'web-md5-password-file'},$u,$p,2); 1654 return $rv if($rv); 1655 } 1656 if( defined( $config{'web-unix-password-file'} ) ) { 1657 $rv = file_verify($config{'web-unix-password-file'},$u,$p,3); 1658 return $rv if($rv); 1659 } 1660 1661 return 0; 1662} 1663# verify against a password file: username:password 1664sub file_verify($$$$) { 1665 my($pwfile,$u,$p,$encmode) = @_; 1666 my($fp,$salt,$cp); 1667 1668 $debugmessage .= " file_verify($pwfile,$u,$p,$encmode)\n" 1669 if( $config{'web-auth-debug'} ); 1670 1671 open PW, "<$pwfile" or return 0; 1672 while( <PW> ) { 1673 if( /([^\s:]+):([^:]+)/ ) { 1674 if($1 eq $u) { 1675 $fp = $2; 1676 chomp $fp; 1677 close PW; # we are returning whatever 1678 if($encmode == 0) { # unencrypted. eek! 1679 return 1 if($p eq $fp); 1680 } elsif ($encmode == 1) { # htpasswd (unix crypt) 1681 if($crypthack) { 1682 require Crypt::UnixCrypt; 1683 $Crypt::UnixCrypt::OVERRIDE_BUILTIN = 1; 1684 } 1685 $salt = substr($fp,0,2); 1686 $cp = crypt($p,$salt); 1687 return 1 if($fp eq $cp); 1688 } elsif ($encmode == 2) { # md5 digest 1689 require Digest::MD5; 1690 return 1 if($fp eq Digest::MD5::md5($p)); 1691 } elsif ($encmode == 3) { # unix crypt 1692 if($crypthack) { 1693 require Crypt::UnixCrypt; 1694 $Crypt::UnixCrypt::OVERRIDE_BUILTIN = 1; 1695 } 1696 $salt = substr($fp,0,2); 1697 $cp = crypt($p,$salt); 1698 return 1 if($fp eq $cp); 1699 } # add new ones here... 1700 if( $config{'web-auth-debug'} ) { 1701 $debugmessage .= "Mismatch password [$u][$p]:[$fp]!=[$cp]\n"; 1702 } 1703 return 0; 1704 } elsif( $config{'web-auth-debug'} ) { 1705 $debugmessage .= "Mismatch user [$1][$u]\n"; 1706 } 1707 } elsif( $config{'web-auth-debug'} ) { 1708 $debugmessage .= "Bad format line $_"; 1709 } 1710 } 1711 close PW; 1712 1713 return 0; # not found 1714} 1715# LDAP verify a username 1716sub ldap_verify($$$) { 1717 my($u, $p, $sec) = @_; 1718 my($dn,$context,$msg); 1719 my($ldap); 1720 my($attr,@attrlist); 1721 1722 if($sec) { 1723 # load the LDAPS module 1724 eval { require IO::Socket::SSL; require Net::LDAPS; }; 1725 if($@) { return 0; } # no Net::LDAPS installed 1726 } else { 1727 # load the LDAP module 1728 eval { require Net::LDAP; }; 1729 if($@) { return 0; } # no Net::LDAP installed 1730 } 1731 1732 # Connect to LDAP and verify username and password 1733 if($sec) { 1734 $ldap = new Net::LDAPS($config{'web-ldaps-server'}); 1735 } else { 1736 $ldap = new Net::LDAP($config{'web-ldap-server'}); 1737 } 1738 if(!$ldap) { return 0; } 1739 @attrlist = ( 'uid','cn' ); 1740 @attrlist = split( " ", $config{'web-ldap-attr'} ) 1741 if( $config{'web-ldap-attr'} ); 1742 1743 foreach $context ( split ":", $config{'web-ldap-context'} ) { 1744 foreach $attr ( @attrlist ) { 1745 $dn = "$attr=$u,".$context; 1746 $msg = $ldap->bind($dn, password=>$p) ; 1747 if(!$msg->is_error) { 1748 $ldap->unbind(); 1749 return 1; 1750 } 1751 } 1752 } 1753 1754 return 0; # not found 1755} 1756# Use mysql to verify a username 1757sub mysql_verify($$) { 1758 my($u, $p) = @_; 1759 my($dsn,$dbh,$sthini); 1760 my($db,$rv,@row); 1761 my($bu,$bp); 1762 1763 eval { require DBI; require DBD::mysql; }; 1764 if($@) { $debugmessage.="MySQL Error: $@\n"; return 0; } 1765 1766 $debugmessage .= "Starting MySQL authentication for user $u\n"; 1767 1768 $db = $config{'web-mysql-database'}; 1769 return 0 if(!$db); 1770 $bu = $config{'web-mysql-user'}; 1771 $bp = $config{'web-mysql-password'}; 1772 1773 $dsn = "DBI:mysql:database=$db;host=".$config{'web-mysql-server'}; 1774 $dbh = DBI->connect($dsn, ($bu?$bu:$u), ($bu?$bp:$p)); 1775 if(!$dbh) { # bind failed 1776 $debugmessage .= "Failed to bind to MySQL database as " 1777 .($bu?$bu:$u)."\n"; 1778 return 0; 1779 } 1780 if(!$bu) { # just doing a bind check 1781 $dbh->disconnect(); # important for mod_perl etc 1782 return 1; # all OK 1783 } 1784 if( ! $config{'web-mysql-table'} ) { 1785 $debugmessage .= "ERROR: No mysql-table name was set in the routers2.conf, although mysql-user and mysql-password were.!\n"; 1786 return 0; 1787 } 1788 $sthini = $dbh->prepare("SELECT PASSWORD(?) `tpass`,`pass` FROM `" 1789 .$config{'web-mysql-table'}."` WHERE `user`=?"); 1790 if(!$sthini) { 1791 $debugmessage .= "Failed to prepare MySQL statement\n"; 1792 $dbh->disconnect; return 0; } 1793 $rv = $sthini->execute($p,$u); 1794 if(!$rv) { 1795 $debugmessage .= "Failed to execute MySQL statement\n"; 1796 $dbh->disconnect; return 0; } 1797 @row = $sthini->fetchrow_array; 1798 $sthini->finish; $dbh->disconnect; 1799 if (!$row[0]) { 1800 $debugmessage .= "User $u was not found in table\n"; 1801 return 0; 1802 } 1803 if ($row[0] eq $row[1]) { return 1; } 1804 return 0; 1805} 1806 1807# generate_cookie -- returns a cookie with current usrname, expiry 1808sub generate_cookie { 1809 my($cookie); 1810 my($exp) = "+10min"; # note this stops wk/mon/yrly autoupdate from working 1811 my($token); 1812 1813 return "" if(!$authuser); 1814 1815 $exp = $config{'web-auth-expire'} if(defined $config{'web-auth-expire'}); 1816 $exp = "+10min" if(!$exp); # some checking for format 1817 1818 $token = $authuser.$q->remote_host; # should really have time here also 1819 $token .= $CHOCOLATE_CHIP; # secret information 1820# $token .= $config{'web-auth-key'} if(defined $config{'web-auth-key'}); 1821 $token = $authuser.':'.unpack('%32C*',$token); # checksum 1822 1823 $cookie = $q->cookie( -name=>'auth', -value=>$token, 1824 -path=>$q->url(-absolute=>1), -expires=>$exp ) ; 1825 1826 return $cookie; 1827} 1828# login_page -- output HTML login form that submits to top level 1829sub login_page { 1830 # this is sent if auth = y and page = top (or blank), 1831 # or if page = login 1832 print $q->header({ -target=>'_top', -expires=>"now" })."\n"; 1833 start_html_ss({ -title =>langmsg(1000,"Login Required"), 1834 -onload => "document.login.username.focus();", 1835 -expires => "now", -bgcolor=>$authbgcolour, -text=>$authfgcolour, 1836 -class => 'auth' }); 1837 print $q->h1(langmsg(1000,"Authentication required"))."\n"; 1838 1839 print "<FORM NAME=login METHOD=POST ACTION=$meurl TARGET=_top>\n"; 1840 1841 print $q->p(langmsg(1001,"Please log in with your appropriate username and password in order to get access to the system."))."\n"; 1842 1843 print "<TABLE BORDER=0 ALIGN=CENTER>\n"; 1844 print $q->Tr($q->td($q->b(langmsg(1002,"Username"))) 1845 .$q->td($q->textfield({name=>'username'}) ))."\n"; 1846 print $q->Tr($q->td($q->b(langmsg(1003,"Password"))) 1847 .$q->td($q->password_field({name=>'password'}) ))."\n"; 1848 print $q->Tr($q->td("") 1849 .$q->td($q->submit({name=>'login',value=>'Login'}) ))."\n"; 1850 print "</TABLE></FORM>\n"; 1851 do_simple_footer; 1852 #print $q->end_html; 1853} 1854# force_login -- output HTML that sends top level to login page 1855sub force_login { 1856 my($javascript); 1857 my($err) = shift; 1858 # Javascript that sets window.location to login URL 1859 # This is created if auth = y and page != login and !authuser 1860 1861 $javascript = "function redir() { "; 1862 $javascript .= "alert('$err'); " if($err); 1863 $javascript .= " window.location = '$meurlfull?page=login'; }"; 1864 1865 $javascript = "function redir() {} " if($config{'web-auth-debug'}); 1866 1867 print $q->header({ -target=>'_top', -expires=>"now" })."\n"; 1868 start_html_ss({ -title =>langmsg(1000,"Login Required"), 1869 -expires => "now", -script => $javascript , -onload => "redir()", 1870 -class => 'auth'}); 1871 print $q->h1({class=>'auth'},langmsg(1000,"Authentication required"))."\n"; 1872 print "Please ".$q->a({href=>"$meurlfull?page=login",class=>'auth'},"login") 1873 ." before continuing.\n"; 1874 print "<!-- $err -->\n"; 1875 do_simple_footer; 1876 #print $q->end_html; 1877} 1878# logout -- set auth cookie to blank, expire now, and redirect to top 1879sub logout_page { 1880 my($cookie,$javascript); 1881 # Javascript that sets window.location to login URL 1882 1883 $javascript = "function redir() { window.location = '$meurlfull?page=main'; }"; 1884 $cookie = $q->cookie( -name=>'auth', -value=>'', 1885 -path=>$q->url(-absolute=>1), -expires=>"now" ) ; 1886 1887 print $q->header({ -target=>'_top', -expires=>"now", 1888 -cookie=>[$cookie] })."\n"; 1889 start_html_ss({ -title =>langmsg(1004,"Logout complete"), 1890 -expires => "now", -script => $javascript , -onload => "redir()", 1891 -bgcolor=>$authbgcolour, -text=>$authfgcolour, -class => 'auth' }); 1892 print $q->h1({class=>'auth'},langmsg(1004,"Logged out of system"))."\n"; 1893 print "Please ".$q->a({href=>"$meurlfull?page=main",class=>'auth'},"go back to the front page") 1894 ." to continue.\n"; 1895 do_simple_footer; 1896 #print $q->end_html; 1897} 1898 1899################################# 1900# Read in files 1901 1902########################################################################### 1903# identify the type of file/interface and set up defaults 1904sub inlist($@) 1905{ 1906 my($pat) = shift @_; 1907 return 0 if(!defined $pat or !$pat or !@_); 1908 foreach (@_) { return 1 if( $_ and /$pat/i ); } 1909 return 0; 1910} 1911sub routerdefaults($) 1912{ 1913 my( $key, $k, %identify ); 1914 1915 $k = $_[0]; 1916 %identify = (); 1917 $identify{icon} = guess_icon(1,$k, $routers{$k}{shdesc}, $routers{$k}{hostname} ); 1918 1919 foreach $key ( keys %identify ) { 1920 $routers{$k}{$key} = $identify{$key} if(!$routers{$k}{$key} ); 1921 } 1922} 1923# possible MODEs: interface, cpu, memory, generic (more to come) 1924sub identify($) { 1925 my( $key, %identify, $k, @d, $mode ); 1926 my($unit,$totunit,$okfile); 1927 my($timel, $times); 1928 1929 $k = $_[0]; 1930 1931 # description defaults 1932 if(defined $config{"targetnames-$k"}) { 1933 $interfaces{$k}{shdesc} = $config{"targetnames-$k"}; 1934 } 1935 if(defined $config{"targettitles-$k"}) { 1936 $interfaces{$k}{desc} = $config{"targettitles-$k"}; 1937 } 1938 if(!defined $interfaces{$k}{shdesc}) { 1939 if(!defined $config{'targetnames-ifdefault'} 1940 or $config{'targetnames-ifdefault'} !~ /target/ ) { 1941 if(defined $interfaces{$k}{ipaddress}) { 1942 $interfaces{$k}{shdesc} = $interfaces{$k}{ipaddress}; 1943 } elsif(defined $interfaces{$k}{ifdesc}) { 1944 $interfaces{$k}{shdesc} = $interfaces{$k}{ifdesc}; 1945 } elsif(defined $interfaces{$k}{ifno}) { 1946 $interfaces{$k}{shdesc} = "#".$interfaces{$k}{ifno}; 1947 } else { 1948# $interfaces{$k}{desc} =~ /^(\S+)/; 1949# $interfaces{$k}{shdesc} = $1; 1950 $interfaces{$k}{shdesc} = $interfaces{$k}{desc}; 1951 } 1952 } 1953 if(defined $config{'targetnames-ifdefault'} 1954 and $config{'targetnames-ifdefault'} =~ /cfgmaker/i ) { 1955 if( $interfaces{$k}{pagetop} =~ /Port Name\s*:[^<]*<\/TD>\s*<TD[^>]*>\s*([^<>\s][^<>]+)</i ) { 1956 $interfaces{$k}{shdesc} = "$1" if($1); 1957 } elsif( $interfaces{$k}{pagetop} =~ /Description\s*:[^<]*<\/TD>\s*<TD[^>]*>\s*([^\s<>][^<>]+)</i ) { 1958 $interfaces{$k}{shdesc} = "$1" if($1); 1959 $interfaces{$k}{'cfgmaker-description'} = $1; 1960 } elsif( $interfaces{$k}{pagetop} =~ /(ifName|Interface)\s*:[^<]*<\/TD>\s*<TD[^>]*>\s*([^\s<>][^<>]+)</i ) { 1961 $interfaces{$k}{shdesc} = "$2" if($2); 1962 } elsif( $interfaces{$k}{pagetop} =~ /Traffic Analysis for (\S+)/i ) { 1963 $interfaces{$k}{shdesc} = "$1" if($1); 1964 }; 1965 if(!$interfaces{$k}{shdesc} and defined $interfaces{$k}{ifdesc}) { 1966 $interfaces{$k}{shdesc} = $interfaces{$k}{ifdesc}; 1967 }; 1968 } 1969 $interfaces{$k}{shdesc} = $k if(!defined $interfaces{$k}{shdesc}); 1970 } 1971 1972 # try and identify the interface 1973 @d = ( $k, $interfaces{$k}{desc}, $interfaces{$k}{shdesc} ); 1974 $mode = ""; 1975 $mode = $interfaces{$k}{mode} if(defined $interfaces{$k}{mode}); 1976 %identify = (); 1977 if(! $mode) { 1978 if( inlist( "cpu", @d ) and ($interfaces{$k}{maxbytes}==100) ) 1979 { $mode = "cpu"; } 1980 elsif( defined $interfaces{$k}{ifno} or defined $interfaces{$k}{ifdesc} 1981 or $interfaces{$k}{isif} or defined $interfaces{$k}{ipaddress} ) 1982 { $mode = "interface"; $interfaces{$k}{isif} = 1; } 1983 elsif(( inlist( "interface", @d ) or inlist("serial",@d) 1984 or inlist( "ATM", @d ) or inlist( "[^mxpe]port\s", @d )) 1985 and !defined $interfaces{$k}{unit} 1986 and !defined $interfaces{$k}{legendi} ) 1987 { $mode = "interface"; } 1988 elsif( inlist( "mem", @d ) ) { $mode = "memory"; } 1989# elsif( inlist( "percent", @d )) { $mode = "percent"; } 1990 else { $mode = "generic"; } 1991 $interfaces{$k}{mode} = $mode; 1992 } 1993 1994 # defaults for everything... 1995 # set appropriate defaults for thismode 1996 $times = "s"; $unit = ""; $totunit = ""; 1997 if(!defined $interfaces{$k}{mult}) { 1998 if($mode eq "interface" and 1999 (!defined $config{'routers.cgi-bytes'} 2000 or $config{'routers.cgi-bytes'} !~ /y/ ) 2001 and !$interfaces{$k}{bytes} 2002 ) { $interfaces{$k}{mult} = 8; $unit = "bits"; } 2003 else { $interfaces{$k}{mult} = 1; } 2004 } 2005 if(!$unit and $interfaces{$k}{bytes}) { $unit = "bytes"; } 2006 if(!$unit and $interfaces{$k}{bits}) { $unit = "bits"; } 2007 if(!$unit and ($mode eq "interface")) { $unit = "bits"; } 2008 $timel = langmsg(2400,"second"); 2009 if($interfaces{$k}{mult} > 3599 ) { 2010 $timel = langmsg(2402,"hour"); $times = "hr"; 2011 if($interfaces{$k}{mult} > 3600) { $unit = "bits"; } 2012 } elsif($interfaces{$k}{mult} >59 ) { 2013 $timel = langmsg(2401,"minute"); $times = "min"; 2014 if($interfaces{$k}{mult} > 60) { $unit = "bits"; } 2015 } elsif($interfaces{$k}{mult} > 1) { $unit = "bits"; } 2016 $totunit = "bytes" if($unit); 2017 $identify{ylegend} = "$unit per $timel"; 2018 $unit = "$unit/$times"; 2019 $unit = "bps" if($unit eq "bits/s"); 2020 $unit = "Bps" if($unit eq "bytes/s"); 2021 $identify{background} = $defbgcolour; 2022 $identify{legendi} = langmsg(6403,"In: "); 2023 $identify{legendo} = langmsg(6404,"Out:"); 2024 $identify{legend1} = langmsg(6405,"Incoming") ; 2025 $identify{legend2} = langmsg(6406,"Outgoing"); 2026 $identify{legend3} = langmsg(6407,"Peak inbound"); 2027 $identify{legend4} = langmsg(6408,"Peak outbound"); 2028 if( defined $config{'routers.cgi-percentile'} 2029 and $config{'routers.cgi-percentile'} =~ /y/i ) { 2030 $identify{percentile} = 1; 2031 $identify{total} = 1; 2032 } else { 2033 $identify{percentile} = 0; 2034 $identify{total} = 0; 2035 } 2036 $identify{factor} = 1; 2037 $identify{percent} = 1; 2038 $identify{unit} = $unit; 2039 $identify{totunit} = $totunit; 2040 $identify{unscaled} = ""; 2041 2042 if($mode eq "interface") { 2043 $identify{ylegend} = "traffic in $unit"; 2044 $identify{legendi} = langmsg(6403,"In: "); 2045 $identify{legendo} = langmsg(6404,"Out:"); 2046 $identify{legend1} = langmsg(6405,"Incoming traffic") ; 2047 $identify{legend2} = langmsg(6406,"Outgoing traffic"); 2048 $identify{legend3} = langmsg(6407,"Peak inbound traffic"); 2049 $identify{legend4} = langmsg(6408,"Peak outbound traffic"); 2050 $identify{icon} = "interface-sm.gif"; 2051 $identify{background} = $defbgcolour; #"#ffffff"; 2052 $identify{unscaled} = "6dwmy"; 2053# $identify{total} = 1; 2054 } elsif( $mode eq "cpu" ) { 2055 $identify{ylegend} = "Percentage use"; 2056 $identify{legendi} = "CPU"; 2057 $identify{unit} = "%"; 2058 $identify{fixunits} = 1; 2059 $identify{totunit} = ""; 2060 $identify{legend1} = "CPU usage"; 2061 $identify{legend3} = "Peak CPU usage"; 2062 $identify{legend2} = ""; 2063 $identify{legend4} = ""; 2064 $identify{icon} = "cpu-sm.gif"; 2065 $identify{background} = $defbgcolour; #"#ffffd0"; 2066 $identify{unscaled} = "6dwmy"; 2067 $identify{percent} = 0; 2068 $identify{total} = 0; 2069 $identify{mult} = 1; 2070 } elsif( $mode eq "memory" ) { 2071 $identify{ylegend} = "Bytes used"; 2072 $identify{legendi} = "MEM"; 2073 $identify{legendo} = "MEM"; 2074 $identify{legend1} = "Memory usage"; 2075 $identify{legend3} = "Peak memory usage"; 2076 $identify{legend2} = "Sec. memory usage"; 2077 $identify{legend4} = "Peak sec memory usage"; 2078 $identify{icon} = "cpu-sm.gif"; 2079 $identify{background} = $defbgcolour; #"#d0d0ff"; 2080 $identify{total} = 0; 2081 $identify{unit} = "bytes"; 2082 $identify{unit} = "bits" if($interfaces{$k}{bits}); 2083 $identify{totunit} = ""; 2084 } elsif( $mode eq "ping" ) { 2085 $identify{totunit} = ""; 2086 $identify{unit} = "ms"; 2087 $identify{fixunits} = 1; 2088 $identify{ylegend} = "milliseconds"; 2089 $identify{legendi} = "High:"; 2090 $identify{legendo} = "Low:"; 2091 $identify{legend1} = "Round trip time range"; 2092 $identify{legend2} = "Round trip time range"; 2093 $identify{legend3} = "High peak 5min RTT"; 2094 $identify{legend4} = "Low peak 5min RTT"; 2095 $identify{icon} = "clock-sm.gif"; 2096 $identify{background} = $defbgcolour; #"#ffffdd"; 2097 $identify{total} = 0; 2098 $identify{percent} = 0; 2099 $identify{percentile} = 0; 2100 $identify{unscaled} = ""; 2101 } elsif( $mode eq "percent" ) { 2102 $identify{totunit} = ""; 2103 $identify{unit} = "%"; 2104 $identify{fixunits} = 1; 2105 $identify{ylegend} = langmsg(2409,"percentage"); 2106 $identify{total} = 0; 2107 $identify{percent} = 0; 2108 $identify{percentile} = 0; 2109 } elsif( $mode eq "relpercent" ) { 2110 $identify{totunit} = ""; 2111 $identify{unit} = "%"; 2112 $identify{fixunits} = 1; 2113 $identify{ylegend} = langmsg(2409,"percentage"); 2114 $identify{total} = 0; 2115 $identify{percent} = 0; 2116 $identify{percentile} = 0; 2117 $identify{legendi} = langmsg(2410,"ratio:"); 2118 $identify{legend1} = langmsg(2411,"Inbound as % of outbound"); 2119 $identify{legend3} = langmsg(2412,"Peak Inbound as % of peak outbound"); 2120 if( defined $interfaces{$k}{ifno} or defined $interfaces{$k}{ifdesc} 2121 or $interfaces{$k}{isif} or defined $interfaces{$k}{ipaddress} ) { 2122 $identify{icon} = "interface-sm.gif"; 2123 } 2124 } 2125 2126 # unscaled default option 2127 if( defined $config{'routers.cgi-unscaled'} ) { 2128 if( $config{'routers.cgi-unscaled'} =~ /[1y]/i ) { 2129 $identify{unscaled} = "6dwmy" ; 2130 } else { 2131 $identify{unscaled} = "" ; 2132 } 2133 } 2134 2135 # set icon 2136 $identify{icon} = guess_icon( 0, $k, $interfaces{$k}{desc}, $interfaces{$k}{shdesc} ) if(!defined $identify{icon}); 2137 2138 # different default for totunit 2139 # if we have a custom 'unit' but no custom 'totunit', then try to be 2140 # a bit more clever. 2141 if( defined $interfaces{$k}{unit} ) { 2142 my( $u ) = $interfaces{$k}{unit}; 2143 if( $u =~ /^(.*)\// ) { 2144 $identify{totunit} = $1; 2145 } elsif( $u =~ /^(.*)ps$/ ) { 2146 $identify{totunit} = $1; 2147 } else { 2148 $identify{totunit} = $u; 2149 } 2150 } 2151 2152 # set the defaults 2153 foreach $key ( keys %identify ) { 2154 $interfaces{$k}{$key} = $identify{$key} 2155 if(!defined $interfaces{$k}{$key} ); 2156 } 2157 2158 $interfaces{$k}{unit2} = $interfaces{$k}{unit} 2159 if(!defined $interfaces{$k}{unit2}); 2160 $interfaces{$k}{totunit2} = $interfaces{$k}{totunit} 2161 if(!defined $interfaces{$k}{totunit2}); 2162 2163 $interfaces{$k}{mult} = 1 if(!defined $interfaces{$k}{mult}); 2164 $interfaces{$k}{maxbytes} = 0 if(!defined $interfaces{$k}{maxbytes}); 2165 $interfaces{$k}{max} = $interfaces{$k}{maxbytes} * $interfaces{$k}{mult}; 2166 $interfaces{$k}{max1} = $interfaces{$k}{maxbytes1} * $interfaces{$k}{mult} 2167 if(defined $interfaces{$k}{maxbytes1}); 2168 $interfaces{$k}{max2} = $interfaces{$k}{maxbytes2} * $interfaces{$k}{mult} 2169 if(defined $interfaces{$k}{maxbytes2}); 2170 # Multiply thresholds by appropriate amount 2171 foreach ( qw/threshmini threshmaxi threshmino threshmaxo upperlimit lowerlimit/ ) { 2172 $interfaces{$k}{$_} *= $interfaces{$k}{mult} 2173 if(defined $interfaces{$k}{$_}); 2174 } 2175 $interfaces{$k}{max} = $interfaces{$k}{max1} if(defined $interfaces{$k}{max1} and $interfaces{$k}{max1} > $interfaces{$k}{max} ); 2176 $interfaces{$k}{max} = $interfaces{$k}{max2} if(defined $interfaces{$k}{max2} and $interfaces{$k}{max2} > $interfaces{$k}{max} ); 2177 $interfaces{$k}{absmax} 2178 = $interfaces{$k}{absmaxbytes} * $interfaces{$k}{mult} 2179 if(defined $interfaces{$k}{absmaxbytes}); 2180 if($interfaces{$k}{factor} and $interfaces{$k}{factor}!=1 ) { 2181 foreach ( 'max','absmax','max1','max2' ) { 2182 $interfaces{$k}{$_} *= $interfaces{$k}{factor} 2183 if(defined $interfaces{$k}{$_}); 2184 } 2185 foreach my $mm ( 'max','min' ) { foreach my $io ( 'i','o' ) { 2186 $interfaces{$k}{"thresh$mm$io"} *= $interfaces{$k}{factor} 2187 if(defined $interfaces{$k}{"thresh$mm$io"}); 2188 }} 2189 } 2190 $interfaces{$k}{noo} = 1 if(!$interfaces{$k}{legend2}); 2191 $interfaces{$k}{noi} = 1 if(!$interfaces{$k}{legend1}); 2192 2193 # catch the stupid people 2194 if($interfaces{$k}{noo} and $interfaces{$k}{noi}) { 2195 $interfaces{$k}{inmenu} = 0; 2196 $interfaces{$k}{insummary} = 0; 2197 $interfaces{$k}{inout} = 0; 2198 } 2199 2200} 2201# guess an appropriate icon. 1st param is 1 for devices menu, 0 for targets 2202# other parameters are a list of attributes to check 2203sub guess_icon($@) 2204{ 2205 my($m) = shift @_; 2206 2207 if($m) { 2208 # these tests for devices menu only 2209 return "cisco-sm.gif" if( inlist "cisco",@_ ); 2210 return "juniper-sm.gif" if( inlist "juniper",@_ ); 2211 return "3com-sm.gif" if( inlist "3com",@_ ); 2212 return "intel-sm.gif" if( inlist "intel",@_ ); 2213 return "router-sm.gif" if( inlist "router",@_ ); 2214 return "switch-sm.gif" if( inlist "switch",@_ ); 2215 return "firewall-sm.gif" if( inlist "firewall",@_ ); 2216 return "ibm-sm.gif" if( inlist "ibm",@_ ); 2217 return "linux-sm.gif" if( inlist "linux",@_ ); 2218 return "freebsd-sm.gif" if( inlist "bsd",@_ ); 2219 return "novell-sm.gif" if( inlist "novell",@_ ); 2220 return "win-sm.gif" if( inlist "windows",@_ ); 2221 } 2222 return "mail-sm.gif" if( inlist 'mail|messages',@_ ); 2223 return "web-sm.gif" if( inlist 'internet',@_ or inlist 'proxy',@_ ); 2224 return "phone-sm.gif" if( inlist 'phone',@_ ); 2225 return "modem-sm.gif" if( inlist 'modem',@_ ); 2226 return "disk-sm.gif" if( inlist 'nfs\w',@_ or inlist 'dsk',@_ ); 2227 return "globe-sm.gif" if( inlist 'dns\w',@_ ); 2228 return "people-sm.gif" if( inlist 'user[s ]',@_ ); 2229 return "server-sm.gif" if( inlist 'server|host',@_ ); 2230 return "web-sm.gif" if( inlist 'web',@_ ); 2231 return "traffic-sm.gif" if( inlist 'traffic',@_ ); 2232 return "chip-sm.gif" if( inlist 'memory|cpu',@_ ); 2233 return "interface-sm.gif" if(!$m and inlist 'interface|serial',@_ ); 2234 return "disk-sm.gif" if( inlist 'dis[kc]|filesystem',@_ ); 2235 return "clock-sm.gif" if( inlist 'time|rtt|ping',@_ ); 2236 return "temp-sm.gif" if( inlist 'temp|climate|environment|heat',@_ ); 2237 return "menu-sm.gif" if( inlist '\wlog',@_ ); 2238 return "interface-sm.gif" if(!$m and inlist 'BRI|eth|tok|ATM|hme',@_ ); 2239 return "load-sm.gif" if( inlist 'load|weight',@_ ); 2240 return "web-sm.gif" if( inlist 'www',@_ ); 2241 2242 if($m) { 2243 # last chance with these less reliable ones 2244 return "mac-sm.gif" if( inlist "mac|apple",@_ ); 2245 return "sun-sm.gif" if( inlist "sun",@_ ); 2246 return "hp-sm.gif" if( inlist "hp",@_ ); 2247 return "win-sm.gif" if( inlist "win|pdc|bdc",@_ ); 2248 } 2249 2250 if($m) { 2251 return $config{'targeticons-filedefault'} 2252 if(defined $config{'targeticons-filedefault'}); 2253 return "menu-sm.gif"; 2254 } else { 2255 return $config{'targeticons-ifdefault'} 2256 if(defined $config{'targeticons-ifdefault'}); 2257 return "target-sm.gif"; 2258 } 2259} 2260 2261# Parse an extension parameters 2262sub parse_ext($) { 2263 my ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = 2264 ("","","cog-sm.gif","graph",0,0,0 ); 2265 my( @tok ) = quotewords('\s+',0,$_[0]); 2266# $desc = shift @tok; 2267# $url = shift @tok; 2268 foreach (@tok) { 2269 if( /^(https?:|ftp|ssh:|telnet:)?\// and !$url ) { $url = $_; next; } 2270 if( /\.(gif|png|jpg)$/ ) { $icon = $_; next; } 2271 if(!$desc) { $desc = $_ ; next; } 2272 if( /^\d+$/ ) { $level = $_; next; } 2273 if( /^insec(ure)?$/ ) { $insec = 1; next; } 2274 if( /^noopt(ion)?s?$/ ) { $noop = 1; next; } 2275 if(!$url) { $url = $_ ; next; } # must be a strange URL 2276 $targ = $_; # Must be a target frame name 2277 } 2278 $desc = "Extension" if(!$desc); 2279 $url = "/" if(!$url); 2280 return ($desc, $url, $icon, $targ, $level, $insec, $noop); 2281} 2282sub parse_link($) { 2283 my ( $desc, $targfile, $icon, $targ, $level ) = 2284 ("Link",$router,"link-general-sm.gif","_summary",0 ); 2285 my( @tok ) = quotewords('\s+',0,$_[0]); 2286 $desc = shift @tok; 2287 $targfile = shift @tok; 2288 foreach (@tok) { 2289 if( /^\d+$/ ) { $level = $_; next; } 2290 if( /\.(gif|png|jpg)$/ ) { $icon = $_; next; } 2291 $targ = $_; # Must be a target frame name 2292 } 2293 return ($desc, $targfile, $icon, $targ, $level); 2294} 2295 2296# read in all routers files. 2297 2298# routers hash: key= filename (within confpath) 2299# data: hash: 2300# keys: filename (full), shdesc, desc, inmenu, hasinout 2301# group, icon 2302 2303sub read_routers() 2304{ 2305 my( $matchstr, $curfile, $curpat, $key, $bn, $group, $f ); 2306 my( $arg, $desc, $url, $icon, $targ, $insec, $level, $noop, $targfile ); 2307 my( $rckey ); 2308 my( $optimise ) = 0; 2309 2310 if($CACHE and (-M $config{'routers.cgi-confpath'} >= 0)) { 2311 # cache key: people may have different cfg file sets! 2312 $rckey = $config{'routers.cgi-confpath'} 2313 .'/'.$config{'routers.cgi-cfgfiles'}; 2314 2315 if(defined $routerscache{$rckey}) { 2316 %routers = %{$routerscache{$rckey}}; 2317 if($router and defined $routers{$router} and 2318 # file has disappeared! 2319 ! -f $routers{$router}{file} ) { 2320 $debugmessage .= "refresh(routers)"; 2321 %routers = (); 2322 %routerscache = (); 2323 } elsif((-M $routers{$router}{file}) < 0 ) { 2324 # config files have changed! 2325 $^T = time; # set 'script init time' to first read of cfg files 2326 %ifstore = (); # clean out all cached info 2327 %routerscache = (); # clean out all cached info 2328 $debugmessage .= "refresh(routers)\n"; 2329 $readinrouters = 0; 2330 %cachedays = (); 2331 } else { 2332 $debugmessage .= "fromcache(routers)\n"; 2333 $readinrouters = 1; 2334 return; 2335 } 2336 } else { 2337 load_cache(); 2338 if(defined $routerscache{$rckey} 2339 and -f $routerscache{$rckey}{$router}{file}) { 2340 %routers = %{$routerscache{$rckey}}; 2341 $debugmessage .= "fromdiskcache(routers)\n"; 2342 $readinrouters = 1; 2343 return; 2344 } else { 2345 $debugmessage .= "Disk cache out of date. Re-reading.\n"; 2346 } 2347 } 2348 } 2349 2350 $optimise = 1 if( defined $config{'routers.cgi-optimise'} 2351 and $config{'routers.cgi-optimise'} =~ /[y1]/i ); 2352 2353 %routers = (); 2354 if(-M $config{'routers.cgi-confpath'} < 0) { 2355 # config files have changed! 2356 $^T = time; # set 'script init time' to first read of cfg files 2357 %ifstore = (); # clean out all cached info 2358 %routerscache = (); # clean out all cached info 2359 %cachedays = (); 2360 $debugmessage .= "refresh(routers)\n"; 2361 $readinrouters = 0; 2362 } 2363 2364FILE: for $curfile ( @cfgfiles ) { 2365 next if(! -f $curfile or ! -r $curfile); 2366 $key = $curfile; 2367 $matchstr = $config{'routers.cgi-confpath'}.$pathsep; 2368 $matchstr =~ s/\\/\\\\/g; 2369 $key =~ s/^$matchstr//; 2370 $f = $bn = basename($curfile,''); 2371 $f =~ s/\.c(fg|onf)$//; 2372 $group = dirname($curfile); 2373 # set the defaults 2374 $routers{$key} = { 2375 file=>$curfile, inmenu=>1, group=>$group, icon=>"", 2376 interval=>5, hastarget=>0 2377 }; 2378 2379 # read the file for any overrides 2380 open CFG,"<$curfile" || do { 2381# $routers{$key}{inmenu}=0; 2382 $routers{$key}{desc}="Error opening file"; 2383 $routers{$key}{icon}="alert-sm.gif"; 2384 next; 2385 }; 2386LINE: while( <CFG> ) { 2387 /^#\s+System:\s+(.*)/ and do { 2388 $desc = $1; 2389 $routers{$key}{'cfgmaker-system'} = $desc; 2390 $routers{$key}{desc} = $desc 2391 if( $desc and defined $config{'targetnames-routerdefault'} 2392 and $config{'targetnames-routerdefault'} =~ /cfgmaker/i ); 2393 next; 2394 }; 2395 /^#\s+(Description|Contact|Location):\s+(.*)/ and do { 2396 ($arg,$desc)=($1,$2); 2397 $routers{$key}{('cfgmaker-'.(lc $arg))} = $desc; 2398 next; 2399 }; 2400 /^\s*#/ && next; # Optimise! 2401 if( /^\s*(routers2?\.cgi\*)?Target\[\S+\]\s*:.*:([^\s@]+)@([^:\s]+)/i ) { 2402 $routers{$key}{community}=$2 if(!$routers{$key}{community}); 2403 $routers{$key}{hostname}=$3 if(!$routers{$key}{hostname}); 2404 $routers{$key}{hastarget}=1; 2405 next; 2406 } 2407 if( /^\s*(routers2?\.cgi\*)?Target\[\S+\]/i ) { 2408 $routers{$key}{hastarget}=1; 2409 next; 2410 } 2411 if( /^\s*(routers2?\.cgi\*)?Include\s*:/i ) { 2412 $routers{$key}{hastarget}=1; # make the assumption 2413 next; 2414 } 2415 if( /^\s*Title\[\S+\]\s*:\s*(.*)/i ) { 2416 $routers{$key}{firsttitle}=$1; 2417 $routers{$key}{hastarget}=1; 2418 last if($optimise); 2419 next; 2420 } 2421 if( /^\s*WorkDir\s*:\s*(.*)/i ) { 2422 $routers{$key}{workdir}=$1; 2423 next; 2424 } 2425 if( /^\s*Interval\s*:\s*([\d\.]+):?(\d*)/i ) { 2426 $routers{$key}{interval}=$1; 2427 $routers{$key}{interval} += $2/60 if($2); 2428 next; 2429 } 2430 next unless( /^\s*routers2?\.cgi\*/i ); # Optimise! 2431 if( /^\s*routers2?\.cgi\*Options\s*:\s*(.*)/i ) { 2432 $routers{$key}{inmenu} = 0 if($1 =~ /ignore/i ); 2433 next; 2434 } 2435 if( /^\s*routers2?\.cgi\*(Descr?|Name|Description)\s*:\s*(.*)/i ) { 2436 $routers{$key}{desc} = $2; 2437 next; 2438 } 2439 if( /^\s*routers2?\.cgi\*Short(Descr?|Name|Description)\s*:\s*(.*)/i ) { 2440 $routers{$key}{shdesc} = $2; 2441 next; 2442 } 2443 if( /^\s*routers2?\.cgi\*Icon\s*:\s*(.*)/i ) { 2444 $routers{$key}{icon}=$1; 2445 next; 2446 } 2447 if( /^\s*routers2?\.cgi\*Ignore\s*:\s*(\S+)/i ) { 2448 $arg = $1; 2449 if($arg =~ /y/i) { 2450 delete $routers{$key}; 2451 close CFG; 2452 next FILE; 2453 } 2454 next; 2455 } 2456 if( /^\s*routers2?\.cgi\*InMenu\s*:\s*(\S+)/i ) { 2457 $arg = $1; 2458 $routers{$key}{inmenu}=0 if($arg =~ /n/i); 2459 next; 2460 } 2461 if( /^\s*routers2?\.cgi\*RoutingTable\s*:\s*(\S+)/i ) { 2462 $arg = $1; 2463 $routers{$key}{routingtable}="n" if($arg =~ /[0n]/i); 2464 $routers{$key}{routingtable}="y" if($arg =~ /[1y]/i); 2465 next; 2466 } 2467 if( /^\s*routers2?\.cgi\*ClearExtensions?\s*:\s*(\S.*)/i ) { 2468 $arg = $1; 2469 $routers{$key}{extensions} = [] if($arg =~ /[y1]/i); 2470 next; 2471 } 2472 if( /^\s*routers2?\.cgi\*Extensions?\s*:\s*(\S.*)/i ) { 2473 $arg = $1; 2474 ( $desc, $url, $icon, $targ, $level, $insec, $noop ) = 2475 parse_ext($arg); 2476 2477 next if(!$url or !$desc); 2478 $routers{$key}{extensions} = [] 2479 if(!defined $routers{$key}{extensions}); 2480 my( $lasthostname,$lastcommunity ) = ( '','' ); 2481 $lasthostname = $routers{$key}{hostname} 2482 if( defined $routers{$key}{hostname} ); 2483 $lastcommunity= $routers{$key}{community} 2484 if( defined $routers{$key}{community} ); 2485 push @{$routers{$key}{extensions}}, 2486 {desc=>$desc, url=>$url, icon=>$icon, target=>$targ, 2487 hostname=>$lasthostname, community=>$lastcommunity, 2488 insecure=>$insec, level=>$level, noopts=>$noop }; 2489 next; 2490 } 2491 if( /^\s*routers2?\.cgi\*Link\s*:\s*(\S.*)/i ) { 2492 $arg = $1; 2493 ( $desc, $targfile, $icon, $targ, $level ) 2494 = parse_link($arg); 2495 next if(!$targfile or !$desc); 2496 $icon = "link-general-sm.gif" if(!$icon); 2497 $url = $meurlfull."?rtr=".$q->escape($targfile) 2498 ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; 2499 $routers{$key}{extensions} = [] 2500 if(!defined $routers{$key}{extensions}); 2501 push @{$routers{$key}{extensions}}, 2502 { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", 2503 level=>$level, insecure=>0, noopts=>2 }; 2504 next; 2505 } 2506 if( /^\s*routers2?\.cgi\*Redirect\s*:\s*(\S+)/i ) { 2507 $arg = $1; 2508 $routers{$key}{redirect} = $arg; 2509 $routers{$key}{inmenu} = 1; 2510 $routers{$key}{hastarget} = 1; 2511 next; 2512 } 2513 if( /^\s*routers2?\.cgi\*NoCache\s*:\s*(\S+)/i ) { 2514 $arg = $1; 2515 if($arg=~/[y1]/i) { $routers{$key}{nocache} = 1; } 2516 else { $routers{$key}{nocache} = 0; } 2517 next; 2518 } 2519 if( /^\s*routers2?\.cgi\*Summary\s*:\s*(.*)/i ) { 2520 $arg = $1; 2521 $routers{$key}{summaryoptions} = $arg; 2522 if($arg=~/active/i) { $routers{$key}{activesummary} = 1; } 2523# if($arg=~/2/) { $routers{$key}{activesummary} = 1; } 2524 next; 2525 } 2526 if( /^\s*routers2?\.cgi\*InOut\s*:\s*(\S+)/i ) { 2527 $arg = $1; 2528 if($arg=~/[a2]/i) { $routers{$key}{activeinout} = 1; } 2529 $routers{$key}{inoutoptions} = $1; 2530 next; 2531 } 2532 if( /^\s*routers2?\.cgi\*(Set)?Symbol\s*:\s*(\S+)\s+(.*)/i ) { 2533 ($arg,$desc)=($2,$3); 2534 $desc =~ s/^['"]//; $desc =~ s/['"]$//; # allow quotes 2535 $routers{$key}{symbols}{$arg}=$desc; 2536 next; 2537 } 2538 if( /^\s*routers2?\.cgi\*(Snmp)?Community\s*:\s*(\S+)/i ) { 2539 $routers{$key}{community} = $2; 2540 next; 2541 } 2542 if( /^\s*(routers2?\.cgi\*)?RRDCached\s*:\s*(\S+)/i ) { 2543 $routers{$key}{rrdcached} = $2; 2544 next; 2545 } 2546 } 2547 close CFG; 2548 2549 # desc default 2550 if(!$routers{$key}{shdesc}) { 2551 if($config{'targetnames-routerdefault'} =~ /hostname/ ) { 2552 if(defined $routers{$key}{hostname} ) { 2553 $routers{$key}{shdesc} = $routers{$key}{hostname}; 2554 } else { 2555 $routers{$key}{shdesc} = $f; 2556 } 2557 } elsif($config{'targetnames-routerdefault'} =~ /ai/ 2558 and defined $routers{$key}{firsttitle} ) { 2559 $routers{$key}{firsttitle} =~ /([^\s:\(]+)/; 2560 $routers{$key}{shdesc} = $1; 2561 $routers{$key}{desc} = $routers{$key}{firsttitle}; 2562 } else { 2563 $routers{$key}{shdesc} = $f; 2564# $routers{$key}{desc} = $curfile if(!$routers{$key}{desc}); 2565 } 2566 } 2567 $routers{$key}{desc} = $routers{$key}{shdesc} 2568 if(!$routers{$key}{desc}); 2569 2570 # check routers.conf for any overrides 2571 if(defined $config{"targetnames-$bn"}) { 2572 $routers{$key}{shdesc} = $config{"targetnames-$bn"}; 2573 $routers{$key}{desc} = $config{"targetnames-$bn"}; 2574 } 2575 $routers{$key}{desc} = $config{"targettitles-$bn"} 2576 if(defined $config{"targettitles-$bn"}); 2577 $routers{$key}{icon} = $config{"targeticons-$bn"} 2578 if(defined $config{"targeticons-$bn"}); 2579 2580 routerdefaults $key; 2581# } # files 2582# } # patterns 2583 } # files 2584 2585 foreach $key ( keys %routers ) { 2586 $routers{$key}{inmenu} = 0 if(!$routers{$key}{hastarget}); 2587 } 2588 2589 if( $config{'routers.cgi-servers'} =~ /[yY1]/ ) { 2590 foreach ( keys %config ) { 2591 if( /^servers-(\S+)/i ) { 2592 $routers{"#SERVER#$1"} = { 2593 file=>"", inmenu=>1, group=>"SERVERS", 2594 icon=>"server-sm.gif", server=>$1, interval=>5, 2595 hastarget=>1, inmenu=>1, desc=>$config{$_}, 2596 shdesc=>$config{$_} 2597 }; 2598 $routers{"#SERVER#$1"}{icon} = $config{"targeticons-$1"} 2599 if(defined $config{"targeticons-$1"}); 2600 } 2601 } 2602 } 2603 2604 # we need to copy the hash, not a hashref, since %routers will be 2605 # re-used in future invocations 2606 if($CACHE) { 2607 $routerscache{$rckey} = { %routers }; 2608 $debugmessage .= "cached[routers] \n"; 2609 write_cache; 2610 } else { 2611 $debugmessage .= "NOCACHE[routers] \n"; 2612 } 2613 $readinrouters = 1 ; # for people without caching 2614} 2615 2616########################################################################### 2617 2618# set pseudointerfaces for a server target 2619sub set_svr_ifs() 2620{ 2621 my( $server ); 2622 2623 %interfaces = (); 2624 $server = $router; 2625 $server =~ s/^#SERVER#//; 2626 2627 $interfaces{"CPU"} = { file=>"", icon=>"chip-sm.gif", 2628 rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), 2629 shdesc=>"CPU Usage", mult=>1, unit=>"%", fixunits=>1, 2630 legendi=>"User:", legendo=>"System:", ylegend=>"Percentage", 2631 legendx=>"Wait:", 2632 legend1=>"User processes", legend2=>"System Processes", 2633 legend3=>"Max User Processes", legend4=>"Max System processes", 2634 legend5=>"System Wait", legend6=>"Max system wait", 2635 desc=>"CPU Usage on $server", mode=>"SERVER", hostname=>$server, 2636 insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, 2637 interval=>5, nomax=>1, noabsmax=>1, maxbytes=>100, max=>100, 2638 available=>1 }; 2639 $interfaces{"Users"} = { file=>"", mult=>1,icon=>"people-sm.gif", 2640 rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), 2641 shdesc=>"Users", noo=>1, integer=>1, percent=>0, fixunits=>1, 2642 ylegend=>"User count", 2643 legendi=>"Users:", legend1=>"User count", legend3=>"Max user count", 2644 desc=>"User count on $server", mode=>"SERVER", hostname=>$server, 2645 insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, 2646 interval=>5, nomax=>1, noabsmax=>1, maxbytes=>10000, 2647 available=>1 }; 2648 $interfaces{"Page"} = { file=>"", mult=>1, icon=>"disk-sm.gif", 2649 rrd=>($config{'routers.cgi-dbpath'}.$pathsep."$server.rrd"), 2650 shdesc=>"Paging", noo=>1, unit=>"pps", fixunits=>1, 2651 legendi=>"Activity:", legend1=>"Paging activity", 2652 legend3=>"Max paging activity", percent=>0, ylegend=>"Pages per second", 2653 desc=>"Paging activity on $server", mode=>"SERVER", hostname=>$server, 2654 insummary=>1, incompact=>0, inmenu=>1, isif=>0, inout=>0, 2655 interval=>5, nomax=>1, noabsmax=>1, maxbytes=>10000, 2656 available=>1 }; 2657} 2658 2659########################################################################### 2660# read in a specified cfg file (default to current router file) 2661 2662# interfaces hash: key= targetname 2663# data: hash: 2664# keys: lots. 2665 2666sub read_cfg_file($$) 2667{ 2668 my($cfgfile,$makespecial) = @_; 2669 my($opts, $graph, $key, $k, $fd, $buf, $curif, @myifs, $arg, $argb, $rrd); 2670 my($argc); 2671 my($ifcnt, @ifarr, $t, $desc, $url, $icon, $targ, $newfile, $targfile); 2672 my( $lasthostname, $lastcommunity ) = ("",""); 2673 my($level, $insec, $noop, $logdir); 2674 2675 my( $inpagetop, $inpagefoot ) = (0,0); 2676 2677 return if(!$cfgfile); 2678 2679 $debugmessage .= "$cfgfile "; 2680 2681 $fd = new FileHandle ; 2682 2683 if(! $fd->open( "<$cfgfile" )) { 2684 $interfaces{$cfgfile} = { 2685 shdesc=>"Error", desc=>"Cannot open file $cfgfile", inmenu=>0, 2686 rrd=>"", insummary=>0, inout=>0, incompact=>0, mode=>"ERROR", 2687 icon=>"alert-sm.gif" }; 2688 return; 2689 } 2690 2691 $key = ""; $curif = ""; @myifs = (); 2692 while ( $buf = <$fd> ) { 2693 next if( $buf =~ /^\s*#/ ); 2694 next if( $buf =~ /^\s*$/ ); # bit more efficient 2695 # solve problem of DOS cfg file under UNIX causing Pango layout issues 2696 $buf =~ s/\s+$//; 2697 if( $inpagefoot ) { 2698 if( $curif and $buf =~ /^\s+\S/ ) { 2699 $interfaces{$curif}{pagefoot} .= $buf; 2700 next; 2701 } 2702 $inpagefoot = 0; 2703 } 2704 if( $inpagetop ) { 2705 if( $curif and $buf =~ /^\s+\S/ ) { 2706 $interfaces{$curif}{pagetop} .= $buf; 2707 next; 2708 } 2709 $inpagetop = 0; 2710 } 2711 if( $buf =~ /^\s*(routers2?\.cgi\*)?Target\[(.+?)\]\s*:\s*(.+)/i ) { 2712 $curif = $2; $arg = $3; 2713 push @myifs, $curif; 2714 # This ***MIGHT*** save people who put their .cfg files 2715 # out of sequence? 2716 if(!defined $interfaces{$curif}) { 2717 $interfaces{$curif} = { file=>$cfgfile, target=>$curif, 2718 insummary=>1, incompact=>1, inmenu=>1, isif=>0, 2719 interval=>$interval, nomax=>0, noabsmax=>0 }; 2720 } else { 2721 $interfaces{$curif} = { file=>$cfgfile, target=>$curif, 2722 insummary=>1, incompact=>1, inmenu=>1, isif=>0, 2723 interval=>$interval, nomax=>0, noabsmax=>0, 2724 %{$interfaces{$curif}} }; 2725 } 2726 if(defined $interfaces{_}{directory}) { 2727 $interfaces{$curif}{rrd} = 2728 $workdir.$pathsep.$interfaces{_}{directory} 2729 .$pathsep.(lc $curif).".rrd"; 2730 } else { 2731 $interfaces{$curif}{rrd} = $workdir.$pathsep.(lc $curif).".rrd"; 2732 } 2733 if( $arg =~ /^-?(\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) { 2734 # interface number 2735 $interfaces{$curif}{isif} = 1; 2736 $interfaces{$curif}{ifno} = $1; 2737 $interfaces{$curif}{community} = $2; 2738 $interfaces{$curif}{hostname} = $3; 2739 $interfaces{$curif}{mode} = "interface"; 2740 } elsif( $arg =~ /^-?\/(\d+\.\d+\.\d+\.\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) { 2741 # IP address 2742 $interfaces{$curif}{isif} = 1; 2743 $interfaces{$curif}{ipaddress} = $1; 2744 $interfaces{$curif}{community} = $2; 2745 $interfaces{$curif}{hostname} = $3; 2746 $interfaces{$curif}{mode} = "interface"; 2747 } elsif( $arg =~ /^-?[\\#!](\S.*?):([^\@:\s]+)\@([\w\-\.]+)/ ) { 2748 $interfaces{$curif}{isif} = 1; 2749 $interfaces{$curif}{ifdesc} = $1; 2750 $interfaces{$curif}{community} = $2; 2751 $interfaces{$curif}{hostname} = $3; 2752 $interfaces{$curif}{mode} = "interface"; 2753 $interfaces{$curif}{ifdesc} =~ s/\\(.)/$1/g ; 2754 } elsif( $arg =~ /&\w*[\d\.]+:(\S+)\@([\w\-\.]+)/ ) { 2755 # explicit OIDs 2756 $interfaces{$curif}{community} = $1; 2757 $interfaces{$curif}{hostname} = $2; 2758 } elsif( $arg =~ /mrtg.ping.probe/ ) { 2759 # special for the mrtg-ping-probe.pl 2760 $interfaces{$curif}{mode} = "ping"; 2761 $interfaces{$curif}{graphstyle} = "range"; 2762 $interfaces{$curif}{incompact} = 1; 2763 $interfaces{$curif}{ifdesc} = langmsg(2413,"Response time") ; 2764 } elsif( $arg =~ /`/ ) { 2765 # external program 2766 $interfaces{$curif}{insummary} = 1; 2767 $interfaces{$curif}{incompact} = 1; 2768 } else { # a target of some sort we dont yet know 2769 $interfaces{$curif}{insummary} = 0; 2770 $interfaces{$curif}{incompact} = 0; 2771 } 2772 $interfaces{$curif}{inout} = $interfaces{$curif}{isif}; 2773 foreach $k ( qw/isif inout incompact insummary inmenu/ ) { 2774 $interfaces{$curif}{$k} = $interfaces{'_'}{$k} 2775 if(defined $interfaces{'_'}{$k}); 2776 } 2777 $lasthostname = $interfaces{$curif}{hostname} 2778 if(defined $interfaces{$curif}{hostname}); 2779 $lastcommunity= $interfaces{$curif}{community} 2780 if(defined $interfaces{$curif}{community}); 2781 next; 2782 } 2783 if( $buf =~ /^\s*(routers2?\.cgi\*)?(Title|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) { 2784 $curif = $3; $arg = $4; 2785 if(!defined $interfaces{$curif}) { 2786 if(defined $interfaces{"_$curif"}) { 2787 $curif = "_$curif"; 2788 } else { 2789 $interfaces{$curif} = {note=>"Out of sequence"}; 2790 } 2791 } 2792 $interfaces{$curif}{desc} = $arg; 2793 next; 2794 } 2795 if( $buf =~ /^\s*Options\[(.+?)\]\s*:\s*(\S.*)/i ) { 2796 $curif = $1; 2797 $curif = "_$curif" if(!defined $interfaces{$curif}); 2798 next if(!defined $interfaces{$curif}); 2799 $interfaces{$curif}{options} = "" if(!$interfaces{$curif}{options}); 2800 $interfaces{$curif}{options} .= ' '.$2; 2801 next; 2802 } 2803 if( $buf =~ /^\s*(routers2?\.cgi\*)?PageTop\[(.+?)\]\s*:\s*(\S.*)/i ) { 2804 $curif = $2; $arg = $3; 2805 $curif = "_$curif" if(!defined $interfaces{$curif}); 2806 next if(!defined $interfaces{$curif}); 2807 $interfaces{$curif}{pagetop} = $arg; 2808 $inpagetop = 1; 2809 next; 2810 } 2811 if( $buf =~ /^\s*(routers2?\.cgi\*)?PageFoot\[(.+?)\]\s*:\s*(\S.*)/i ) { 2812 $curif = $2; $arg = $3; 2813 $curif = "_$curif" if(!defined $interfaces{$curif}); 2814 next if(!defined $interfaces{$curif}); 2815 $interfaces{$curif}{pagefoot} = $arg; 2816 $inpagefoot = 1; 2817 next; 2818 } 2819 if( $buf =~ /^\s*(routers2?\.cgi\*)?SetEnv\[(.+?)\]\s*:\s*(\S.*)/i ) { 2820 $curif = $2; $arg = $3; 2821 next if(!defined $interfaces{$curif}); 2822 foreach $k ( quotewords('\s+',0,$arg) ) { 2823 if( $k =~ /MRTG_INT_IP=\s*["]?\s*(\d+\.\d+\.\d+\.\d+)/ ) { 2824 $interfaces{$curif}{ipaddress}=$1 2825 if(!defined $interfaces{$curif}{ipaddress}); 2826 next; 2827 } 2828 if( $k =~ /MRTG_INT_DESCR?=\s*["]?\s*(\S[^"]*)/ ) { 2829 $interfaces{$curif}{shdesc}=$1 2830 if(!defined $interfaces{$curif}{shdesc}); 2831 next; 2832 } 2833 } 2834 next; 2835 } 2836 if( $buf =~ /^\s*routers2?\.cgi\*Short(Name|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) { 2837 $curif = $2; $arg = $3; 2838 $curif = "_$curif" if(!defined $interfaces{$curif}); 2839 next if(!defined $interfaces{$curif}); 2840 $interfaces{$curif}{shdesc} = $arg if($arg); 2841 next; 2842 } 2843 if( $buf =~ /^\s*routers2?\.cgi\*Options\[(.+?)\]\s*:\s*(\S.*)/i ) { 2844 $curif = $1; $arg = $2; 2845 $curif = "_$curif" if(!defined $interfaces{$curif}); 2846 next if(!defined $interfaces{$curif}); 2847 $interfaces{$curif}{cgioptions}="" 2848 if(!$interfaces{$curif}{cgioptions}); 2849 $interfaces{$curif}{cgioptions} .= " ".$arg; 2850 next; 2851 } 2852 if( $buf =~ /^\s*(routers2?\.cgi\*)?MaxBytes\[(.+?)\]\s*:\s*(\d+[\.,]?\d*)/i ) { 2853 next if(!defined $interfaces{$2}); 2854 $interfaces{$2}{maxbytes} = $3; 2855 next; 2856 } 2857 if($buf=~ /^\s*(routers2?\.cgi\*)?Unscaled\[(.+?)\]\s*:\s*([6dwmyn]*)/i){ 2858 $curif = $2; $arg = $3; 2859 next if(!defined $interfaces{$curif}); 2860 $arg = "" if($arg =~ /n/i); # for 'none' or 'n' option 2861 $interfaces{$curif}{unscaled} = $arg; 2862 next; 2863 } 2864 if($buf=~ /^\s*(routers2?\.cgi\*)?WithPeaks?\[(.+?)\]\s*:\s*([dwmyn]*)/i) { 2865 next if(!defined $interfaces{$2}); 2866 $interfaces{$2}{withpeak} = $3; 2867 next; 2868 } 2869 if( $buf =~ /^\s*(routers2?\.cgi\*)?(YLegend2?)\[(.+?)\]\s*:\s*(\S.*)/i ) { 2870 $curif = $3; $arg = $4; $key = lc $2; 2871 $curif = "_$curif" if(!defined $interfaces{$curif}); 2872 next if(!defined $interfaces{$curif}); 2873 $interfaces{$curif}{$key} = $arg; 2874 next; 2875 } 2876 if( $buf =~ /^\s*routers2?\.cgi\*ScaleShift\[(.+?)\]\s*:\s*(\S+)/i ) { 2877 $curif = $1; $arg = $2; 2878 $curif = "_$curif" if(!defined $interfaces{$curif}); 2879 next if(!defined $interfaces{$curif}); 2880 $interfaces{$curif}{scaleshift} = $arg; 2881 if($arg=~/(-?\d+\.?\d*)(:(-?\d+\.?\d*))?/) { 2882 $interfaces{$curif}{scale} = ($1?$1:1); 2883 $interfaces{$curif}{shift} = ($3?$3:0); 2884 } 2885 next; 2886 } 2887 if($buf=~ /^\s*(routers2?\.cgi\*)?ShortLegend(2?)\[(.+?)\]\s*:\s*(.*)/i){ 2888 next if(!defined $interfaces{$3}); 2889 $interfaces{$3}{"unit$2"} = $4; 2890 $interfaces{$3}{"unit$2"} =~ s/ / /g; 2891 next; 2892 } 2893 if($buf =~ /^\s*routers2?\.cgi\*TotalLegend(2?)\[(.+?)\]\s*:\s*(.*)/i){ 2894 $curif = $2; $arg = $3; $key = "totunit$1"; 2895 next if(!defined $interfaces{$curif}); 2896 $arg =~ s/ / /g; 2897 $interfaces{$curif}{$key} = $arg; 2898 next; 2899 } 2900 # We now allow any number of digits for future expansion 2901 if( $buf =~ /^\s*(routers2?\.cgi\*)?(Legend[IOTA\d]\d*[IOTA]?)\[(.+?)\]\s*:\s*(\S.*)/i ) { 2902 $curif = $3; $key = lc $2; $arg = $4; 2903 $curif = "_$curif" if(!defined $interfaces{$curif}); 2904 next if(!defined $interfaces{$curif}); 2905 $arg =~ s/ / /; 2906 # for backwards compatibility. 1T used to be TI, etc 2907 # IT and OT are the new total versions of I and O for userdefineds 2908 $key = "legendti" if($key eq "legend1t"); 2909 $key = "legendto" if($key eq "legend2t"); 2910 $key = "legendai" if($key eq "legend1a"); 2911 $key = "legendao" if($key eq "legend2a"); 2912 $interfaces{$curif}{$key} = $arg; 2913 next; 2914 } 2915 if( $buf =~ /^\s*routers2?\.cgi\*Mode\[(.+?)\]\s*:\s*(\S+)/i ) { 2916 next if(!defined $interfaces{$1}); 2917 $interfaces{$1}{mode} = $2; 2918 next; 2919 } 2920 if( $buf =~ /^\s*routers2?\.cgi\*RoutingTable\s*:\s*(\S.*)/i ) { 2921 $arg = $1; 2922 $routers{$router}{routingtable} = "y" if($arg =~ /y/i); 2923 $routers{$router}{routingtable} = "n" if($arg =~ /n/i); 2924 next; 2925 } 2926 if( $buf =~ /^\s*routers2?\.cgi\*ClearExtensions?\s*:\s*(\S.*)/i 2927 ) { 2928# and !$readinrouters) { 2929 $arg = $1; 2930 $routers{$router}{extensions} = [] if($arg =~ /[y1]/i); 2931 next; 2932 } 2933 if( # !$readinrouters and 2934 $buf =~ /^\s*routers2?\.cgi\*Extensions?\s*:\s*(\S.*)/i ) { 2935 $arg = $1; 2936 ( $desc, $url, $icon, $targ, $level, $insec, $noop ) 2937 = parse_ext($arg); 2938 next if(!$url or !$desc); 2939 $routers{$router}{extensions} = [] 2940 if(!defined $routers{$router}{extensions}); 2941 push @{$routers{$router}{extensions}}, 2942 {desc=>$desc, url=>$url, icon=>$icon, target=>$targ, 2943 hostname=>$lasthostname, community=>$lastcommunity, 2944 insecure=>$insec, level=>$level, noopts=>$noop }; 2945 next; 2946 next; 2947 } 2948 if( # !$readinrouters and 2949 $buf =~ /^\s*routers2?\.cgi\*Link\s*:\s*(\S.*)/i ) { 2950 $arg = $1; 2951 ( $desc, $targfile, $icon, $targ, $level ) 2952 = parse_link($arg); 2953 next if(!$targfile or !$desc); 2954 $icon = "link-general-sm.gif" if(!$icon); 2955 $url = $meurlfull."?rtr=".$q->escape($targfile) 2956 ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; 2957 $routers{$router}{extensions} = [] 2958 if(!defined $routers{$router}{extensions}); 2959 push @{$routers{$router}{extensions}}, 2960 { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", 2961 level=>$level, insecure=>0, noopts=>2 }; 2962 next; 2963 } 2964 if( $buf =~ /^\s*routers2?\.cgi\*Extensions?\[(.+?)\]\s*:\s*(\S.*)/i ) { 2965 $curif = $1; $arg = $2; 2966 $curif = "_$curif" if(!defined $interfaces{$curif}); 2967 next if(!defined $interfaces{$curif}); 2968 ( $desc, $url, $icon, $targ, $level, $insec, $noop ) 2969 = parse_ext($arg); 2970 $interfaces{$curif}{extensions} = [] 2971 if(!defined $interfaces{$curif}{extensions}); 2972 push @{$interfaces{$curif}{extensions}}, 2973 { desc=>$desc, url=>$url, icon=>$icon, target=>$targ, 2974 hostname=>$interfaces{$curif}{hostname}, 2975 community=>$interfaces{$curif}{community}, 2976 level=>$level, insecure=>$insec, noopts=>$noop }; 2977 next; 2978 } 2979 if( $buf =~ /^\s*routers2?\.cgi\*Link\[(.+?)\]\s*:\s*(\S.*)/i ) { 2980 $curif = $1; $arg = $2; 2981 $curif = "_$curif" if(!defined $interfaces{$curif}); 2982 next if(!defined $interfaces{$curif}); 2983# ( $desc, $targfile, $targ, $icon ) = quotewords('\s+',0,$arg); 2984 ( $desc, $targfile, $icon, $targ, $level ) 2985 = parse_link($arg); 2986 next if(!$targfile or !$desc); 2987# if( $targ =~ /\.(gif|png)$/ and !$icon ) { 2988# $icon = $targ; $targ = ""; 2989# } 2990 $icon = "link-general-sm.gif" if(!$icon); 2991 $url = $meurlfull."?rtr=".$q->escape($targfile) 2992 ."&if=".$q->escape($targ)."&page=graph&xmtype=options"; 2993 $interfaces{$curif}{extensions} = [] 2994 if(!defined $interfaces{$curif}{extensions}); 2995 push @{$interfaces{$curif}{extensions}}, 2996 { desc=>$desc, url=>$url, icon=>$icon, target=>"graph", 2997 level=>$level, insecure=>0, noopts=>2 }; 2998 next; 2999 } 3000 if( $buf =~ /^\s*routers2?\.cgi\*(Graph|Summary)\[(.+?)\]\s*:\s*(\S.*)/i ) { 3001 $curif = $2; $arg = $3; $argb = (lc $1); 3002 next if( $curif eq '_' ); # not allowed 3003 if(!defined $interfaces{$curif}) { 3004 if( $argb eq "summary") { 3005 $curif = "_$curif" ; 3006 } else { 3007 # Create a dummy target... 3008 $interfaces{$curif} = { file=>$cfgfile, target=>$curif, 3009 insummary=>0, incompact=>0, inmenu=>0, isif=>0, 3010 interval=>$interval, nomax=>0, noabsmax=>0 }; 3011 if(defined $interfaces{_}{directory}) { 3012 $interfaces{$curif}{rrd} = 3013 $workdir.$pathsep.$interfaces{_}{directory} 3014 .$pathsep.(lc $curif).".rrd"; 3015 } else { 3016 $interfaces{$curif}{rrd} 3017 = $workdir.$pathsep.(lc $curif).".rrd"; 3018 } 3019 } 3020 } 3021 next if(!defined $interfaces{$curif}); 3022 if( $arg =~ /^"/ ) { 3023 $arg =~ /^"([^"]+)"\s*:?(.*)/; 3024 $opts = $2; $graph = $1; 3025 } else { 3026 $arg =~ /^(\S+)\s*:?(.*)/; 3027 $opts = $2; $graph = $1; 3028 } 3029 next if(!$graph); 3030 if( defined $interfaces{"_$graph"} ) { 3031 push @{$interfaces{"_$graph"}{targets}}, $curif 3032 if(!inlist("^$curif\$",@{$interfaces{"_$graph"}{targets}})); 3033 $interfaces{"_$graph"}{cgioptions} .= " $opts"; 3034 $interfaces{"_$graph"}{usergraph} = 1; 3035 } else { 3036 $interfaces{$curif}{usergraphs} = [] 3037 if(!defined $interfaces{$curif}{usergraphs}); 3038 push @{$interfaces{$curif}{usergraphs}}, $graph; 3039 # here we set up various defaults. Anything not set here 3040 # and not set by the user will be inherited from target 1 3041 if( $argb eq "summary" ) { # summary page 3042 $interfaces{"_$graph"} = { 3043 shdesc=>$graph, targets=>[$curif], 3044 cgioptions=>$opts, mode=>"\177_USERSUMMARY", 3045 usergraph=>1, icon=>"summary-sm.gif", 3046 inout=>0, incompact=>0, withtotal=>0, withaverage=>0, 3047 insummary=>0, inmenu=>1, desc=>"Summary $graph", 3048 issummary=>1, pagetop=>"", pagefoot=>"" 3049 }; 3050 } else { # userdefined graph 3051 $interfaces{"_$graph"} = { 3052 shdesc=>$graph, targets=>[$curif], 3053 cgioptions=>$opts, mode=>"\177_USER", 3054 usergraph=>1, icon=>"cog-sm.gif", inout=>0, incompact=>0, 3055 insummary=>0, inmenu=>1, desc=>"User defined graph $graph", 3056 withtotal=>0, withaverage=>0, issummary=>0, 3057 pagetop=>"", pagefoot=>"", factor=>1 3058 }; 3059 $interfaces{"_$graph"}{rrd} = $interfaces{$curif}{rrd}; 3060 } 3061 $interfaces{"_$graph"}{withtotal} = 1 3062 if( defined $config{'routers.cgi-showtotal'} 3063 and $config{'routers.cgi-showtotal'}=~/y/i); 3064 push @myifs, "_$graph"; 3065 } 3066 next; 3067 } 3068 if( $buf =~ /^\s*routers2?\.cgi\*Icon\[(.+?)\]\s*:\s*(\S+)/i ) { 3069 $curif = $1; $arg = $2; 3070 $curif = "_$curif" if(!defined $interfaces{$curif}); 3071 next if(!defined $interfaces{$curif}); 3072 $interfaces{$curif}{icon} = $arg; 3073 next; 3074 } 3075 if( $buf =~ /^\s*routers2?\.cgi\*Ignore\[(.+?)\]\s*:\s*(\S+)/i ) { 3076 $curif = $1; $arg = $2; 3077 $curif = "_$curif" if(!defined $interfaces{$curif}); 3078 next if(!defined $interfaces{$curif}); 3079 if( $arg =~ /y/i ) { 3080 $interfaces{$curif}{insummary} = 0; 3081 $interfaces{$curif}{inmenu} = 0; 3082 $interfaces{$curif}{inout} = 0; 3083 $interfaces{$curif}{isif} = 0; 3084 } 3085 next; 3086 } 3087 if( $buf =~ /^\s*routers2?\.cgi\*InSummary\[(.+?)\]\s*:\s*(\S+)/i ) { 3088 $curif = $1; $arg = $2; 3089 $curif = "_$curif" if(!defined $interfaces{$curif}); 3090 next if(!defined $interfaces{$curif}); 3091 if( $arg =~ /[1y]/i ) { $interfaces{$curif}{insummary} = 1; } 3092 elsif( $arg =~ /[2a]/i ) { $interfaces{$curif}{insummary} = 2; } 3093 else { $interfaces{$curif}{insummary} = 0; } 3094 next; 3095 } 3096 if( $buf =~ /^\s*routers2?\.cgi\*InMenu\[(.+?)\]\s*:\s*(\S+)/i ) { 3097 $curif = $1; $arg = $2; 3098 $curif = "_$curif" if(!defined $interfaces{$curif}); 3099 next if(!defined $interfaces{$curif}); 3100 if( $arg =~ /[1y]/i ) { $interfaces{$curif}{inmenu} = 1; } 3101 elsif( $arg =~ /[2a]/i ) { $interfaces{$curif}{inmenu} = 2; } 3102 else { $interfaces{$curif}{inmenu} = 0; } 3103 next; 3104 } 3105 if( $buf =~ /^\s*routers2?\.cgi\*InOut\[(.+?)\]\s*:\s*(\S+)/i ) { 3106 $curif = $1; $arg = $2; 3107 next if(!defined $interfaces{$curif}); 3108 if( $arg =~ /[1y]/i ) { $interfaces{$curif}{inout} = 1; } 3109 elsif( $arg =~ /[2a]/i ) { $interfaces{$curif}{inout} = 2; } 3110 else { $interfaces{$curif}{inout} = 0; } 3111 next; 3112 } 3113 if( $buf =~ /^\s*routers2?\.cgi\*InCompact\[(.+?)\]\s*:\s*(\S+)/i ) { 3114 $curif = $1; $arg = $2; 3115 next if(!defined $interfaces{$curif}); 3116 if( $arg =~ /[1y]/i ) { $interfaces{$curif}{incompact} = 1; } 3117 elsif( $arg =~ /[2a]/i ) { $interfaces{$curif}{incompact} = 2; } 3118 else { $interfaces{$curif}{incompact} = 0; } 3119 next; 3120 } 3121 if( $buf =~ /^\s*(routers2?\.cgi\*)?Background\[(.+?)\]\s*:\s*(#[a-fA-F\d]+)/i ) { 3122 next if(!defined $interfaces{$2}); 3123 $interfaces{$2}{background} = $3; 3124 $interfaces{$2}{xbackground} = $3; # if using stylesheets 3125 next; 3126 } 3127 if( $buf =~ /^\s*(routers2?\.cgi\*)?Timezone\[(.+?)\]\s*:\s*(\S.*)/i ) { 3128 next if(!defined $interfaces{$2}); 3129 $interfaces{$2}{timezone} = $3; 3130 next; 3131 } 3132 if( $buf =~ /^\s*(routers2?\.cgi\*)?Directory\[(.+?)\]\s*:\s*(\S.*)/i ) { 3133 $curif = $2; $arg = $3; 3134 next if(!defined $interfaces{$curif}); 3135 $arg =~ s/[\s\\\/]+$//; # trim trailing spaces and path separators! 3136 $interfaces{$curif}{rrd} = 3137 $workdir.$pathsep.$arg.$pathsep.(lc $curif).".rrd"; 3138 $interfaces{$curif}{directory} = $arg; 3139 next; 3140 } 3141 if( $buf =~ /^\s*Logdir\s*:\s*(\S+)/i ) { 3142 $logdir = $1; $logdir =~ s/[\\\/]+$//; $workdir = $logdir; next; } 3143 if( $buf =~ /^\s*(routers2?\.cgi\*)?Workdir\s*:\s*(\S+)/i and !$logdir ) { 3144 $workdir = $2; $workdir =~ s/[\\\/]+$//; next; } 3145 if( $buf =~ /^\s*Interval\s*:\s*([\d\.]+):?(\d*)/i ) { 3146 $interval = $1; $interval += $2/60 if($2); next; } 3147 if( $buf =~ /^\s*(routers2?\.cgi\*)?Include\s*:\s*(\S+)/i ) { 3148 $newfile = $2; 3149 $newfile = (dirname $cfgfile).$pathsep.$newfile 3150 if( $newfile !~ /^([a-zA-Z]:)?[\/\\]/ ); 3151 foreach my $d ( glob( $newfile ) ) { 3152 read_cfg_file($d,0); 3153 } 3154 next; 3155 } 3156 if( $buf =~ /^\s*(routers2?\.cgi\*)?LibAdd\s*:\s*(\S+)/i ) { 3157 $interfaces{$curif}{libadd} = $2; 3158 unshift @INC, $1; next; } 3159 if($buf=~ /^\s*(routers2?\.cgi\*)?MaxBytes(\d)\[(.+?)\]\s*:\s*(\d+)/i ){ 3160 $curif = $3; $arg = $4; 3161 next if(!defined $interfaces{$curif}); 3162 $interfaces{$curif}{"maxbytes$2"} = $arg; 3163 $interfaces{$curif}{maxbytes} = $arg 3164 if(!$interfaces{$curif}{maxbytes}); 3165 next; 3166 } 3167 # the regexp from hell - preserved for posterity 3168# 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 ) { 3169 if( $buf =~ /^\s*(routers2?\.cgi\*)?Colou?rs\[(.+?)\]\s*:\s*(.*)/i ) { 3170 $curif = $2; $arg = $3; 3171 $curif = "_$curif" if(!defined $interfaces{$curif}); 3172 next if(!defined $interfaces{$curif}); 3173 $interfaces{$curif}{colours} = []; # null array 3174 while( $arg =~ s/^[\s,]*[^#]*(#[\da-fA-F]{6})[\s,]*//i ) { 3175 push @{$interfaces{$curif}{colours}},$1; 3176 } 3177 $interfaces{$curif}{colours} = [ '#00ff00','#0000ff','#800080','#008000' ] 3178 if($#{$interfaces{$curif}{colours}}<0); 3179 next; 3180 } 3181 if( $buf =~ /^\s*routers2?\.cgi\*MBLegend\[(.+?)\]\s*:\s*(\S.*)/i ) { 3182 $curif = $1; 3183 $curif = "_$curif" if(!defined $interfaces{$curif}); 3184 $interfaces{$curif}{mblegend} = $2; 3185 next; 3186 } 3187 if( $buf =~ /^\s*routers2?\.cgi\*AMLegend\[(.+?)\]\s*:\s*(\S.*)/i ) { 3188 $curif = $1; 3189 $curif = "_$curif" if(!defined $interfaces{$curif}); 3190 $interfaces{$curif}{amlegend} = $2; 3191 next; 3192 } 3193 if( $buf =~ /^\s*(routers2?\.cgi\*)?AbsMax\[(.+?)\]\s*:\s*(\d+[\.,]?\d*)/i ) { 3194 next if(!defined $interfaces{$2}); 3195 $interfaces{$2}{absmaxbytes} = $3; 3196 next; 3197 } 3198 if( $buf =~ /^\s*WeekFormat(\[.+?\])?\s*:\s*%?([UVW])/i ) { 3199 # yes I know this is ugly, it is being retrofitted 3200 $monthlylabel = "%".$2; 3201 next; 3202 } 3203 if( $buf =~ /^\s*routers2?\.cgi\*GraphStyle\[(.+?)\]\s*:\s*(\S+)/i ) { 3204 $curif = $1; $arg = $2; 3205 $curif = "_$curif" if(!defined $interfaces{$curif}); 3206 next if(!defined $interfaces{$curif}); 3207 $interfaces{$curif}{graphstyle} = $arg; 3208 next; 3209 } 3210 if( $buf =~ /^\s*(routers2?\.cgi\*)?Factor\[(.+?)\]\s*:\s*(-?[\d\.,]+)/i ) { 3211 $curif = $2; $arg = $3; 3212 $curif = "_$curif" if(!defined $interfaces{$curif}); 3213 next if(!defined $interfaces{$curif}); 3214 $interfaces{$curif}{factor} = $arg if($arg != 0); 3215 next; 3216 } 3217 if( $buf =~ /^\s*(routers2?\.cgi\*)?Supp?ress?\[(.+?)\]\s*:\s*(\S+)/i ) { 3218 $curif = $2; $arg = $3; 3219 $curif = "_$curif" if(!defined $interfaces{$curif}); 3220 next if(!defined $interfaces{$curif}); 3221 $interfaces{$curif}{suppress} = $arg; 3222 next; 3223 } 3224 if( $buf =~ /^\s*(routers2?\.cgi\*)?UpperLimit\[(.+?)\]\s*:\s*(\d+[\.,]?\d*)/i ) { 3225 $curif = $2; $arg = $3; 3226 $curif = "_$curif" if(!defined $interfaces{$curif}); 3227 next if(!defined $interfaces{$curif}); 3228 $interfaces{$curif}{upperlimit} = $arg; 3229 next; 3230 } 3231 if( $buf =~ /^\s*routers2?\.cgi\*IfNo\[(.+?)\]\s*:\s*(\d+)/i ) { 3232 $curif = $1; $arg = $2; 3233 $curif = "_$curif" if(!defined $interfaces{$curif}); 3234 next if(!defined $interfaces{$curif}); 3235 $interfaces{$curif}{ifno} = $arg; 3236 next; 3237 } 3238 if( $buf =~ /^\s*(routers2?\.cgi\*)?LowerLimit\[(.+?)\]\s*:\s*(\d+[\.,]?\d*)/i ) { 3239 $curif = $2; $arg = $3; 3240 $curif = "_$curif" if(!defined $interfaces{$curif}); 3241 next if(!defined $interfaces{$curif}); 3242 $interfaces{$curif}{lowerlimit} = $arg; 3243 next; 3244 } 3245 if( $buf =~ /^\s*(routers2?\.cgi\*)?(Thresh(Max|Min)[IO])\[(.+?)\]\s*:\s*(\d+[\.,]?\d*)(%?)/i ) { 3246 $curif = $4; $arg = $5; $argb = $6; 3247 $curif = "_$curif" if(!defined $interfaces{$curif}); 3248 next if(!defined $interfaces{$curif}); 3249 if( $argb ) { # Its a percentage! Set here for later usage 3250 $interfaces{$curif}{(lc $2)."pc"} = 1; 3251 } 3252 $interfaces{$curif}{(lc $2)} = $arg; 3253 next; 3254 } 3255 if( $buf =~ /^\s*routers2?\.cgi\*FixUnits?\[(.+?)\]\s*:\s*(\d+)/i ) { 3256 $curif = $1; $arg = $2; 3257 $curif = "_$curif" if(!defined $interfaces{$curif}); 3258 next if(!defined $interfaces{$curif}); 3259 $interfaces{$curif}{exponent} = $arg; 3260 $interfaces{$curif}{fixunits} = 1; # Implied 3261 next; 3262 } 3263 if( $buf =~ /^\s*routers2?\.cgi\*HRule\[(.+?)\]\s*:\s*(-?\d+[\.,]?\d*)\s*"?([^"]*)"?\s*(#([0-9a-f]{6}))?/i ) { 3264 $curif = $1; $arg = $2; $argb = $3; $argc = $5; 3265 $curif = "_$curif" if(!defined $interfaces{$curif}); 3266 next if(!defined $interfaces{$curif}); 3267 $interfaces{$curif}{hrule} = [] 3268 if(!defined($interfaces{$curif}{hrule})); 3269 push @{$interfaces{$curif}{hrule}}, { 3270 value=>$arg, desc=>$argb, colour=>$argc 3271 }; 3272 next; 3273 } 3274 # Experimental: routers.cgi*Line[target]: rpn expression 3275 if( $buf =~ /^\s*routers2?\.cgi\*Line\[(.+?)\]\s*:\s*(\S.*)$/i ) { 3276 $curif = $1; $arg = $2; 3277 $curif = "_$curif" if(!defined $interfaces{$curif}); 3278 next if(!defined $interfaces{$curif}); 3279 next if(!$interfaces{$curif}{usergraph}); 3280 $interfaces{$curif}{lines} = [] 3281 if(!defined($interfaces{$curif}{lines})); 3282 push @{$interfaces{$curif}{lines}}, { 3283 legend1=>"", legendi=>"", legendo=>"", units=>"", 3284 rpn=>[split /[\s,]/,$arg] 3285 }; 3286 next; 3287 } 3288 if( $buf =~ /^\s*routers2?\.cgi\*(Set)?Symbol\[(.+?)\]\s*:\s*(\S+)\s+(.*)$/i ) { 3289 ($curif,$arg,$desc)=($2,$3,$4); 3290 $curif = "_$curif" if(!defined $interfaces{$curif}); 3291 next if(!defined $interfaces{$curif}); 3292 $desc =~ s/^"//; $desc =~ s/"$//; # allow surrounding quotes 3293 $interfaces{$curif}{symbols}{$arg}=$desc; 3294 next; 3295 } 3296 if( $buf =~ /^\s*routers2?\.cgi\*Comment\[(.+?)\]\s*:\s*(.*)$/i ) { 3297 ($curif,$arg)=($1,$2); 3298 $curif = "_$curif" if(!defined $interfaces{$curif}); 3299 next if(!defined $interfaces{$curif}); 3300 if(defined $interfaces{$curif}{comment}) { 3301 push @{$interfaces{$curif}{comment}},$arg; 3302 } else { 3303 $interfaces{$curif}{comment}=[$arg]; 3304 } 3305 next; 3306 } 3307 if( $buf =~ /^\s*routers2?\.cgi\*SortBy\[(.+?)\]\s*:\s*(\S*)/i ) { 3308 ($curif,$arg)=($1,$2); 3309 $curif = "_$curif" if(!defined $interfaces{$curif}); 3310 next if(!defined $interfaces{$curif}); 3311 $interfaces{$curif}{sortby}=$arg; 3312 next; 3313 } 3314 if( $buf =~ /^\s*(routers2?\.cgi\*)?Kilo\[(.+?)\]\s*:\s*(1024|1000)/i ) { 3315 ($curif,$arg)=($2,$3); 3316 $curif = "_$curif" if(!defined $interfaces{$curif}); 3317 next if(!defined $interfaces{$curif}); 3318 $interfaces{$curif}{kilo}=$arg; 3319 next; 3320 } 3321 if( $buf =~ /^\s*(routers2?\.cgi\*)?Kmg\[(.+?)\]\s*:\s*(\S+)/i ) { 3322 ($curif,$arg)=($2,$3); 3323 $curif = "_$curif" if(!defined $interfaces{$curif}); 3324 next if(!defined $interfaces{$curif}); 3325 $interfaces{$curif}{kmg}=[ split /,/,$arg ]; 3326 next; 3327 } 3328 } 3329 $fd->close; 3330 3331 # now take the current file defaults 3332 foreach $key ( keys %{$interfaces{'_'}} ) { 3333 foreach $curif ( @myifs ) { 3334 $interfaces{$curif}{$key} = $interfaces{'_'}{$key} 3335 if(!defined $interfaces{$curif}{$key}); 3336 } 3337 } 3338 foreach $key ( keys %{$interfaces{'^'}} ) { 3339 foreach $curif ( @myifs ) { 3340 $interfaces{$curif}{$key} = $interfaces{'^'}{$key}.' '.$interfaces{$curif}{$key}; 3341 } 3342 } 3343 foreach $key ( keys %{$interfaces{'$'}} ) { 3344 foreach $curif ( @myifs ) { 3345 $interfaces{$curif}{$key} .= ' '.$interfaces{'$'}{$key}; 3346 } 3347 } 3348 # now check for threshold percentages 3349 # we do this now because people may set maxbytes after setting thresh*, 3350 # or may set thresholds as percentages in the default target. 3351 foreach $curif ( @myifs ) { 3352 next if(!$curif); 3353 foreach ( qw/maxi maxo mini mino/ ) { 3354 if( $interfaces{$curif}{"thresh${_}pc"} 3355 and $interfaces{$curif}{maxbytes} ) { 3356 $interfaces{$curif}{"thresh${_}"} = 3357 $interfaces{$curif}{maxbytes} 3358 *( $interfaces{$curif}{"thresh${_}"} /100.0 ); 3359 } #if 3360 }#foreach 3361 }#foreach 3362 3363 # now process the options 3364 foreach $curif ( @myifs ) { 3365 next if(!$curif); 3366 if(defined $interfaces{$curif}{options} ) { 3367 foreach $k ( split /[\s,]+/,$interfaces{$curif}{options} ) { 3368 if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; } 3369 $interfaces{$curif}{noo} = 1 if( $k eq "noo"); 3370 $interfaces{$curif}{noi} = 1 if( $k eq "noi"); 3371 if( $k eq "bits") { 3372 $interfaces{$curif}{bytes} = 0; 3373 $interfaces{$curif}{bits} = 1; } 3374 if( $k eq "perminute") { 3375 $interfaces{$curif}{perminute} = 1 3376 if(!defined $interfaces{$curif}{perhour} 3377 and !defined $interfaces{$curif}{perminute}); 3378 } 3379 if( $k eq "perhour") { 3380 $interfaces{$curif}{perhour} = 1 3381 if(!defined $interfaces{$curif}{perhour} 3382 and !defined $interfaces{$curif}{perminute}); 3383 } 3384 if( $k eq "nopercent") { 3385 $interfaces{$curif}{percent} = 0 ; 3386 # default incompact to NO if target has nopercent set 3387 $interfaces{$curif}{incompact} = 0 3388 if(($interfaces{$curif}{incompact} == 1) 3389 and($interfaces{$curif}{max} ne 100)); 3390 } 3391 if( $k eq "dorelpercent") { 3392 $interfaces{$curif}{noo} = 1; 3393 $interfaces{$curif}{dorelpercent} = 1; 3394 $interfaces{$curif}{fixunits} = 1; 3395 $interfaces{$curif}{percent} = 0; 3396 $interfaces{$curif}{bytes} = 1; 3397 $interfaces{$curif}{bits} = 0; 3398 $interfaces{$curif}{total} = 0; 3399 $interfaces{$curif}{percentile} = 0; 3400 $interfaces{$curif}{perminute} = 0; 3401 $interfaces{$curif}{perhour} = 0; 3402 $interfaces{$curif}{withtotal} = 0; 3403 $interfaces{$curif}{noabsmax} = 1; 3404 $interfaces{$curif}{nomax} = 0; 3405 $interfaces{$curif}{mblegend} = 'Equality'; 3406 $interfaces{$curif}{unit} = '%'; 3407 $interfaces{$curif}{totunit} = ''; 3408 $interfaces{$curif}{ylegend} = 'percentage'; 3409 $interfaces{$curif}{mode} = 'relpercent'; 3410 } 3411 $interfaces{$curif}{integer} = 1 if( $k eq "integer"); 3412 $interfaces{$curif}{logscale} = 1 if( $k eq "logscale"); 3413 } } # if defined options 3414 if ( defined $interfaces{$curif}{cgioptions} ) { 3415 foreach $k ( split /[\s,]+/,$interfaces{$curif}{cgioptions} ) { 3416 if( $k eq "default") { 3417 $routers{$router}{defif} = $curif; 3418 $interfaces{$curif}{default} = 1 ; 3419 next; 3420 } 3421 $interfaces{$curif}{logscale} = 1 if( $k eq "logscale"); 3422 $interfaces{$curif}{withfoot} = 1 if( $k eq "withpagefoot"); 3423 $interfaces{$curif}{withtop} = 1 if( $k eq "withpagetop"); 3424 $interfaces{$curif}{active} = 1 if( $k eq "active"); 3425 $interfaces{$curif}{active} = 1 if( $k eq "activeonly"); 3426 $interfaces{$curif}{cf} = 'MAX' if( $k eq "maximum"); 3427 $interfaces{$curif}{cf} = 'MAX' if( $k eq "maxvalue"); 3428 $interfaces{$curif}{cf} = 'MIN' if( $k eq "minimum"); 3429# $interfaces{$curif}{cf} = 'LAST' if( $k eq "last"); 3430 $interfaces{$curif}{available} = 1 if( $k eq "available"); 3431 $interfaces{$curif}{available} = 0 if( $k eq "noavailable"); 3432 $interfaces{$curif}{noo} = 1 if( $k eq "noo"); 3433 $interfaces{$curif}{noi} = 1 if( $k eq "noi"); 3434 $interfaces{$curif}{noo} = 0 if( $k eq "o"); 3435 $interfaces{$curif}{noi} = 0 if( $k eq "i"); 3436 $interfaces{$curif}{c2fi} = 1 if( $k eq "c2fi"); 3437 $interfaces{$curif}{c2fo} = 1 if( $k eq "c2fo"); 3438# $interfaces{$curif}{mult} = 8 if( $k eq "bits"); 3439# $interfaces{$curif}{mult} = 1 if( $k eq "bytes"); 3440 if( $k eq "bytes") { $interfaces{$curif}{bytes} = 1; 3441 $interfaces{$curif}{bits} = 0; next; } 3442 if( $k eq "bits") { $interfaces{$curif}{bits} = 1; 3443 $interfaces{$curif}{bytes} = 0; next; } 3444 if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; } 3445 if( $k eq "unknasprev") { $interfaces{$curif}{unknasprev} = 1; } 3446 if( $k eq "overridelegend") { $interfaces{$curif}{overridelegend} = 1; } 3447 if( $k eq "perminute") { 3448 $interfaces{$curif}{perminute} = 1 3449 if(!defined $interfaces{$curif}{perhour} 3450 and !defined $interfaces{$curif}{perminute}); 3451 next; 3452 } 3453 if( $k eq "perhour") { 3454 $interfaces{$curif}{perhour} = 1 3455 if(!defined $interfaces{$curif}{perhour} 3456 and !defined $interfaces{$curif}{perminute}); 3457 next; 3458 } 3459 $interfaces{$curif}{isif} = 1 if($k eq "interface"); 3460 if( $k eq "ignore") { 3461 $interfaces{$curif}{inmenu} = 0 ; 3462 $interfaces{$curif}{insummary} = 0 ; 3463 $interfaces{$curif}{inout} = 0 ; 3464 $interfaces{$curif}{incompact} = 0 ; 3465 next; 3466 } 3467 $interfaces{$curif}{unscaled} = "" if( $k eq "scaled"); 3468 if( $k eq "nototal") { 3469 if($interfaces{$curif}{usergraph}) { 3470 $interfaces{$curif}{withtotal} = 0 ; 3471 } else { 3472 $interfaces{$curif}{total} = 0 ; 3473 } 3474 next; 3475 } 3476 $interfaces{$curif}{percentile} = 0 if( $k eq "nopercentile"); 3477 $interfaces{$curif}{percentile} = 1 if( $k eq "percentile"); 3478 if( $k eq "summary" ) { 3479 $interfaces{$curif}{summary} = 1; 3480 $interfaces{$curif}{compact} = 0; 3481 $interfaces{$curif}{withtotal} = 0; 3482 $interfaces{$curif}{withaverage} = 0; 3483 $interfaces{$curif}{insummary} = 0 ; 3484 $interfaces{$curif}{incompact} = 0 ; 3485 next; 3486 } 3487 if( $k eq "compact" ) { 3488 $interfaces{$curif}{summary} = 0; 3489 $interfaces{$curif}{compact} = 1; 3490 $interfaces{$curif}{withtotal} = 0; 3491 $interfaces{$curif}{withaverage} = 0; 3492 $interfaces{$curif}{insummary} = 0; 3493 $interfaces{$curif}{incompact} = 0; 3494 next; 3495 } 3496 if( $k eq "total") { 3497 if($interfaces{$curif}{usergraph}) { 3498 $interfaces{$curif}{withtotal} = 1 ; 3499 } else { 3500 $interfaces{$curif}{total} = 1 ; 3501 } 3502 next; 3503 } 3504 if( $k eq "aspercent") { 3505 $interfaces{$curif}{aspercent} = 1; 3506 $interfaces{$curif}{fixunits} = 1; 3507 $interfaces{$curif}{percent} = 0; 3508 $interfaces{$curif}{bytes} = 1; 3509 $interfaces{$curif}{bits} = 0; 3510 $interfaces{$curif}{total} = 0; 3511 $interfaces{$curif}{percentile} = 0; 3512 $interfaces{$curif}{perminute} = 0; 3513 $interfaces{$curif}{perhour} = 0; 3514 $interfaces{$curif}{withtotal} = 0; 3515 $interfaces{$curif}{noabsmax} = 1; 3516 $interfaces{$curif}{mblegend} = ''; 3517 $interfaces{$curif}{unit} = '%'; 3518 $interfaces{$curif}{totunit} = ''; 3519 $interfaces{$curif}{ylegend} = 'percentage'; 3520 $interfaces{$curif}{mode} = 'percent'; 3521 next; 3522 } 3523 $interfaces{$curif}{withaverage} = 1 if( $k eq "average"); 3524 $interfaces{$curif}{nolegend} = 1 if( $k eq "nolegend"); 3525 $interfaces{$curif}{nodetails} = 1 if( $k eq "nodetails"); 3526 $interfaces{$curif}{nodetails} = 1 if( $k eq "nodetail"); 3527 $interfaces{$curif}{nodesc} = 1 if( $k eq "nodesc"); 3528 $interfaces{$curif}{nogroup} = 1 3529 if( $k eq "nogroup" or $k eq "nogroups"); 3530 $interfaces{$curif}{nogroup} = 0 if( $k eq "group" ); 3531 $interfaces{$curif}{nolines} = 1 if( $k eq "nolines"); 3532 if( $k eq "nomax") { 3533 $interfaces{$curif}{nomax} = 1; 3534 $interfaces{$curif}{percent} = 0; 3535 # percent doesnt make sense if you dont have a maximum 3536 $interfaces{$curif}{incompact} = 0 3537 if($interfaces{$curif}{incompact} == 1); 3538 } 3539 $interfaces{$curif}{noabsmax} = 1 if( $k eq "noabsmax"); 3540 $interfaces{$curif}{percent} = 0 if( $k eq "nopercent"); 3541 $interfaces{$curif}{integer} = 1 if( $k eq "integer"); 3542 $interfaces{$curif}{'reverse'} = 1 if( $k eq "reverse"); 3543 $interfaces{$curif}{rigid} = 1 if( $k eq "rigid"); 3544 if( $k =~ /^#[\da-fA-F]{6}$/ ) { 3545 $interfaces{$curif}{colours} = [] 3546 if(!defined $interfaces{$curif}{colours}); 3547 push @{$interfaces{$curif}{colours}}, $k; 3548 next; 3549 } 3550 $interfaces{$curif}{fixunits} = 1 3551 if( $k =~ /^fixunits?/i or $k =~ /^nounits?/i ); 3552 $interfaces{$curif}{altscale} = 1 if( $k eq "altscale"); 3553 $interfaces{$curif}{altscale} = 0 if( $k eq "noaltscale"); 3554 $interfaces{$curif}{nothresholds} = 1 if( $k eq "nothresholds"); 3555 } 3556 } 3557 # fix the mult 3558 if($interfaces{$curif}{bytes}) { 3559 $interfaces{$curif}{mult} = 1; 3560 } elsif($interfaces{$curif}{bits} ) { 3561 $interfaces{$curif}{mult} = 8; 3562 } 3563 if($interfaces{$curif}{perminute}) { 3564 $interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult}); 3565 $interfaces{$curif}{mult} *= 60; 3566 } elsif($interfaces{$curif}{perhour}) { 3567 $interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult}); 3568 $interfaces{$curif}{mult} *= 3600; 3569 } 3570 # sanity check 3571 if( $interfaces{$curif}{incompact} and 3572 (!$interfaces{$curif}{maxbytes} or $interfaces{$curif}{nomax})){ 3573 $interfaces{$curif}{incompact} = 0; 3574 } 3575 if( $interfaces{$curif}{cf} and $interfaces{$curif}{cf} eq 'MAX'){ 3576 # cant have WithPeak if you have cf=MAX set 3577 $interfaces{$curif}{withpeak} = "n"; 3578 } 3579 3580 # calculate RRD filename 3581 if(!$interfaces{$curif}{usergraph}) { 3582 $rrd = $workdir; 3583 $rrd .= $pathsep.$interfaces{$curif}{directory} 3584 if($interfaces{$curif}{directory}); 3585 $rrd .= $pathsep.lc($interfaces{$curif}{target}).".rrd"; 3586 $interfaces{$curif}{rrd} = $rrd; 3587 } 3588 } 3589 3590 # now read the corresponding .ok file, if it exists 3591 $cfgfile =~ s/\.(conf|cfg)$/.ok/; 3592 if( open OK, "<$cfgfile" ) { 3593 my( %ifdesc ) = (); 3594 my( %ifip ) = (); 3595 while( <OK> ) { 3596 if( /\tDescr\t(.+)\t(\d+)/ ) { 3597 $ifdesc{$2} = $1; $ifdesc{$1} = $2; 3598 } 3599 if( /\tIp\t(.+)\t(\d+)/ ) { 3600 $ifip{$2} = $1; $ifip{$1} = $2; 3601 } 3602 } 3603 close OK; 3604 3605 foreach $curif ( @myifs ) { 3606 if(!defined $interfaces{$curif}{ifno}) { 3607 $interfaces{$curif}{ifno} = $ifdesc{$interfaces{$curif}{ifdesc}} 3608 if(defined $interfaces{$curif}{ifdesc} 3609 and defined $ifdesc{$interfaces{$curif}{ifdesc}}); 3610 $interfaces{$curif}{ifno} = $ifip{$interfaces{$curif}{ipaddress}} 3611 if(defined $interfaces{$curif}{ipaddress} 3612 and defined $ifip{$interfaces{$curif}{ipaddress}}); 3613 } 3614 if(defined $interfaces{$curif}{ifno}) { 3615 $key = $interfaces{$curif}{ifno}; 3616 $interfaces{$curif}{ifdesc} = $ifdesc{$key} 3617 if(defined $ifdesc{$key} and !defined $interfaces{$curif}{ifdesc}); 3618 $interfaces{$curif}{ipaddress} = $ifip{$key} 3619 if(defined $ifip{$key} and !defined $interfaces{$curif}{ipaddress}); 3620 } 3621 } 3622 } # ok file exists 3623 3624 # Creation of special interfaces moved to read_cfg 3625} 3626 3627sub read_cfg() 3628{ 3629 my($cfgfile) = $_[0]; 3630 my($l,$key,$k); 3631 my($ifcnt,$curif,@ifarr); 3632 3633 $cfgfile = $routers{$router}{file} 3634 if(!$cfgfile and $router and defined $routers{$router}); 3635 $cfgfile = $config{'routers.cgi-confpath'}.$pathsep.$router 3636 if(!$cfgfile and $router); 3637 return if (!$cfgfile); 3638 3639 # now, have we done $cfgfile before? 3640 if( $CACHE and defined $ifstore{$cfgfile} 3641 and !$routers{$router}{nocache} and (-M $cfgfile >= 0 )) { 3642 # yes! 3643 %interfaces = %{$ifstore{$cfgfile}}; 3644 $routers{$router}{extensions} = [@{$ifstore{"R:$cfgfile"}}] 3645 if(defined $ifstore{"R:$cfgfile"}); 3646 $debugmessage .= "fromcache($cfgfile)\n"; 3647 return; 3648 } 3649 if( -M $cfgfile < 0 ) { 3650 undef $ifstore{$cfgfile}; 3651 undef $ifstore{"R:$cfgfile"}; 3652 $debugmessage .= "refresh($cfgfile)\n"; 3653 } 3654 3655 $debugmessage .= "Reading: "; 3656 3657 %interfaces = ( '_'=>{x=>0}, '^'=>{x=>0}, '$'=>{x=>0} ); 3658 $interval = 5; 3659 $workdir = $config{'routers.cgi-dbpath'}; 3660 3661 # Clear extension list ready to re-load it 3662 $routers{$router}{extensions} = [] if(defined $routers{$router}); 3663 # recursively read the .cfg file and any includes 3664 read_cfg_file($cfgfile,1); 3665 3666 # zap defaults 3667 delete $interfaces{'_'}; 3668 delete $interfaces{'$'}; 3669 delete $interfaces{'^'}; 3670 delete $interfaces{''} if(defined $interfaces{''}); 3671 3672 # now set up userdefined graphs for Incoming and Outgoing, if it is 3673 # necessary. 3674 $ifcnt = 0; @ifarr = (); $curif=""; 3675 foreach ( keys %interfaces ) { 3676 $curif = $_ if(!$curif and $interfaces{$_}{community} 3677 and $interfaces{$_}{hostname} ); 3678 if($interfaces{$_}{inout}) { 3679 $ifcnt++; 3680 push @ifarr, $_; 3681 } 3682 } 3683 $debugmessage .= "ifcnt=$ifcnt\n"; 3684 if($ifcnt) { 3685 my($t); 3686 $t = ""; 3687 $t = $routers{$router}{shdesc}.": " 3688 if($router and defined $routers{$router} 3689 and defined $routers{$router}{shdesc}); 3690 if( defined $interfaces{'_incoming'} ) { 3691 push @{$interfaces{'_incoming'}{targets}},@ifarr 3692 if( $interfaces{'_incoming'}{mode} =~ /_AUTO/ ); 3693 } else { 3694 $interfaces{'_incoming'} = { 3695 usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, 3696 shdesc=>langmsg(2405,"Incoming"), targets=>[@ifarr], noo=>1, mult=>8, 3697 icon=>"incoming-sm.gif", mode=>"\177_AUTO", 3698 desc=>$t.langmsg(2414,"Incoming traffic"), 3699 withtotal=>0, withaverage=>0, issummary=>0, 3700 graphstyle=>'lines' 3701 }; 3702 $interfaces{'_incoming'}{active} = 1 3703 if($routers{$router}{activeinout}); 3704 if(defined $config{'routers.cgi-showtotal'} 3705 and $config{'routers.cgi-showtotal'}=~ /y/i ) { 3706 $interfaces{'_incoming'}{withtotal} = 1; 3707 } 3708 } 3709 if( defined $interfaces{'_outgoing'} ) { 3710 push @{$interfaces{'_outgoing'}{targets}},@ifarr 3711 if( $interfaces{'_outgoing'}{mode} =~ /_AUTO/ ); 3712 } else { 3713 $interfaces{'_outgoing'} = { 3714 usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, 3715 shdesc=>langmsg(2406,"Outgoing"), targets=>[@ifarr], noi=>1, mult=>8, 3716 icon=>"outgoing-sm.gif", mode=>"\177_AUTO", 3717 desc=>$t.langmsg(2415,"Outgoing traffic"), 3718 withtotal=>0, withaverage=>0, issummary=>0, 3719 graphstyle=>'lines' 3720 }; 3721 $interfaces{'_outgoing'}{active} = 1 3722 if($routers{$router}{activeinout}); 3723 if(defined $config{'routers.cgi-showtotal'} 3724 and $config{'routers.cgi-showtotal'}=~ /[1y]/i ) { 3725 $interfaces{'_outgoing'}{withtotal} = 1; 3726 } 3727 } 3728 } 3729 3730 # Now set up default userdefined summary, if anything is insummary 3731 @ifarr = (); 3732 foreach ( keys %interfaces ) { 3733 push @ifarr, $_ if($interfaces{$_}{insummary}); 3734 # first pass for interfaces 3735 identify $_ if(!$interfaces{$_}{usergraph}); 3736 } 3737 if(@ifarr) { 3738 if( defined $interfaces{'_summary_'} ) { 3739 push @{$interfaces{'_summary_'}{targets}},@ifarr 3740 if( $interfaces{'_summary_'}{mode} =~ /_AUTOSUMMARY/ ); 3741 } else { 3742 $interfaces{'_summary_'} = { 3743 usergraph=>1, insummary=>0, inmenu=>1, inout=>0, incompact=>0, 3744 shdesc=>langmsg(2416,"Summary"), 3745 targets=>[@ifarr], noo=>1, mult=>8, 3746 icon=>"summary-sm.gif", mode=>"\177_AUTOSUMMARY", 3747 withtotal=>0, withaverage=>0, issummary=>1 3748 }; 3749 $interfaces{'_summary_'}{active} = 1 3750 if($routers{$router}{activesummary}); 3751 $interfaces{'_summary_'}{active} = 1 3752 if($routers{$router}{summaryoptions} and $routers{$router}{summaryoptions} =~ /active/); 3753 $interfaces{'_summary_'}{nodetails} = 1 3754 if($routers{$router}{summaryoptions} and $routers{$router}{summaryoptions} =~ /nodetail/); 3755 } 3756 } 3757 3758 # Can we call out to the routingtable.cgi program? 3759 if( defined $config{'routers.cgi-routingtableurl'} and $curif 3760 and ( !defined $routers{$router}{routingtable} 3761 or $routers{$router}{routingtable} =~ /[1y]/i )) { 3762 $routers{$router}{extensions} = [] 3763 if( !defined $routers{$router}{extensions} ); 3764 push @{$routers{$router}{extensions}}, { 3765 url=>$config{'routers.cgi-routingtableurl'}, 3766 desc=>langmsg(2417,"Routing Table"), icon=>"router-sm.gif", 3767 community=>$interfaces{$curif}{community}, 3768 hostname=>$interfaces{$curif}{hostname}, 3769 level=>0, insecure=>1 3770 }; 3771 } 3772 3773 # second pass for user graphs 3774 foreach $key ( keys %interfaces ) { 3775 if($interfaces{$key}{usergraph}) { 3776 $k = $key; $k=~ s/^_//; # chop off initial _ prefix 3777 $interfaces{$key}{shdesc} = $config{"targetnames-$k"} 3778 if(defined $config{"targetnames-$k"}); 3779 $interfaces{$key}{desc} = $config{"targettitles-$k"} 3780 if(defined $config{"targettitles-$k"}); 3781 $interfaces{$key}{icon} = $config{"targeticons-$k"} 3782 if(defined $config{"targeticons-$k"}); 3783 # Inherit most options from first target 3784 foreach $k (keys %{$interfaces{$interfaces{$key}{targets}->[0]}}) { 3785 $interfaces{$key}{$k} 3786 = $interfaces{$interfaces{$key}{targets}->[0]}{$k} 3787 if(!defined $interfaces{$key}{$k} 3788 and ($k ne 'extensions') 3789 and ($k ne 'pagetop') and ($k ne 'pagefoot') 3790 ); 3791 } 3792 } else { 3793 # Can we call out to the trend.cgi program? (undocumented) 3794 if( defined $config{'routers.cgi-trendurl'} 3795 and !$interfaces{$key}{usergraph} ) { 3796 $interfaces{$key}{extensions} = [] 3797 if(!defined $interfaces{$key}{extensions}); 3798 push @{$interfaces{$key}{extensions}}, { 3799 url=>$config{'routers.cgi-trendurl'}, 3800 desc=>langmsg(2418,"Trend Analysis"), icon=>"graph-sm.gif", 3801 target=>"graph", level=>0, insecure=>0 3802 }; 3803 } 3804 } 3805 } 3806 3807 # at this point, %interfaces is set up. 3808 if($CACHE) { 3809 # cache it 3810 $ifstore{$cfgfile} = { %interfaces }; 3811 $debugmessage .= "cached[$cfgfile] "; 3812 if(defined $routers{$router}{extensions}) { 3813 $ifstore{"R:$cfgfile"} = [ @{$routers{$router}{extensions}} ]; 3814 $debugmessage .= "cached[$cfgfile:X] "; 3815 } 3816 $debugmessage .= "\n"; 3817 if( $archdate ) { # clean up mess before caching 3818 foreach my $tmpif ( keys %interfaces ) { 3819 $ifstore{$cfgfile}{$tmpif}{rrd} 3820 = $ifstore{$cfgfile}{$tmpif}{origrrd} 3821 if($ifstore{$cfgfile}{$tmpif}{origrrd}); 3822 } 3823 } 3824# write_cache; 3825 } else { 3826 $debugmessage .= "NOCACHE\n"; 3827 } 3828} 3829 3830 3831############################################################################# 3832# reformat to look nice 3833# params -- number, fix flag, integer flag 3834sub doformat($$$) 3835{ 3836 my( $sufx ) = ""; 3837 my( $val, $fix, $intf ) = @_; 3838 3839 return "???" if(!defined $val or $val !~ /\d/ ); 3840 return $val if( $val == 0 ); 3841 3842 if(!$fix) { 3843 if( abs($val) >= $T ) { 3844 $val /= $T; $sufx = 'T'; 3845 } elsif( abs($val) >= $G ) { 3846 $val /= $G; $sufx = 'G'; 3847 } elsif( abs($val) >= $M ) { 3848 $val /= $M; $sufx = 'M'; 3849 } elsif( abs($val) >= $k ) { 3850 $val /= $k; $sufx = $ksym; 3851 } elsif( abs($val) < 0.001 ) { 3852 $val *= 1000000; $sufx = 'u'; 3853 } elsif( abs($val) < 1 ) { 3854 $val *= 1000; $sufx = 'm'; 3855 } 3856 } 3857 3858 return sprintf "%.0f %s",$val,$sufx 3859 if( $intf or ( int($val*100) == (100*int($val)) ) ); 3860 return sprintf "%.2f %s",$val,$sufx; 3861} 3862# Round the number to a set no of decimal places 3863sub dp($$) { 3864 my($num,$dcp) =@_; 3865 my($rv); 3866 return '0' if(!$num); 3867 $rv = sprintf '%.'.$dcp.'f',$num; 3868 $rv =~ s/\.0+$//; # remove trailing .0 3869 return $rv; 3870} 3871 3872################################# 3873# Calculate nth percentile (bits), and total bandwidth (bits), for current rrd 3874# and for specified interval (d,w,m,y) 3875# Returns ( desc, [inpercentile,intotal,emsg], [outpercentile,outtotal,emsg] ) 3876 3877sub calc_percentile($$$) 3878{ 3879 my( $thisif, $pcinterval, $percentile ) = @_; # interface, dwmy, 95 3880 my( @rv, $e, @opts ); 3881 my( $rrd, $ds ); 3882 my( $resolution, $startpoint, $desc ); # fetch input values 3883 my( $datastart, $datastep, $dsnames, $dsdata ); # fetch return values 3884 my( $pc, $row, $totalbits, @pcarray, $idx, $pcidx ); 3885 3886 return ("",["-","-","No interface"],["-","-",""]) 3887 if(!$thisif); # just in case 3888 3889 $rrd = $interfaces{$thisif}{rrd}; 3890 if($rrdcached and $rrdcached!~/^unix:/) { 3891 my($pth) = $config{'routers.cgi-dbpath'}; 3892 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 3893 $rrd =~ s/^$pth\/*//; 3894 } 3895 foreach ( $pcinterval ) { 3896 /y/ and do { $resolution = 3600; $startpoint = "-1y"; 3897 $desc = langmsg(2420,"rolling last year"); last; }; 3898 /m/ and do { $resolution = 1800; $startpoint = "-1month"; 3899 $desc = langmsg(2421,"rolling last month"); last; }; 3900 /w/ and do { $resolution = 300; $startpoint = "-7d"; 3901 $desc = langmsg(2422,"last 7 days"); last; }; 3902 /6/ and do { $resolution = 60*$interfaces{$thisif}{interval}; 3903 $desc = langmsg(2423,"last 6 hours"); 3904 $startpoint = "-6h"; last; }; 3905 $resolution = 60*$interfaces{$thisif}{interval}; # interval 3906 $startpoint = "-24h"; # 1 day 3907 $desc = langmsg(2424,"last 24 hours"); 3908 } 3909 $desc =~ s/last/previous/ if($pcinterval =~ /-/); 3910 $resolution = 300 if(!$resolution); 3911 push @rv, $desc; 3912 3913 # fetch the data 3914 eval { require RRDs; }; 3915 if( $@ ) { 3916 return ("", ["-","-","No RRDs.pm"],["-","-",""]) ; 3917 } 3918 if($basetime) { 3919 @opts = ( $rrd,"AVERAGE","-e",$basetime,"-s","end$startpoint" ); 3920 } elsif( $pcinterval =~ /-/ ) { 3921 @opts = ( $rrd,"AVERAGE","-e","now$startpoint","-s","end$startpoint" ); 3922 } elsif( $uselastupdate > 1 and $archivetime) { 3923 @opts = ( $rrd,"AVERAGE","-e",$archivetime,"-s","end$startpoint" ); 3924 } elsif( $uselastupdate ) { 3925 @opts = ( $rrd,"AVERAGE","-e",$lastupdate,"-s","end$startpoint" ); 3926 } else { 3927 @opts = ( $rrd,"AVERAGE","-s",$startpoint ); 3928 } 3929 ( $datastart, $datastep, $dsnames, $dsdata ) = RRDs::fetch( @opts, @rrdcached ); 3930 $e = RRDs::error(); 3931 if ( $e ) { 3932 @rv = ("",["?","?",$e], ["?","?","fetch ".(join " ",@opts)]); 3933 return @rv; 3934 } 3935 3936 # now we do two calculations: the total traffic ( $datastep*sum(value) ) 3937 # for both in and out, and the percentile (95% into sorted array ) 3938 foreach $idx ( 0..1 ) { 3939 $totalbits = 0; @pcarray = (); 3940 foreach $row ( @$dsdata ) { 3941 # ???? Is this correctly skipping UNKN values? 3942 # This needs to be checked, we should avoid UNKN in %ile 3943 next if(!defined $row->[$idx]); 3944 if( $row->[$idx] =~ /\d/ ) { 3945# $totalbits += $row->[$idx]*$interfaces{$thisif}{mult}*$datastep; 3946# We no longer multiply by {mult} since we DO NOT want to multiple for 3947# permin/perhour totals (datastep takes care of that) and we want bits to 3948# be totalled in bytes. 3949 $totalbits += $row->[$idx]*$datastep; 3950 push @pcarray, ( $row->[$idx] * $interfaces{$thisif}{mult} ); 3951 } 3952 } 3953 @pcarray = sort numerically @pcarray if($#pcarray>0); 3954 $pcidx = int($#pcarray * $percentile / 100); 3955# Now, at this point, if $thisif is a RANGE, we should do percentile and 3956# 100-percentile , ie, the opposite for the 'from'. 3957 if( $idx and $interfaces{$thisif} and $interfaces{$thisif}{graphstyle} 3958 and $interfaces{$thisif}{graphstyle} eq "range" ) { 3959 $pcidx = int($#pcarray * (100-$percentile) / 100); 3960 } 3961 $pc = $pcarray[$pcidx]; 3962 # multiply by the factor : we did the mult previously 3963 $pc *= $interfaces{$thisif}{factor} if($interfaces{$thisif}{factor}); 3964 $totalbits *= $interfaces{$thisif}{factor} 3965 if($interfaces{$thisif}{factor}); 3966 # the c2f options are BEFORE display 3967 if(($interfaces{$thisif}{c2fi} and !$idx) 3968 or ($interfaces{$thisif}{c2fo} and $idx)) { 3969 $pc = $pc * 1.8 + 32; 3970 $totalbits = $totalbits * 1.8 + 32; # yes its stupid but consistent 3971 } 3972 push @rv, [ $pc.' ', $totalbits, '' ]; 3973 } 3974 3975 return @rv; 3976} 3977 3978################################# 3979# Top menu 3980 3981sub do_head() 3982{ 3983my($iconsuffix) = ""; 3984my($loginbuttons) = ""; 3985my($colwid) = 115; 3986my($logo); 3987 3988$iconsuffix = "-bw" if( $gstyle =~ /b/ ); 3989 3990start_html_ss({ -bgcolor => $menubgcolour, -text => $menufgcolour, 3991 -class => 'header' }); 3992print "<DIV class=header>"; 3993if( $config{'web-auth-required'} =~ /^[yo]/i ) { 3994 if( $authuser ) { 3995 $loginbuttons = $q->td({ -align=>"LEFT", -width=>110, -valign=>"TOP", 3996 class=>'header', id=>'htlogin' }, 3997 $q->a({href=>"$meurlfull?page=logout", target=>'_top', class=>'header'}, 3998 $q->img({src=>"${config{'routers.cgi-iconurl'}}logout$iconsuffix.gif", 3999 alt=>langmsg(5000,"Logout"), border=>"0", width=>100, height=>20, class=>'header'})) 4000 ."<div class=login>" 4001 .$q->br.langmsg(1002,"User").": <div class=username>$authuser</div></div>"); 4002 } else { 4003 $loginbuttons = $q->td({ -align=>"LEFT", -width=>110, -valign=>"TOP", class=>'header', id=>'htlogin' }, 4004 $q->a({href=>"$meurlfull?page=login", target=>'_top', class=>'header'}, 4005 $q->img({src=>"${config{'routers.cgi-iconurl'}}login$iconsuffix.gif", 4006 alt=>langmsg(5001,"Login"), border=>"0", width=>100, height=>20, class=>'header'})) 4007 ); 4008 } 4009} elsif( $config{'web-auth-required'} =~ /^s/i ) { 4010 if( $authuser ) { 4011 $loginbuttons = $q->td({ -align=>"LEFT", -width=>110, -valign=>"TOP", 4012 class=>'header', id=>'htlogin' }, 4013 "<div class=login>" 4014 .langmsg(1002,"User").": <div class=username>$authuser</div>" 4015 ."</div>" 4016 ); 4017 } else { 4018 $loginbuttons = $q->td({ -align=>"LEFT", -width=>110, -valign=>"TOP", class=>'header', id=>'htlogin' }, 4019 $q->a({href=>($config{'web-shib-login'}?$config{'web-shib-login'}:'/secure'), target=>'_top', class=>'header'}, 4020 $q->img({src=>"${config{'routers.cgi-iconurl'}}login$iconsuffix.gif", 4021 alt=>langmsg(5001,"Login"), border=>"0", width=>100, height=>20, class=>'header'})) 4022 ); 4023 } 4024} 4025 4026# Page top logo, may be overridden 4027if($config{'routers.cgi-logourl'}) { 4028 $logo = $q->img({ src=>$config{'routers.cgi-logourl'}, border=>0, class=>'header'}); 4029} else { 4030 $logo = $q->a( { href=>$APPURL, target=>"_new", class=>'header' } , 4031 $q->img({ src=>($config{'routers.cgi-smalliconurl'}."routers2.gif"), 4032 alt=>"Routers2.cgi", border=>0, width=>120, height=>40, class=>'header' })); 4033} 4034 4035print "\n".$q->table( { -border=>"0", -width=>"100%", cellspacing=>0, cellpadding=>1, class=>'header' }, 4036 $q->Tr( { -valign=>"TOP", -width=>"100%", class=>'header' }, "\n". 4037 $q->td({ -align=>"LEFT", -width=>$colwid, -valign=>"TOP", class=>'header', id=>'htleft' }, 4038 ($config{'web-backurl'}?( "<DIV nowrap><nobr>". 4039 $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4040 border=>0, width=>15, height=>15, class=>'header'})." ". 4041 $q->a({ href=>$config{'web-backurl'}, target=>"_top", class=>'header'}, 4042 $q->img({ src=>"${config{'routers.cgi-iconurl'}}mainmenu$iconsuffix.gif", alt=>langmsg(5002,"Main Menu"), border=>0, 4043 width=>100, height=>20, class=>'header' }))."</nobr></DIV>"."\n" 4044 ):"")."<DIV nowrap><nobr>" 4045 .$q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4046 border=>0, width=>15, height=>15, class=>'header'})." " 4047 .$q->a({href=>"javascript:parent.graph.location.reload(true)", class=>'header'}, 4048 $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh$iconsuffix.gif",alt=>langmsg(5003,"Refresh"), border=>"0", 4049 width=>100, height=>20, class=>'header'}))."</nobr></div>" 4050 )."\n" 4051 .$loginbuttons 4052 .$q->td({ -align=>"CENTER", -valign=>"TOP", class=>'header', id=>'htmiddle' }, $toptitle)."\n" 4053 .$q->td({ -align=>"RIGHT", -width=>1, -valign=>"TOP", class=>'header', id=>'htright' }, $logo)."\n" 4054 ) 4055),"\n"; 4056print "</DIV>"; 4057# Finish off the page 4058print $q->end_html(); 4059} 4060 4061########################### 4062# Side menu 4063 4064# $mtype specified 'routers' (list routers) or 'options' (list options) 4065 4066 4067sub do_menu() 4068{ 4069my ($iflabel); 4070my ($target) = "graph"; 4071my ($rtrdesc,$gs,$adesc); 4072my ($iconsuffix) = ""; 4073my ($groupdesc, $lastgroup, $thisgroup); 4074#my ($hassummary) = 0; 4075my ($hascompact) = 0; 4076my ($explore) = "y"; 4077my (@archive) = (); 4078my ($archivepat); 4079my ($timeframe); 4080my ($lurl); # link URL 4081my ($menulevel) = 0; 4082my ($multilevel) = 0; 4083my ($gs) = ':'; 4084my ($pfx); 4085 4086# explore will contain either y, n, or i 4087$explore = $config{'routers.cgi-allowexplore'} 4088 if( defined $config{'routers.cgi-allowexplore'} ); 4089$mtype = "options" if( $explore !~ /y/i ); 4090 4091$iconsuffix = "-bw" if( $gstyle =~ /b/ ); 4092$target = "_top" if( $gstyle =~ /p/ ); 4093 4094# Start it off 4095start_html_ss({ -bgcolor => $menubgcolour, -text => $menufgcolour, 4096 nowrap => "yes", -class => 'sidemenu' }); 4097 4098print "<DIV NOWRAP class=sidemenu>\n"; 4099 4100# top link for other stuff 4101#if( $mtype eq "options" or !$router or $router eq "none" 4102# or $router eq "__none" or $interface eq "__none" ) { 4103# print $q->a({name=>"top"},""); 4104#} 4105print "<FONT size=".$config{'routers.cgi-menufontsize'}.">\n" 4106 if( defined $config{'routers.cgi-menufontsize'} ); 4107 4108# Main stuff and links 4109if ( $mtype eq "options" ) { 4110 # check for inout graphs 4111 foreach ( keys %interfaces ) { 4112# if( $interfaces{$_}{insummary} ) { $hassummary = 1; } 4113 if( $interfaces{$_}{incompact} ) { $hascompact = 1; } 4114 } 4115 # check for archive 4116 if( defined $config{'routers.cgi-archive'} 4117 and $config{'routers.cgi-archive'} !~ /^n/i ) { 4118 $archivepat = $router; $archivepat =~ s/[\?#\\\/]//g; 4119 $archivepat = $config{'routers.cgi-graphpath'}.$pathsep 4120 .$archivepat.$pathsep.$interface.$pathsep."*.*"; 4121 # do this in an eval because some Perl implementations treat a null 4122 # glob as an error (why??) 4123 eval { @archive = glob($archivepat); }; 4124 } 4125 4126 # now show it all 4127 if( !$twinmenu ) { 4128 print "<nobr>" 4129 .$q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4130 border=>0, width=>15, height=>15, class=>'sidemenu'})." " 4131 .$q->a({ href=>"$meurlfull?".optionstring( 4132 { page=>"menu",xmtype=>"routers" }),class=>'sidemenu', target=>"_self", 4133 onMouseOver=>"if(devices){devices.src='${config{'routers.cgi-iconurl'}}devices-dn-w.gif'; window.status='Show list of routers';}", 4134 onmouseout=>"if(devices){devices.src='${config{'routers.cgi-iconurl'}}devices-dn$iconsuffix.gif'; window.status='';}" }, 4135 $q->img({ src=>"${config{'routers.cgi-iconurl'}}devices-dn$iconsuffix.gif", 4136 alt=>langmsg(5004,"Devices"), border=>0 , name=>"devices", 4137 class => 'sidemenu', 4138 width=>100, height=>20}))."</nobr>\n".$q->br."\n" 4139 if( $explore =~ /y/i ); 4140 } 4141 # list options 4142 if( $explore !~ /n/i and $router ne "none") { 4143 print "<nobr>"; 4144 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4145 border=>0, width=>15, height=>15,class=>'sidemenu'})." " 4146 .$q->img({ src=>"${config{'routers.cgi-iconurl'}}targets$iconsuffix.gif", 4147 alt=>langmsg(5005,"Targets"),width=>100, height=>20,class=>'sidemenu' }) 4148 ."</nobr>".$q->br."\n"; 4149 foreach ( sort byifdesc keys( %interfaces ) ) { 4150 next if(!$_); # avoid the '#' interface... 4151 next if(!$interfaces{$_}{inmenu}); # if not in menu... 4152 $iflabel = $interfaces{$_}{shdesc} if(defined $interfaces{$_}{shdesc}); 4153 $iflabel = "#$_" unless ( $iflabel ); 4154 $iflabel =~ s/ /\ /g; # get rid of spaces... 4155 print "<NOBR>"; 4156 if( $_ eq $interface ) { 4157 my(@k) = (keys %interfaces); 4158 print $q->a({name=>"top"},"") if($#k>25); } 4159 if( $interfaces{$_}{icon} ) { 4160 print $q->img({ 4161 src=>($config{'routers.cgi-smalliconurl'}.$interfaces{$_}{icon}), 4162 width=>15, height=>15, alt=>$interfaces{$_}{desc},class=>'sidemenu' })," "; 4163 } elsif( $interfaces{$_}{isif} ) { 4164 print $q->img({ 4165 src=>($config{'routers.cgi-smalliconurl'}."interface-sm.gif"), 4166 width=>15, height=>15, alt=>$interfaces{$_}{desc},class=>'sidemenu' })," "; 4167 } else { 4168 print $q->img({ 4169 src=>($config{'routers.cgi-smalliconurl'}."target-sm.gif"), 4170 width=>15, height=>15, alt=>$interfaces{$_}{desc},class=>'sidemenu' })," "; 4171 } 4172 if ( $interface eq $_ ) { 4173 print $q->b($iflabel); 4174 } else { 4175 if( $gstyle =~ /p/ ) { 4176 print $q->a({ href=>"$meurlfull?".optionstring( 4177 { page=>"main", if=>"$_" }), target=>"_top",class=>'sidemenu' }, $iflabel ); 4178 } else { 4179 print $q->a({ href=>"$meurlfull?".optionstring( 4180 { if=>"$_" }), target=>"graph",class=>'sidemenu' }, $iflabel ); 4181 } 4182 } 4183 print "</NOBR>".$q->br."\n"; 4184 4185 } # special targets - summary, compact, info, userdefined 4186 if( $router ne "none" and $router ne "__none" ) { 4187 if($hascompact) { 4188 if( $config{'routers.cgi-stylesheet'} 4189 or ! defined $config{'routers.cgi-compact'} 4190 or $config{'routers.cgi-compact'} !~ /n/i ) { 4191 print "<NOBR>"; 4192 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}compact-sm.gif", 4193 width=>15, height=>15,class=>'sidemenu' })," "; 4194 if( $interface eq "__compact" ) { 4195 print $q->b(langhtml(2000,"Compact summary")); 4196 } else { 4197 if( $gstyle =~ /p/ ) { 4198 print $q->a({ href=>"$meurlfull?".optionstring( 4199 { page=>"main", if=>"__compact" }), target=>"_top",class=>'sidemenu' }, 4200 langhtml(2000,"Compact summary")); 4201 } else { 4202 print $q->a({ href=>"$meurlfull?".optionstring( 4203 { if=>"__compact" }), target=>"graph",class=>'sidemenu' }, 4204 langhtml(2000,"Compact summary")); 4205 } 4206 } 4207 print "</NOBR>".$q->br."\n"; 4208 } # compact option 4209 } # hascompact 4210 if( $router !~ /^#/ ) { 4211 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}menu-sm.gif", 4212 width=>15, height=>15,class=>'sidemenu' })," "; 4213 if( $interface eq "__info" ) { 4214 print $q->b(langhtml(2001,"Information")),$q->br,"\n"; 4215 } else { 4216 if( $gstyle =~ /p/ ) { 4217 print $q->a({ href=>"$meurlfull?".optionstring( 4218 { page=>"main",if=>"__info"}), target=>"_top",class=>'sidemenu'}, 4219 langhtml(2001,"Information")),$q->br,"\n"; 4220 } else { 4221 print $q->a({ href=>"$meurlfull?".optionstring( 4222 { if=>"__info" }), target=>"graph",class=>'sidemenu' }, 4223 langhtml(2001,"Information")),$q->br,"\n"; 4224 } 4225 } 4226 } # not system special #SERVER# 4227 # any userdefined's for this router? 4228 if ( defined $routers{$router}{extensions} ) { 4229 my( $u, $ext, $targ ); 4230 foreach $ext ( @{$routers{$router}{extensions}} ) { 4231 if($seclevel<$ext->{level}) { 4232# print $ext->{desc}." (".$ext->{level}.")".$q->br."\n"; 4233 next; 4234 } 4235 $targ = "graph"; 4236 $targ = $ext->{target} if( defined $ext->{target} ); 4237 $u = $ext->{url}; 4238 if(!$ext->{noopts}) { 4239 $u .= "?x=1" if( $u !~ /\?/ ); 4240 $u .= "&fi=".$q->escape($router) 4241 ."&url=".$q->escape($q->url()); 4242 $u .= "&t=".$q->escape($targ); 4243 $u .= "&L=".$seclevel; 4244 $u .= "&r=".$q->escape($ext->{hostname}) 4245 ."&h=".$q->escape($ext->{hostname}) if(defined $ext->{hostname}); 4246 $u .= "&c=".$q->escape($ext->{community}) 4247 if(defined $ext->{community} and $ext->{insecure}); 4248 $u .= "&b=".$q->escape("javascript:history.back();history.back()") 4249 ."&conf=".$q->escape($conffile); 4250 $u .= "&ad=$archdate&arch=$archdate" if($archdate); 4251 } elsif( $ext->{noopts} == 2 ) { # special for Link[] 4252 $u .= "&L=$seclevel&xgtype=$gtype&xgstyle=$gstyle"; 4253 $u .= "&ad=$archdate&arch=$archdate" if($archdate); 4254 } 4255 print "<NOBR>".$q->img({ src=>(${config{'routers.cgi-smalliconurl'}} 4256 .$ext->{icon}), width=>15, height=>15,class=>'sidemenu' })," "; 4257 print $q->a({ href=>$u, target=>$targ,class=>'sidemenu' }, 4258 expandvars($ext->{desc}) )."</NOBR>".$q->br."\n"; 4259 } 4260 } # extensions defined 4261 } # not 'none' router 4262 print $q->br; 4263 } # explore 4264 4265 print "\n<DIV class=sidemenuoptions>"; 4266 if( !$archive and $interface ne "__none" and $interface ne "__info" ) { 4267 print "<nobr>"; 4268 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4269 border=>0, width=>15, height=>15,class=>'sidemenu'})." "; 4270 print $q->img({ src=>"${config{'routers.cgi-iconurl'}}graphs$iconsuffix.gif", alt=>langmsg(5006,"Graphs"), 4271 width=>100, height=>20,class=>'sidemenu' })."</nobr>". $q->br."\n"; 4272 # Here, if the option is enabled, use the calendar tool 4273 if( $config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'}=~/f/i ) { 4274 my($mindate) = ""; 4275 my($rrdinfo); 4276 my($e); 4277 my($rranum) = 0; 4278 my($gwindow) = 400; 4279 my($basedate) = ""; 4280 my($rrdfilename); 4281 my($datestr,$dformat) = ('Live Data','%Y-%m-%d'); 4282 my($mday,$mon,$year); 4283 if(defined $interfaces{$interface}{origrrd}) { 4284 $rrdfilename = $interfaces{$interface}{origrrd}; 4285 } else { 4286 $rrdfilename = $interfaces{$interface}{rrd}; 4287 } 4288 # convert this into a param that can be used by Javascript Date() 4289 if( $q->param('arch') ) { 4290 if( $q->param('arch') =~ /(\d\d\d\d)-(\d\d)-(\d\d)/ ) { 4291 $basedate = "$1,".($2-1).",$3"; 4292 ($mday,$mon,$year)=($3,$2-1,$1-1900); 4293 $dformat = $config{'web-dateonlyformat'} 4294 if(defined $config{'web-dateonlyformat'}); 4295 $dformat =~ s/ / /g; 4296 $datestr = POSIX::strftime($dformat,0,0,0,$mday,$mon,$year); 4297 } else { 4298 $datestr = $q->param('arch'); 4299 } 4300 } 4301 if( $gtype =~ /w/ ) { 4302 $gwindow = 333; # weekly graphs are shorter time window 4303 $rranum = 1; 4304 } elsif( $gtype =~ /m/ ) { 4305 $rranum = 2; 4306 } elsif( $gtype =~ /y/ ) { 4307 $rranum = 3; 4308 } 4309 if($rrdcached and $rrdcached!~/^unix:/) { 4310 my($pth) = $config{'routers.cgi-dbpath'}; 4311 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 4312 $rrdfilename =~ s/^$pth\/*//; 4313 } 4314 eval { require RRDs; }; 4315 if($@) { 4316 $e = $@; 4317 } else { 4318 $rrdinfo = RRDs::info($rrdfilename,@rrdcached); 4319 $e = RRDs::error(); 4320 } 4321 if($e) { 4322 print "<!-- RRD error: $e -->\n"; 4323 print "<!-- RRD file: $rrdfilename -->\n"; 4324 print "<!-- RRDcached option: $rrdcached -->\n"; 4325 print "<!-- RRDcached setting: ".(join(" ",@rrdcached))." -->\n"; 4326 } else { 4327 print "<!-- RRD rra=$rranum rows=".$rrdinfo->{"rra[${rranum}].rows"}." -->\n"; 4328 } 4329 if(defined $rrdinfo and !$e and $rrdinfo->{"rra[${rranum}].rows"} ) { 4330 $mindate = 1000 * (time() - ($rrdinfo->{step} * $rrdinfo->{"rra[${rranum}].pdp_per_row"} * ($rrdinfo->{"rra[${rranum}].rows"}-$gwindow))); 4331 } 4332 print "<TABLE><TR><TD>"; 4333 print "<FORM name=dateform method=GET action=$meurlfull target=graph class=sidemenu>"; 4334 print "<span id=\"calendar-trigger\">".$q->img({ src=>"${config{'routers.cgi-smalliconurl'}}calendar-sm.gif", 4335 width=>15, height=>15, class=>'sidemenuform', id=>'dateanchor' })," "; # spacer 4336 print "<button id=\"calendar-trigger-button\">$datestr</button></span><br>\n"; 4337 print $q->hidden(-id=>"calendar-field", -name=>"arch", -override=>1, -default=>($q->param('arch'))); 4338 print $q->hidden(-name=>'rtr', -default=>"$router", -override=>1); 4339 print $q->hidden(-name=>'if', -default=>"$interface", -override=>1); 4340 print $q->hidden(-name=>'page', -default=>'graph', -override=>1); 4341 print $q->hidden(-name=>'xpage', -default=>'graph', -override=>1); # grr 4342 print $q->hidden(-name=>'xgtype', -default=>"$gtype", -override=>1); 4343 print $q->hidden(-name=>'xgstyle', -default=>"$gstyle", -override=>1); 4344 print $q->hidden(-name=>'xgopts', -default=>"$gopts", -override=>1); 4345 print $q->hidden(-name=>'bars', -default=>"$baropts", -override=>1); 4346 print $q->hidden(-name=>'extra', -default=>"$extra", -override=>1); 4347 print $q->hidden(-name=>'uopts', -default=>"$uopts", -override=>1); 4348 print "</FORM>"; 4349 print "</TD></TR></TABLE>\n"; 4350 print "<SCRIPT>\n 4351// JSCal2 Calendar control from http://www.dynarch.com/projects/calendar/ 4352function getDateInfo(date, wantsClassName) { 4353 var idate = Calendar.dateToInt(date); 4354 if (String(idate).indexOf(\"0821\") == 4) { 4355 return { klass: \"birthday\", tooltip: \"Steve's Birthday!\" }; 4356 } 4357}; 4358var cal = Calendar.setup({ 4359 inputField : \"calendar-field\", 4360 trigger : \"calendar-trigger\", 4361 anchor : \"dateanchor\", 4362 animation : false, 4363 opacity : 1, 4364 align : \"BC/ /l/b/\", 4365 dateFormat : \"\%Y-\%m-\%d\", 4366 selection : Calendar.dateToInt(new Date(${basedate})), 4367 max : Calendar.dateToInt(new Date()), 4368 min : Calendar.dateToInt(new Date(${mindate})), 4369 dateInfo : getDateInfo, 4370 onSelect : function() { 4371 this.hide(); 4372 if( Calendar.printDate(Calendar.intToDate(this.selection.get()),\"\%Y-\%m-\%d\") != \"".$q->param('arch')."\" ) { 4373 dateform.submit(); 4374 } 4375 } 4376}); 4377</SCRIPT>\n"; 4378 } else { 4379 # First we list all the archived RRD files, if available. 4380 my($archroot) = ''; 4381 if($interface and defined $interfaces{$interface}) { 4382 if($interfaces{$interface}{origrrd}) { 4383 $archroot = dirname($interfaces{$interface}{origrrd}) 4384 .$pathsep.'archive'; 4385 } elsif($interfaces{$interface}{rrd}) { 4386 $archroot = dirname($interfaces{$interface}{rrd}) 4387 .$pathsep.'archive'; 4388 } 4389 } 4390 if( -d $archroot ) { 4391 # An archive exists! 4392 my($rrdfilename); 4393 if(defined $interfaces{$interface}{origrrd}) { 4394 $rrdfilename = basename($interfaces{$interface}{origrrd}); 4395 } else { 4396 $rrdfilename = basename($interfaces{$interface}{rrd}); 4397 } 4398 my(@days) = ( '0' ); 4399 my(%descs); 4400 my($dmyfmt); 4401 if( defined $config{'web-dateonlyformat'} ) { 4402 $dmyfmt = $config{'web-dateonlyformat'}; 4403 } else { $dmyfmt = "\%d/\%m/\%y" } # could use %x here? 4404 $debugmessage .= "Dateformat used: $dmyfmt\n"; 4405 $descs{0} = langmsg(5007,'Live data'); 4406 # caching code for speedycgi people 4407 if( -M $archroot < 0 ) { 4408 # invalidate archive cache, as a new one has been added. 4409 %cachedays = (); 4410 $^T = time; # set 'script init time' to first read of cfg files 4411 # we also need to clear all other caches since they are tied 4412 # to the script init time? 4413 # try without since if they have changed the previous checks will 4414 # already have picked it up and refreshed them 4415 #%ifstore = (); # clean out all cached info 4416 #%routerscache = (); # clean out all cached info 4417 #$readinrouters = 0; 4418 } 4419 if( defined $cachedays{$rrdfilename} ) { 4420 @days = @{$cachedays{$rrdfilename}}; 4421 # If we get the list from the cache, we still need to build descs 4422 # This is because people may have different date formats... 4423 foreach ( @days ) { 4424 if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { 4425 if($dmyfmt) { 4426 $descs{$_} = 4427 POSIX::strftime($dmyfmt,0,0,0,$4,($3-1),(($1>19)?($2+100):$2)); 4428 } else { $descs{$_} = "$4/$3/$2"; } #DMY 4429 } 4430 } 4431 $debugmessage .= "fromcache(dates:$rrdfilename)\n"; 4432 } else { 4433 # Maybe find a better way to do this -- glob is SLOW 4434 $|=1; # print out what we've done so far 4435 foreach ( sort rev findarch( $archroot,$rrdfilename ) ) { 4436 if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { 4437 push @days, "$1$2-$3-$4"; 4438 if($dmyfmt) { 4439 $descs{"$1$2-$3-$4"} = 4440 POSIX::strftime($dmyfmt,0,0,0,$4,($3-1),(($1>19)?($2+100):$2)); 4441 } else { $descs{"$1$2-$3-$4"} = "$4/$3/$2"; } #DMY 4442 } 4443 } 4444 $cachedays{$rrdfilename} = [ @days ]; # Cache for later 4445 $debugmessage .= "cached[dates:$rrdfilename]\n"; 4446 } 4447 if( $#days > 0 ) { 4448 print "<nobr><TABLE cellspacing=0 cellpadding=0 border=0 class=sidemenu><TR class=sidemenu><TD class=sidemenu>"; 4449 print "<FORM name=archform method=GET action=$meurlfull target=graph class=sidemenu>"; 4450 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}calendar-sm.gif", 4451 width=>15, height=>15, class=>'sidemenuform' })," "; # spacer 4452 my($curd) = $q->param('arch'); 4453 $curd = $opt_a if($opt_a); 4454 $curd = '0' if(!$curd); 4455 print $q->popup_menu( -name=>"arch", -values=>\@days, 4456 -default=>$curd, -labels=>\%descs, 4457 -onChange=>'archform.submit();', class=>'sidemenuform'); 4458 print $q->hidden(-name=>'rtr', -default=>"$router", -override=>1); 4459 print $q->hidden(-name=>'if', -default=>"$interface", -override=>1); 4460 print $q->hidden(-name=>'page', -default=>'graph', -override=>1); 4461 print $q->hidden(-name=>'xpage', -default=>'graph', -override=>1); # grr 4462 print $q->hidden(-name=>'xgtype', -default=>"$gtype", -override=>1); 4463 print $q->hidden(-name=>'xgstyle', -default=>"$gstyle", -override=>1); 4464 print $q->hidden(-name=>'xgopts', -default=>"$gopts", -override=>1); 4465 print $q->hidden(-name=>'bars', -default=>"$baropts", -override=>1); 4466 print $q->hidden(-name=>'extra', -default=>"$extra", -override=>1); 4467 print $q->hidden(-name=>'uopts', -default=>"$uopts", -override=>1); 4468 print "</FORM>\n"; 4469 print "</TD></TR></TABLE></nobr>"; 4470 } else { 4471 print "<!-- no archive dates -->"; 4472 } 4473 } else { 4474 print "<!-- $archroot does not exist -->\n"; 4475 } 4476 } # new archive method 4477 # Now all the different daily/weekly/etc graph types 4478 foreach ( @gorder ) { 4479 if( defined $interfaces{$interface} 4480 and defined $interfaces{$interface}{suppress} ) { 4481 $timeframe = $_; $timeframe =~ s/-//g; 4482 next if( $interfaces{$interface}{suppress} =~ /$timeframe/ ); 4483 } 4484 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}clock-sm.gif", 4485 width=>15, height=>15, class=>'sidemenu' })," "; 4486 if($gtype eq $_) { 4487 print $q->b($gtypes{$_}),$q->br,"\n"; 4488 } elsif((($interface eq "__compact") 4489 and (length > 2 )) 4490 or ( $router eq "none" )) { 4491 print $gtypes{$_},$q->br,"\n"; 4492 } else { 4493 if( $gstyle =~ /p/ ) { 4494 print $q->a({ href=>"$meurlfull?".optionstring( 4495 { page=>"main", xgtype=>"$_" }), 4496 target=>"_top", class=>'sidemenu' }, $gtypes{$_} ), $q->br,"\n"; 4497 } else { 4498 print $q->a({ href=>"$meurlfull?".optionstring( 4499 { xgtype=>"$_" }), target=>"graph", class=>'sidemenu' }, $gtypes{$_} ),$q->br,"\n"; 4500 } 4501 } 4502 } 4503 print $q->br; 4504 } # ! viewing archive 4505 print "\n"; 4506 if( @archive ) { 4507 print "<nobr>"; 4508 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4509 border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4510 print $q->img({ 4511 src=>"${config{'routers.cgi-iconurl'}}archive-h$iconsuffix.gif", 4512 alt=>langmsg(5008,"Archive"), width=>100, height=>20, class=>'sidemenu' }),"</nobr>".$q->br."\n"; 4513 if($archive) { 4514 print "<NOBR>"; 4515 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}graph-sm.gif", 4516 width=>15, height=>15, class=>'sidemenu' })," "; 4517 $adesc = langhtml(5007,"Live graph"); 4518 if( $gstyle=~/p/ ) { 4519 print $q->a({ href=>"$meurlfull?".optionstring( { page=>"main" }), 4520 target=>"_top", class=>'sidemenu' }, $adesc ); 4521 } else { 4522 print $q->a({ href=>"$meurlfull?".optionstring( { page=>"graph" }), 4523 target=>"graph", class=>'sidemenu' }, $adesc ); 4524 } 4525 print "</NOBR>".$q->br."\n"; 4526 } 4527 foreach ( sort @archive ) { 4528 if(/(\d+)-(\d+)-(\d+)-(\d+)-(\d+)-(\S+)\.(gif|png)$/) { 4529 # try to get local formatting 4530# $adesc = "$4:$5 $3/$2/$1 (".$gtypes{$6}.")"; 4531 my( $dformat ) = "%c"; 4532 $dformat = $config{'web-shortdateformat'} 4533 if(defined $config{'web-shortdateformat'}); 4534 if(!$dformat) { 4535 $adesc = "$4:$5 $3/$2/$1 (".$gtypes{$6}.")"; 4536 } else { 4537 $adesc = POSIX::strftime($dformat, 4538 0,$5,$4,$3,($2-1),($1-1900))." (".$gtypes{$6}.")"; 4539 $adesc =~ s/ /\ /g; 4540 } 4541 print "<NOBR>"; 4542 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}graph-sm.gif", 4543 width=>15, height=>15, class=>'sidemenu' })," "; 4544 if( $gstyle=~/p/ ) { 4545 print $q->a({ href=>"$meurlfull?".optionstring( { page=>"main", 4546 archive=>(basename $_), xgtype=>"$6"}), 4547 target=>"_top", class=>'sidemenu' }, $adesc ); 4548 } else { 4549 print $q->a({ href=>"$meurlfull?".optionstring( { 4550 page=>"graph", 4551 archive=>(basename $_), xgtype=>"$6"}), 4552 target=>"graph", class=>'sidemenu' }, $adesc ); 4553 } 4554 print "</NOBR>".$q->br."\n"; 4555 } else { 4556 print "<!-- Error in archive [$_] -->\n"; 4557 } 4558 } 4559 print $q->br."\n"; 4560 } 4561 4562 if( !$archive and $interface ne "__none" and $interface ne "__info" ) { 4563 print "<nobr>"; 4564 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4565 border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4566 print $q->img({ 4567 src=>"${config{'routers.cgi-iconurl'}}styles$iconsuffix.gif", 4568 alt=>langmsg(5009,"Styles"), width=>100, height=>20, class=>'sidemenu' })."</nobr>".$q->br."\n"; 4569 foreach ( @sorder ) { 4570 next if (!defined $gstyles{$_}); 4571 print "<NOBR>"; 4572 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}pbrush-sm.gif", 4573 width=>15, height=>15, class=>'sidemenu' })," "; 4574 $gs = $gstyles{$_}; 4575 $gs =~ s/ /\ /g; 4576 if($gstyle eq $_) { 4577 print $q->b($gs); 4578 } elsif( $router eq "none" ) { 4579 print $gs; 4580 } else { 4581 # PDAs cant be relied on to have javascript support 4582 if( /p/ ) { 4583 print $q->a({ href=>"$meurlfull?".optionstring( 4584 { page=>"main", xgstyle=>"$_"}), target=>"_top", class=>'sidemenu' }, $gs ); 4585 } else { 4586 print $q->a({ href=>"$meurlfull?".optionstring( 4587 { xgstyle=>"$_"}), target=>"graph", class=>'sidemenu' }, $gs ); 4588 } 4589 } 4590 print "</NOBR>".$q->br."\n"; 4591 } 4592 print $q->br; 4593 } # ! archive viewing 4594 print "<nobr>"; 4595 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4596 border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4597 print $q->img({ src=>"${config{'routers.cgi-iconurl'}}otherstuff$iconsuffix.gif", alt=>langmsg(5010,"Other Stuff"), 4598 width=>100, height=>20, class=>'sidemenu' })."</nobr>". $q->br."\n"; 4599 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}prefs-sm.gif", 4600 width=>15, height=>15, class=>'sidemenu' })," "; 4601 print $q->a({href=>"$meurlfull?".optionstring( 4602 { page=>"config" }) , target=>"graph", class=>'sidemenu'}, 4603 langmsg(5011,"Preferences")),$q->br,"\n"; 4604 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}info-sm.gif", class=>'sidemenu' })," "; 4605 print $q->a({href=>"$meurlfull?".optionstring({page=>"help"}), target=>"graph", class=>'sidemenu'}, 4606 langmsg(5012,"Information")),$q->br,"\n"; 4607# print $q->img({ src=>"${config{'routers.cgi-iconurl'}}error-sm.gif" })," "; 4608# print $q->a({href=>("$meurl?page=verify&rtr=" 4609# .$q->escape($router)),target=>"_new"},"Configuration check") 4610# .$q->br."\n"; 4611 # twin menu 4612 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}menu-sm.gif", class=>'sidemenu' }), 4613 " "; 4614 if( $twinmenu ) { 4615 $uopts=~ s/[tT]//g; $uopts .= "T"; 4616 print $q->a({ href=>"$meurlfull?".optionstring({ page=>"main"}), 4617 target=>"_top", class=>'sidemenu' },langhtml(5013,"Close second menu") ) 4618 } else { 4619 $uopts=~ s/[tT]//g; $uopts .= "t"; 4620 print $q->a({ href=>"$meurlfull?".optionstring({page=>"main"}), 4621 target=>"_top", class=>'sidemenu' }, langhtml(5014,"Twin menu view") ) 4622 } 4623 print $q->br."\n"; 4624 print "</DIV>"; # sidemenuoptions 4625} else { 4626 # Devices (Routers) menu list 4627 # 4628 if( ! $twinmenu ) { 4629 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4630 border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4631 print $q->a({ href=>"$meurlfull?".optionstring( 4632 { page=>"menu", xmtype=>"options" }), target=>"_self" , 4633 onMouseOver=>"if(options){options.src='${config{'routers.cgi-iconurl'}}options-dn-w.gif'; window.status='Show display options';}", 4634 onmouseout=>"if(options){options.src='${config{'routers.cgi-iconurl'}}options-dn$iconsuffix.gif'; window.status='';}", class=>'sidemenu' }, 4635 $q->img({ src=>"${config{'routers.cgi-iconurl'}}options-dn$iconsuffix.gif", alt=>langmsg(5015,"Options"), border=>0, name=>"options", class=>'sidemenu', 4636 height=>20, width=>100 }))."\n".$q->br."\n"; 4637 } 4638 # list devices 4639 print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}nothing-sm.gif", 4640 border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4641 print $q->img({ src=>"${config{'routers.cgi-iconurl'}}devices$iconsuffix.gif", alt=>langmsg(5004,"Devices"), 4642 height=>20, width=>100, class=>'sidemenu' }), $q->br,"\n"; 4643 # The 'Find' box 4644 print "<DIV class=sidemenuoptions>"; 4645 if( !defined $config{'routers.cgi-showfindbox'} 4646 or $config{'routers.cgi-showfindbox'} =~ /[Yy1]/ ) { 4647 print "<NOBR><TABLE align=left cellspacing=0 cellpadding=0 border=0 class=sidemenu><TR class=sidemenu><TD nowrap class=sidemenu><FORM method=GET action=$meurlfull target=graph class=sidemenuform>"; 4648 print $q->img({src=>"${config{'routers.cgi-smalliconurl'}}search-sm.gif", border=>0, width=>15, height=>15, class=>'sidemenu'})." "; 4649 print $q->textfield({-name=>'searchhost', 4650 -value=>langmsg(5004,"Device"), -size=>9, class=>'sidemenuform'}); 4651 print $q->hidden(-name=>'page', -default=>"graph", -override=>1); 4652 print $q->hidden(-name=>'xgtype', -default=>"$gtype", -override=>1); 4653 print $q->hidden(-name=>'xgstyle', -default=>"$gstyle", -override=>1); 4654 print $q->hidden(-name=>'xgopts', -default=>"$gopts", -override=>1); 4655 print $q->hidden(-name=>'bars', -default=>"$baropts", -override=>1); 4656 print $q->hidden(-name=>'extra', -default=>"$extra", -override=>1); 4657 print $q->hidden(-name=>'uopts', -default=>"$uopts", -override=>1); 4658 print $q->submit({ name=>"search", value=>"?", class=>'sidemenuform' }); 4659 print "</FORM></TD></TR></TABLE></NOBR><br clear=both>\n"; 4660 } 4661 print "</DIV>"; 4662 # grouping 4663 my($lastgroupdesc,$activegroupdesc); 4664 $grouping = $multilevel = 0; 4665 $grouping = 1 if( defined $config{'routers.cgi-group'} 4666 and $config{'routers.cgi-group'} =~ /[Yy1]/ ); 4667 if($grouping) { 4668 $group=$lastgroup=""; 4669 $group=$routers{$router}{group} if(defined $routers{$router}); 4670 $gs = ':'; 4671 $gs = $config{'routers.cgi-groupsep'} 4672 if(defined $config{'routers.cgi-groupsep'}); 4673 $multilevel = 1 if( defined $config{'routers.cgi-multilevel'} 4674 and $config{'routers.cgi-multilevel'}=~/[y1]/i ); 4675 # Prefix to cut off for group names 4676 $pfx = $config{'routers.cgi-confpath'}.$pathsep; 4677 # Can't add escapes for some reason 4678# $pfx =~ s/\//\\\//g; 4679 $pfx =~ s/\\/\\\\/g; 4680 4681 if($multilevel) { 4682 if( defined $config{"targetnames-$group"} ) { 4683 $activegroupdesc = $config{"targetnames-$group"}; 4684 } elsif( defined $config{("targetnames-".(lc $group))} ) { 4685 $activegroupdesc = $config{("targetnames-".(lc $group))}; 4686 } elsif($group) { 4687 $activegroupdesc = $group; 4688 $activegroupdesc =~ s/^$pfx//; # Chop off confpath 4689 $activegroupdesc = basename( $group,'' ).$pathsep 4690 if(!$activegroupdesc); 4691 } else { 4692 $activegroupdesc = "None"; 4693 } 4694 } 4695 } 4696 foreach ( sort byshdesc keys(%routers) ) { 4697 next if(!$routers{$_}{inmenu}); 4698 if( $grouping ) { 4699 $thisgroup = $routers{$_}{group}; 4700 if( $thisgroup ne $lastgroup ) { 4701 my(@grps); 4702 if( defined $config{"targetnames-$thisgroup"} ) { 4703 $groupdesc = $config{"targetnames-$thisgroup"}; 4704 } elsif( defined $config{("targetnames-".(lc $thisgroup))} ) { 4705 $groupdesc = $config{("targetnames-".(lc $thisgroup))}; 4706 } else { 4707 $groupdesc = $thisgroup; 4708 $groupdesc =~ s/^$pfx//; # Chop off confpath 4709 $groupdesc = basename( $thisgroup,'' ).$pathsep if(!$groupdesc); 4710 } 4711 if($multilevel) { 4712 @grps = getgroups($activegroupdesc,$groupdesc,$lastgroupdesc); 4713 } else { 4714 @grps = ( [ $groupdesc,1,(($thisgroup eq $group)?1:0) ] ); 4715 } 4716 foreach my $gg ( @grps ) { 4717 print "<NOBR>"; 4718 $menulevel = $gg->[1]; 4719 print " " x $menulevel if($menulevel); 4720 if( $gg->[2] ) { 4721 print $q->img({ 4722 src=>"${config{'routers.cgi-smalliconurl'}}g-sm.gif", 4723 width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu' })," "; 4724 print $q->b($gg->[0]); 4725 } else { 4726 $lurl = $meurlfull; 4727 $lurl = $routers{$_}{redirect} 4728 if(defined $routers{$_}{redirect}); 4729 if( $gstyle =~ /p/ or defined $routers{$_}{redirect}) { 4730 print $q->img({ 4731 src=>"${config{'routers.cgi-smalliconurl'}}plus-sm.gif", 4732 width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu', 4733 border=>0 })," "; 4734 print $q->a({href=>"$lurl?" 4735 .optionstring({page=>"main",'if'=>"",rtr=>"$_"}), 4736 target=>"_top", class=>'sidemenu' },$q->b($gg->[0]) ); 4737 } else { 4738 print $q->a({ href=>"$lurl?" 4739 .optionstring({ rtr=>"$_", 'if'=>"" }), 4740 target=>"graph", class=>'sidemenu' }, $q->img({ 4741 src=>"${config{'routers.cgi-smalliconurl'}}plus-sm.gif", 4742 width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu', 4743 border=>0 }))." "; 4744 print $q->a({ href=>"$lurl?" 4745 .optionstring({ rtr=>"$_", 'if'=>"" }), 4746 target=>"graph", class=>'sidemenu' },$q->b($gg->[0]) ); 4747 } 4748 } 4749 print "</NOBR>".$q->br."\n"; 4750 } # foreach 4751 $lastgroup = $thisgroup; 4752 $lastgroupdesc = $groupdesc; 4753 } # if in new group 4754 if( $multilevel ) { 4755 next if(( $thisgroup ne $group ) 4756 and ( $activegroupdesc !~ /^$groupdesc$gs/ )); 4757# if(( $thisgroup ne $group ) 4758# and ( $activegroupdesc !~ /^$groupdesc$gs/ )) { print "[$activegroupdesc][^$groupdesc$gs]"; } 4759 } else { 4760 next if( $thisgroup ne $group ); # only show active group 4761 } 4762 } # if grouping 4763 $rtrdesc = $routers{$_}{shdesc}; 4764 $rtrdesc = $_ if(! $rtrdesc ); 4765 $rtrdesc =~ s/ /\ \;/g; # stop breaking of line on spaces 4766 4767 print "<NOBR>"; 4768 if($grouping) { print ( " " x ($menulevel+1)); } 4769 if( $_ eq $router ) { print $q->a({name=>"top"},""); } 4770 print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$routers{$_}{icon}), 4771 width=>15, height=>15, class=>'sidemenu', 4772 alt=>( $routers{$_}{shdesc}?$routers{$_}{shdesc}:$_ ) })," "; 4773 if( $_ eq $router ) { 4774 print $q->b($rtrdesc); 4775 } else { 4776 $lurl = $meurlfull; 4777 $lurl = $routers{$_}{redirect} 4778 if(defined $routers{$_}{redirect}); 4779 if( $gstyle =~ /p/ or defined $routers{$_}{redirect}) { 4780 print $q->a({href=>"$lurl?".optionstring({page=>"main", 'if'=>"", 4781 rtr=>"$_"}), target=>"_top", class=>'sidemenu' },$rtrdesc ); 4782 } else { 4783 print $q->a({href=>"$lurl?".optionstring({ rtr=>"$_", 'if'=>"" }), 4784 target=>"graph", class=>'sidemenu' },$rtrdesc ); 4785 } 4786 } 4787 print "</NOBR>".$q->br."\n"; 4788 } 4789 # Now add any site links 4790 my($mkey,$marg,$mdesc,$micon,$murl,$targ,$level,$insec,$noop); 4791# my($itemx) = 1; 4792# while ( defined $config{"menu-item$itemx"} ) { 4793# $marg = $config{"menu-item$itemx"}; 4794# $mkey = "Item $itemx"; 4795# $itemx += 1; 4796## This way is slower, but more user-friendly 4797 foreach ( sort keys %config ) { 4798 if( /^menu-(\S+)/i ) { 4799 $mkey = $1; 4800 $marg = $config{$_}; 4801 4802 ( $mdesc, $murl, $micon, $targ, $level, $insec, $noop ) = 4803 parse_ext($marg); 4804 if($seclevel >= $level ) { # Are we high enough security level? 4805 if( !$micon and $mdesc =~ /\.gif$/ ) { 4806 $micon = $mdesc; $mdesc = $mkey; 4807 } 4808 $mdesc = $mkey if(!$mdesc); #default 4809 $micon = "cog-sm.gif" if(!$micon); #default 4810 if(!$noop and $murl !~ /\.html?$/ ) { 4811 if( $murl =~ /\?/ ) { $murl .= '&'; } else { $murl .= '?'; } 4812 $murl .= "fi=".$q->escape($router) 4813 ."&url=".$q->escape($q->url()) 4814 ."&t=".$q->escape($targ)."&L=".$seclevel; 4815 } 4816 print "<NOBR>"; 4817 print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$micon), 4818 width=>15, height=>15, alt=>"$mdesc", class=>'sidemenu' })," "; 4819 print $q->a({href=>$murl, target=>$targ, class=>'sidemenu' },$mdesc ); 4820 print "</NOBR>".$q->br."\n"; 4821 } # security level 4822 } # if 4823 } # foreach 4824} 4825 4826# Finish off the page 4827print "</FONT>\n" if( defined $config{'routers.cgi-menufontsize'} ); 4828print "</DIV>\n<!-- Version $VERSION -->\n"; 4829print "<!-- R:[$router] I:[$interface] A:[$archive] U:[$authuser] -->\n"; 4830print "<!--\n$debugmessage\n-->\n" if($debugmessage); 4831print $q->end_html(); 4832} 4833 4834############################ 4835# Main frame set 4836 4837sub do_main() 4838{ 4839 my( $javascript, $framethree ); 4840 my( $urla, $urlb, $urlc, $urlh ); 4841 my( $menuwidth ) = 150; 4842 my( $frameopts ) = " marginwidth=2 marginheight=2 bgcolor=$menubgcolour "; 4843 my( $borderwidth ) = 1; 4844 4845 $gtype = "" if(!defined $gtype); 4846 $mtype = "" if(!defined $mtype); 4847 $gstyle = "" if(!defined $gstyle); 4848 $gopts = "" if(!defined $gopts); 4849 $baropts = "cam" if(!defined $baropts); 4850 4851 $borderwidth = $config{'routers.cgi-borderwidth'} 4852 if( defined $config{'routers.cgi-borderwidth'} ); 4853 4854 $menuwidth = $config{'routers.cgi-menuwidth'} 4855 if( defined $config{'routers.cgi-menuwidth'} ); 4856 $menuwidth = 150 if ( $menuwidth < 100 or $menuwidth > 500 4857 or $menuwidth !~ /^\d+$/ ); 4858 4859# Javasciript funtion to reload the page with a specified set of params. 4860 $javascript = " 4861 function makebookmark(rtr,rtrif,xgtype,xgstyle,xgopts,bars,extra,arch) { 4862 var newurl; 4863 newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif); 4864 if ( xgtype != '' ) { newurl = newurl + '&xgtype='+xgtype; } 4865 if ( xgstyle != '' ) { newurl = newurl + '&xgstyle='+xgstyle; } 4866 if ( xgopts != '' ) { newurl = newurl + '&xgopts='+xgopts ; } 4867 if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } 4868 if ( arch != '' ) { newurl = newurl + '&arch='+escape(arch) ; } 4869 if ( bars != '' && rtrif == '__compact' ) { newurl = newurl + '&bars='+bars ; } 4870 window.location = newurl; 4871 } 4872 function makearchmark(rtr,rtrif,extra,arch) { 4873 var newurl; 4874 newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif) 4875 +'&archive='+arch; 4876 if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } 4877 window.location = newurl; 4878 } 4879 var lastaurl; 4880 var lastburl; 4881 function setlocationa(url) { 4882 if( lastaurl != url ) { 4883 self.menu.location = url; 4884 lastaurl = url; 4885 } 4886 return 0; 4887 } 4888 function setlocationb(url) { 4889 if( self.menub ) { 4890 if( lastburl != url ) { 4891 self.menub.location = url; 4892 lastburl = url; 4893 } 4894 } 4895 return 0; 4896 } 4897"; 4898 4899 $urlb = $meurlfull."?".optionstring({ page=>"graph", nomenu=>1 }); 4900 4901 if( $twinmenu ) { 4902 $urla = $meurlfull."?".optionstring({ page=>"menu", xmtype=>"routers" 4903 }) ."#top"; 4904 $urlc = $meurlfull."?".optionstring({ page=>"menub", xmtype=>"options" 4905 }) ."#top"; 4906 $framethree = "<FRAMESET border=$borderwidth $frameopts 4907 cols=$menuwidth,*,$menuwidth class=main> 4908 <FRAME name=menu src=$urla scrolling=auto nowrap $frameopts class=main id=leftframe> 4909 <FRAME name=graph src=$urlb scrolling=auto $frameopts class=main id=graphframe> 4910 <FRAME name=menub src=$urlc scrolling=auto nowrap $frameopts class=main id=rightframe> 4911 </FRAMESET>\n"; 4912 } else { 4913 $urla = $meurlfull."?".optionstring({ page=>"menu", nomenu=>1 })."#top"; 4914 $framethree = "<FRAMESET border=$borderwidth $frameopts 4915cols=$menuwidth,* > 4916 <FRAME name=menu src=$urla scrolling=auto nowrap $frameopts class=main id=leftframe> 4917 <FRAME name=graph src=$urlb scrolling=auto $frameopts class=main id=graphframe> 4918 </FRAMESET>\n"; 4919 } 4920 4921 $urlh = $meurlfull."?".optionstring({ page=>"head" }); 4922 4923 if($q->cookie('auth')) { 4924 print "<!-- ".$q->cookie('auth')." -->\n"; 4925 } 4926 4927 print "<HTML><HEAD>\n<!-- $pagetype -->\n"; 4928 print "<LINK rel=\"stylesheet\" type=\"text/css\" href=\"" 4929 .$config{"routers.cgi-stylesheet"}."\" />\n" 4930 if($config{"routers.cgi-stylesheet"}); 4931 print "<TITLE>$windowtitle</TITLE></HEAD><SCRIPT language=JavaScript><!--\n$javascript\n//--></SCRIPT>\n"; 4932 if(! $q->param('noheader') ) { 4933 print "<FRAMESET border=$borderwidth $frameopts rows=50,* bgcolor=$menubgcolour class=main>\n"; 4934 print "<FRAME name=head src=$urlh resize scrolling=no $frameopts class=main id=topframe>\n"; 4935 } 4936 print "$framethree\n"; 4937 if(! $q->param('nohead') ) { print "</FRAMESET>\n"; } 4938 print <<EOT 4939<NOFRAMES> 4940 <BODY> 4941 Sorry, routers.cgi does not support non-frames browsers. 4942 Upgrade to Netscape 4.x or later, or MSIE 4.x or later. 4943 </BODY> 4944</NOFRAMES> 4945<!-- Language $language --> 4946<!-- User $authuser --> 4947<!-- Version $VERSION --> 4948<!-- $debugmessage --> 4949<!-- NOTE: 4950 You should not normally run routers.cgi from the command line. It is 4951 intended to be used as a CGI script, called by your Web Server. When 4952 installed in this way, you should be able to view the output in your 4953 web browser by calling the CGI script through your web server. 4954 You may want to call it from the command line with the -A parameter 4955 in order to manually create Archived graphs. In this case, use -D and 4956 -T to specify Device and Target, and -s, -t for Style and Type. 4957 Similarly, the -C option will export CSV data to standard output. 4958 You can use the -U option to specify an authenticated username if required. 4959 --> 4960</HTML> 4961EOT 4962; 4963# now clean up the verify stuff if it's there 4964# we cant do this in the do_verify subroutine because the file is required 4965# by a future connection. 4966unlink ($config{'routers.cgi-graphpath'}.$pathsep."redsquare.png") 4967 if( -f $config{'routers.cgi-graphpath'}.$pathsep."redsquare.png" ); 4968 4969} 4970 4971######################## 4972# Is this target 'active'? 4973# return 0 (inactive), 1 (active), error message 4974sub isactive($) { 4975 my($curif) = $_[0]; 4976 my($start,$end,$interval,$rrd,$data,$names); 4977 my($e,$line,$val); 4978 my(@params)=('MAX'); # Should we use MAX? Might be confused with -ve data 4979# my(@params)=('AVG'); 4980 my($dwmy,$lastupdate); 4981 4982 # Userdefined! 4983 return "Summaries are always active!" 4984 if( $interfaces{$curif}{issummary} ); # should never happen 4985 if( $interfaces{$curif}{usergraph} ) { 4986 my ( @ctgt, $t, $r ); 4987 foreach $t ( @{$interfaces{$curif}{targets}} ) { 4988 next if( $interfaces{$t}{usergraph} ); # prevent looping 4989 return 1 if( isactive($t) ); # optimise if possible 4990 } 4991 return 0; 4992 } 4993 4994 # If this is an archive, then uselastupdate=2 and rrd is already changed 4995 $rrd = $interfaces{$curif}{rrd}; 4996 if($rrdcached and $rrdcached!~/^unix:/) { 4997 my($pth) = $config{'routers.cgi-dbpath'}; 4998 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 4999 $rrd =~ s/^$pth\/*//; 5000 } 5001 $dwmy = $gtype; 5002 5003 $end = 'now'; 5004 if($uselastupdate) { 5005 $lastupdate = RRDs::last($rrd,@rrdcached); 5006 if($lastupdate) { $end = $lastupdate; } 5007 $end = $archivetime 5008 if($uselastupdate > 1 and $archivetime); 5009 $end = $basetime if($basetime); 5010 } 5011 if( $dwmy =~ /-/ ) { 5012 if ( $dwmy =~ /6/ ) { push @params, "-e", "$end-6h"; } 5013 elsif ( $dwmy =~ /d/ ) { push @params, "-e", "$end-24h";} 5014 elsif ( $dwmy =~ /w/ ) { push @params, "-e", "$end-7d"; } 5015 elsif ( $dwmy =~ /m/ ) { push @params, "-e", "$end-30d";} 5016 elsif ( $dwmy =~ /y/ ) { push @params, "-e", "$end-365d";} 5017 } else { 5018 push @params, '-e', $end; 5019 } 5020 if ( $dwmy =~ /6/ ) { $interval = "60"; } 5021 elsif ( $dwmy =~ /d/ ) { $interval = "300"; } 5022 elsif ( $dwmy =~ /w/ ) { $interval = "1800"; } 5023 elsif ( $dwmy =~ /m/ ) { $interval = "7200"; } 5024 elsif ( $dwmy =~ /y/ ) { $interval = "86400"; } 5025 5026 push @params,'-r',86400; # always use daily max RRA 5027 push @params,'-s',"end-".($interval*400);# just back to start of this graph 5028 5029 ($start,$interval,$names,$data) = RRDs::fetch($rrd,@params,@rrdcached); 5030 $e = RRDs::error(); 5031 return "Error: $e" if($e); # so erroring targets display by default 5032 foreach $line ( @$data ) { 5033 foreach $val ( @$line ) { return 1 if($val); } 5034 } 5035 return 0; # not active: no values other than 0 or UNKN were found 5036} 5037 5038########################## 5039# Graph panel 5040 5041sub sinout { 5042 my($interface); 5043 my($sin,$sout,$sext); 5044 my($ssin,$ssout,$ssext); 5045 my($l,$escunit,$escunit2); 5046 my($alt); 5047 5048 ($interface,$alt,$l) = @_; 5049 5050 $escunit = $interfaces{$interface}{unit}; 5051 $escunit =~ s/%/%%/g; 5052 $escunit =~ s/:/\\:/g; 5053 $escunit =~ s/ / /g; 5054 $escunit2 = $interfaces{$interface}{unit2}; 5055 $escunit2 =~ s/%/%%/g; 5056 $escunit2 =~ s/:/\\:/g; 5057 $escunit2 =~ s/ / /g; 5058 5059 $sin=langmsg(6403,"In: "); $sout=langmsg(6404,"Out:"); $sext = "Ext:"; 5060 $ssext = $ssin = $ssout = ""; 5061 $sin = $interfaces{$interface}{legendi} 5062 if( defined $interfaces{$interface}{legendi} ); 5063 $sout= $interfaces{$interface}{legendo} 5064 if( defined $interfaces{$interface}{legendo} ); 5065 $sext = $interfaces{$interface}{legendx} 5066 if( defined $interfaces{$interface}{legendx} ); 5067 5068 if( $alt and $interfaces{$alt}{overridelegend} 5069 and $interfaces{$interface}{shdesc} 5070 and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} 5071 or $interfaces{$alt}{noo} or $interfaces{$alt}{noi} ) 5072 ) { 5073 $sin = $sout = $interfaces{$interface}{shdesc}.':'; 5074 } 5075 5076 if(!$l) { 5077 $l = length $sin; $l = length $sout if($l < length $sout); 5078 } 5079 $sin = substr($sin.' ',0,$l); 5080 $sout= substr($sout.' ',0,$l); 5081 $sin =~ s/:/\\:/g; $sout =~ s/:/\\:/g; 5082 $sin =~ s/%/%%/g; $sout =~ s/%/%%/g; 5083 if( $interfaces{$interface}{integer} ) { 5084 $ssin = "%5.0lf"; $ssout = "%5.0lf"; $ssext = "%5.0lf"; 5085 } elsif( $interfaces{$interface}{fixunits} 5086 and !$interfaces{$interface}{exponent} ) { 5087 $ssin = "%7.2lf "; $ssout = "%7.2lf "; $ssext = "%7.2lf"; 5088 } else { 5089 $ssin = "%6.2lf %s"; $ssout = "%6.2lf %s"; $ssext = "%6.2lf %s"; 5090 } 5091 if( defined $config{'routers.cgi-legendunits'} 5092 and $config{'routers.cgi-legendunits'} =~ /y/i ) { 5093 $ssin .= $escunit; $ssout .= $escunit2; 5094 } 5095 $sin .= $ssin; $sout .= $ssout; 5096 if( $interfaces{$interface}{mode} eq "SERVER" 5097 and $interface eq "CPU" ) { 5098 $sin = "usr\\:%6.2lf%%"; $sout = "sys\\:%6.2lf%%"; 5099 $sext = "wa\\: %6.2lf%%"; 5100 $ssin = $ssout = $ssext = "%6.2lf%%"; 5101 } 5102 5103 return ( $sin,$sout,$sext, $ssin,$ssout,$ssext ); 5104} 5105 5106sub usr_params(@) 5107{ 5108 my($ds0,$ds1,$mds0,$mds1); 5109 my($lin, $lout); 5110 my($dwmy,$interface) = @_; 5111 my($ssin, $ssout, $sin, $sout, $sext, $ssext); 5112 my($l,$defrrd, $curif); 5113 my($legendi,$legendo); 5114 my(@clr,$ifcnt, $c, $escunit); 5115 my($totindef,$totoutdef,$incnt, $outcnt); 5116 my($totin,$totout) = ("totin","totout"); 5117 my($stacking) = 0; 5118 my($mirroring) = 0; 5119 my($max1, $max2); 5120 my($greydef) = "0"; # extra RPN is added if necessary 5121 my($havepeaks) = 0; 5122 my($workday) = 0; 5123# my($timezone) = 0; # use the global 5124 my(@wdparams) = (); 5125 my($maxlbl,$avglbl,$curlbl,$lastlbl) = ('Max','Avg','Cur','Last'); 5126 my($gmaxlbl,$gavglbl,$gcurlbl,$glastlbl); 5127 my(@extraparams) = (); 5128 my($titlemaxlen) = 128; 5129 my($daemonsuffix) = ""; 5130 my(@sorted); 5131 my($leglen) = 0; # length of legends 5132 5133 if($rrdcached) { 5134 $daemonsuffix = "daemon=$rrdcached"; 5135 $daemonsuffix =~ s/:/\\:/g; 5136 $daemonsuffix = ":$daemonsuffix"; 5137 } 5138 5139 $titlemaxlen = $config{'routers.cgi-maxtitle'}?$config{'routers.cgi-maxtitle'}:128; 5140 5141 $maxlbl = langmsg(2200,$maxlbl); $avglbl = langmsg(2201,$avglbl); 5142 $curlbl = langmsg(2202,$curlbl); $lastlbl = langmsg(2203,$lastlbl); 5143 $gmaxlbl = langmsg(6200,$maxlbl); $gavglbl = langmsg(6201,$avglbl); 5144 $gcurlbl = langmsg(6202,$curlbl); $glastlbl = langmsg(6203,$lastlbl); 5145 5146 if( defined $config{'routers.cgi-daystart'} 5147 and defined $config{'routers.cgi-dayend'} 5148 and $config{'routers.cgi-daystart'}<$config{'routers.cgi-dayend'} 5149 and $dwmy !~ /y/ ){ 5150 $workday = 1; 5151 } 5152 5153 # stacking? 5154 if( defined $interfaces{$interface}{graphstyle} 5155 and $interfaces{$interface}{graphstyle} =~ /stack/i ) { 5156 $stacking = 1; # first is AREA, then STACK 5157 } 5158 if( defined $interfaces{$interface}{graphstyle} 5159 and $interfaces{$interface}{graphstyle} =~ /mirror/i ) { 5160 $mirroring = 1; 5161 } 5162 # identify colours 5163 if( defined $interfaces{$interface}{colours} ) { 5164 @clr = @{$interfaces{$interface}{colours}}; 5165 } 5166 if(! @clr ) { 5167 if( $gstyle =~ /b/ ) { 5168 @clr = ( "#000000","#888888","#cccccc","#dddddd","#666666","#444444", 5169 "#222222", "#aaaaaa", "#eeeeee", "#bbbbbb", "#555555", "#333333" ); 5170 } else { 5171 @clr = ( "#0000ff","#00ff00","#ff0000","#00cccc","#cccc00","#cc00cc", 5172 "#8800ff", "#88ff00", "#ff8800", "#0088ff", "#ff0088", "#00ff88" ); 5173 } 5174 } 5175 $ifcnt = $#{$interfaces{$interface}{targets}}; 5176 5177# Now the workday highlights, if required 5178 if( $workday ) { 5179 # note we must have a DS in there even if it is not used 5180 push @wdparams, "CDEF:wdtest=in1,POP," 5181 ."TIME,3600,/,$timezone,+,DUP,24,/,7,%,DUP,4,LT,EXC,2,GE,+,2,LT," 5182 ."EXC,24,%,DUP," 5183 .trim($config{'routers.cgi-daystart'}).",GE,EXC," 5184 .trim($config{'routers.cgi-dayend'}).",LT,+,2,EQ,1," 5185 ."0,IF,0,IF"; # Set to 1 if in working day 5186 # mark the working day background, if not in b&w mode 5187 if( $gstyle !~ /b/ ) { 5188 push @wdparams, "CDEF:wd=wdtest,INF,0,IF", "AREA:wd#ffffcc"; 5189 push @wdparams, "CDEF:mwd=wd,-1,*", "AREA:mwd#ffffcc" ; 5190# if($mirroring); 5191 } 5192 } 5193 5194 while( $#clr < $ifcnt ) { push @clr, @clr; } 5195 5196 $totindef = "CDEF:$totin=0"; $totoutdef = "CDEF:$totout=0"; 5197 $ifcnt = 0; $incnt = $outcnt = 0; 5198 5199 if( $interfaces{$interface}{sortby} ) { 5200 @sorted = sorttargets($interface,$dwmy,$interfaces{$interface}{sortby}); 5201 } else { 5202 @sorted = @{$interfaces{$interface}{targets}}; 5203 } 5204 5205 foreach $curif ( @sorted ) { 5206 if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}) { 5207 my $olen = length $interfaces{$curif}{legendo}; 5208 $leglen = $olen if($olen > $leglen); 5209 } 5210 if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}) { 5211 my $ilen = length $interfaces{$curif}{legendi}; 5212 $leglen = $ilen if($ilen > $leglen); 5213 } 5214 } 5215 $leglen = 20 if($leglen > 20); # sanity check 5216 5217 ################################################### 5218 # MAIN LOOP THROUGH COMPONENT TARGETS STARTS HERE # 5219 ################################################### 5220 foreach $curif ( @sorted ) { 5221 # loop through all interfaces 5222 5223 if($interfaces{$interface}{active}) { 5224 next if(!isactive($curif)); 5225 } 5226 $ifcnt++; 5227 5228 $defrrd = $interfaces{$curif}{rrd}; 5229 $defrrd =~ s/:/\\:/g; 5230 if($rrdcached and $rrdcached!~/^unix:/) { 5231 my($pth) = $config{'routers.cgi-dbpath'}; 5232 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 5233 $defrrd =~ s/^$pth\/*//; 5234 } 5235 5236# $debugmessage .= "RRD: $defrrd\n"; 5237 5238 ($sin,$sout,$sext ,$ssin,$ssout,$ssext) = sinout($curif,$interface,$leglen); 5239 5240 if ( $dwmy =~ /s/ ) { 5241 $lin=""; $lout=""; 5242 } else { 5243 $lin = langmsg(6405,"Inbound"); $lout = langmsg(6406,"Outbound"); 5244 $lin = $interfaces{$curif}{legend1} 5245 if( defined $interfaces{$curif}{legend1} ); 5246 $lout = $interfaces{$curif}{legend2} 5247 if( defined $interfaces{$curif}{legend2} ); 5248 if( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} ) { 5249 $lin = $interfaces{$curif}{desc}." ($lin)" 5250 if($lin ne $interfaces{$curif}{desc}); 5251 $lout= $interfaces{$curif}{desc}." ($lout)" 5252 if($lout ne $interfaces{$curif}{desc}); 5253 } 5254 $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; 5255 $lin = ':'.$lin; $lout = ':'.$lout; 5256 if($interfaces{$interface}{noo} or $interfaces{$curif}{noo}) { 5257 $lin .= "\\l" 5258 } else { $lout .= "\\l"; } 5259 } 5260 $lin = substr( $lin." ",0,30 ) 5261 if($lin and !$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}); 5262 5263 if( $interfaces{$interface}{nolegend} or 5264 $interfaces{$interface}{nodetails} ) { 5265 $lin = $lout = ""; 5266 } 5267 5268 ($ds0, $ds1) = ("ds0", "ds1"); 5269 push @params, 5270 "DEF:in$ifcnt=".$defrrd.":$ds0:" 5271 .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") 5272 .$daemonsuffix, 5273 "DEF:out$ifcnt=".$defrrd.":$ds1:" 5274 .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") 5275 .$daemonsuffix; 5276 ($ds0, $ds1) = ("in$ifcnt", "out$ifcnt"); 5277 5278 # Now for unknasprev 5279 if( $interfaces{$curif}{unknasprev} 5280 or $interfaces{$interface}{unknasprev} ) { 5281 if($RRDs::VERSION >= 1.00039 ) { 5282 push @params, 5283 "CDEF:unpin$ifcnt=$ds0,UN,PREV,$ds0,IF", 5284 "CDEF:unpout$ifcnt=$ds1,UN,PREV,$ds1,IF"; 5285 ($ds0, $ds1) = ("unpin$ifcnt", "unpout$ifcnt"); 5286 } 5287 } 5288 # Now for unknaszero 5289 elsif( $interfaces{$curif}{unknaszero} 5290 or $interfaces{$interface}{unknaszero} ) { 5291 push @params, 5292 "CDEF:unin$ifcnt=$ds0,UN,0,$ds0,IF", 5293 "CDEF:unout$ifcnt=$ds1,UN,0,$ds1,IF"; 5294 ($ds0, $ds1) = ("unin$ifcnt", "unout$ifcnt"); 5295 } else { 5296 if($RRDs::VERSION >= 1.00039 ) { 5297 my($step) = $routers{$router}{interval}; 5298 if($step) { $step *= 60; } else { $step = 300; } 5299 push @params, 5300 "CDEF:unxin$ifcnt=NOW,TIME,-,$step,LT,$ds0,UN,+,2,EQ,PREV,$ds0,IF", 5301 "CDEF:unxout$ifcnt=NOW,TIME,-,$step,LT,$ds1,UN,+,2,EQ,PREV,$ds1,IF"; 5302 ($ds0, $ds1) = ("unxin$ifcnt", "unxout$ifcnt"); 5303 } 5304 } 5305 5306 # Needs to be here because ds1 must be defined 5307 push @params, @wdparams if($workday and ($ifcnt == 1)); 5308 5309### do this if we are using BITS 5310 if( $interfaces{$curif}{mult} and ($interfaces{$curif}{mult} != 1) ) { 5311 push @params, "CDEF:fin$ifcnt=$ds0,".$interfaces{$curif}{mult}.",*", 5312 "CDEF:fout$ifcnt=$ds1,".$interfaces{$curif}{mult}.",*"; 5313 ($ds0, $ds1) = ("fin$ifcnt", "fout$ifcnt"); 5314 } 5315 if( $interfaces{$curif}{factor} and $interfaces{$curif}{factor}!=1) { 5316 push @params, "CDEF:ffin$ifcnt=$ds0,".$interfaces{$curif}{factor}.",*", 5317 "CDEF:ffout$ifcnt=$ds1,".$interfaces{$curif}{factor}.",*"; 5318 ($ds0, $ds1) = ("ffin$ifcnt", "ffout$ifcnt"); 5319 } 5320 if( $interfaces{$interface}{factor} 5321 and $interfaces{$interface}{factor}!=1) { 5322 push @params, "CDEF:ffinx$ifcnt=$ds0,".$interfaces{$interface}{factor}.",*", 5323 "CDEF:ffoutx$ifcnt=$ds1,".$interfaces{$interface}{factor}.",*"; 5324 ($ds0, $ds1) = ("ffinx$ifcnt", "ffoutx$ifcnt"); 5325 } 5326 if( $interfaces{$curif}{c2fi} ) { 5327 push @params, "CDEF:c2fin$ifcnt=$ds0,1.8,*,32,+"; 5328 $ds0 = "c2fin$ifcnt"; 5329 } 5330 if( $interfaces{$curif}{c2fo} ) { 5331 push @params, "CDEF:c2fout$ifcnt=$ds1,1.8,*,32,+"; 5332 $ds1 = "c2fout$ifcnt"; 5333 } 5334 5335 # For later referral by userdefined calculations 5336 $interfaces{$curif}{ds0} = $ds0; 5337 $interfaces{$curif}{ds1} = $ds1; 5338 5339 if(!$interfaces{$curif}{noi} ) { 5340 if($RRDs::VERSION < 1.00039 ) { 5341 $totindef .= ",$ds0,UN,0,$ds0,IF,+"; 5342 } else { 5343# $totindef .= ",$ds0,DUP,UN,EXC,PREV($ds0),DUP,UN,EXC,0,EXC,IF,EXC,IF,+"; 5344 $totindef .= ",NOW,TIME,-,300,LT,$ds0,UN,+,2,EQ,PREV($ds0),DUP,UN,EXC,0,EXC,IF,$ds0,IF,+"; 5345 } 5346 $incnt++; 5347 if( !$interfaces{$curif}{unknasprev} 5348 and !$interfaces{$interface}{unknasprev} 5349 and !$interfaces{$curif}{unknaszero} ) { 5350 $greydef .= ",in$ifcnt,UN,+"; 5351 } 5352 } 5353 if(!$interfaces{$curif}{noo} ) { 5354 if($RRDs::VERSION < 1.00039 ) { 5355 $totoutdef .= ",$ds1,UN,0,$ds1,IF,+"; 5356 } else { 5357# $totoutdef.= ",$ds1,DUP,UN,EXC,PREV($ds1),DUP,UN,EXC,0,EXC,IF,EXC,IF,+"; 5358 $totoutdef .= ",NOW,TIME,-,300,LT,$ds1,UN,+,2,EQ,PREV($ds1),DUP,UN,EXC,0,EXC,IF,$ds1,IF,+"; 5359 } 5360 $outcnt++; 5361 if( !$interfaces{$curif}{unknasprev} 5362 and !$interfaces{$interface}{unknasprev} 5363 and !$interfaces{$curif}{unknaszero} ) { 5364 $greydef .= ",out$ifcnt,UN,+"; 5365 } 5366 } 5367# now for the peaks stuff 5368 ($mds0, $mds1) = ("ds0", "ds1"); 5369 push @params, 5370 "DEF:min$ifcnt=".$defrrd.":$mds0:MAX".$daemonsuffix 5371 .(($RRDs::VERSION >= 1.4)?":reduce=MAX":""), 5372 "DEF:mout$ifcnt=".$defrrd.":$mds1:MAX".$daemonsuffix 5373 .(($RRDs::VERSION >= 1.4)?":reduce=MAX":""); 5374 ($mds0, $mds1) = ("min$ifcnt", "mout$ifcnt"); 5375### Do this if we are using BITS 5376 if( $interfaces{$curif}{mult} ne 1 ) { 5377 push @params, "CDEF:fmin$ifcnt=$mds0,".$interfaces{$curif}{mult}.",*", 5378 "CDEF:fmout$ifcnt=$mds1,".$interfaces{$curif}{mult}.",*"; 5379 ($mds0, $mds1) = ("fmin$ifcnt", "fmout$ifcnt"); 5380 } 5381 if( $interfaces{$curif}{factor} and $interfaces{$curif}{factor}!=1) { 5382 push @params,"CDEF:ffmin$ifcnt=$mds0," 5383 .$interfaces{$curif}{factor}.",*", 5384 "CDEF:ffmout$ifcnt=$mds1,".$interfaces{$curif}{factor}.",*"; 5385 ($mds0, $mds1) = ("ffmin$ifcnt", "ffmout$ifcnt"); 5386 } 5387 if( $interfaces{$interface}{factor} and $interfaces{$interface}{factor}!=1 ) { 5388 push @params,"CDEF:ffminx$ifcnt=$mds0," 5389 .$interfaces{$interface}{factor}.",*", 5390 "CDEF:ffmoutx$ifcnt=$mds1,".$interfaces{$interface}{factor}.",*"; 5391 ($mds0, $mds1) = ("ffminx$ifcnt", "ffmoutx$ifcnt"); 5392 } 5393 if( $interfaces{$curif}{c2fi} ) { 5394 push @params, "CDEF:mc2fin$ifcnt=$mds0,1.8,*,32,+"; 5395 $mds0 = "mc2fin$ifcnt"; 5396 } 5397 if( $interfaces{$curif}{c2fo} ) { 5398 push @params, "CDEF:mc2fout$ifcnt=$mds1,1.8,*,32,+"; 5399 $mds1 = "mc2fout$ifcnt"; 5400 } 5401 5402 # For later referral by userdefined calculations 5403 $interfaces{$curif}{mds0} = $mds0; 5404 $interfaces{$curif}{mds1} = $mds1; 5405### 5406# And the percentages 5407 $max1 = $max2 = $interfaces{$curif}{max}; 5408 $max1 = $interfaces{$curif}{max1} if(defined $interfaces{$curif}{max1}); 5409 $max2 = $interfaces{$curif}{max2} if(defined $interfaces{$curif}{max2}); 5410 if( $max1 && $dwmy !~ /s/ ) { 5411 push @params, 5412 "CDEF:pcin$ifcnt=$ds0,100,*,".$max1.",/", 5413 "CDEF:mpcin$ifcnt=$mds0,100,*,".$max1.",/"; 5414 } 5415 if( $max2 && $dwmy !~ /s/ ) { 5416 push @params, 5417 "CDEF:pcout$ifcnt=$ds1,100,*,".$max2.",/", 5418 "CDEF:mpcout$ifcnt=$mds1,100,*,".$max2.",/"; 5419 } 5420 5421 # For scaleshift 5422 if( defined $interfaces{$interface}{scaleshift} 5423 and ($RRDs::VERSION >= 1.3) ) { 5424 if(!$interfaces{$interface}{altscale} or $interfaces{$curif}{altscale}){ 5425 push @params, 5426 "CDEF:x$ds1=$ds1," 5427 .$interfaces{$interface}{shift}.",-," 5428 .$interfaces{$interface}{scale}.",/"; 5429# "CDEF:x$mds1=$mds1,".$interfaces{$interface}{scale}.",/," 5430# .$interfaces{$interface}{shift}.",-"; 5431 } else { 5432 push @params, "CDEF:x$ds1=$ds1"; 5433# , "CDEF:x$mds1=$mds1"; 5434 } 5435 if($interfaces{$interface}{altscale} and $interfaces{$curif}{altscale}){ 5436 push @params, 5437 "CDEF:x$ds0=$ds0," 5438 .$interfaces{$interface}{shift}.",-," 5439 .$interfaces{$interface}{scale}.",/"; 5440# "CDEF:x$mds0=$mds0,".$interfaces{$interface}{scale}.",/," 5441# .$interfaces{$interface}{shift}.",-"; 5442 } else { 5443 push @params, "CDEF:x$ds0=$ds0"; 5444# , "CDEF:x$mds0=$mds0"; 5445 } 5446 } else { 5447 push @params, "CDEF:x$ds1=$ds1"; 5448# , "CDEF:x$mds1=$mds1"; 5449 push @params, "CDEF:x$ds0=$ds0"; 5450# , "CDEF:x$mds0=$mds0"; 5451 } 5452 5453 if($mirroring and $lin and $lout ) { 5454 $lout = ""; 5455 $lin = $interfaces{$curif}{desc}; 5456 $lin = substr($lin,0,$titlemaxlen) if(length($lin)>$titlemaxlen); 5457 $lin =~ s/:/\\:/g; 5458 $lin = ":$lin\\l"; 5459 } else { 5460 if( !$interfaces{$interface}{nolegend} and 5461 !$interfaces{$interface}{nodetails} and 5462 !$interfaces{$interface}{nodesc} and 5463 $dwmy !~ /s/ and 5464 !$interfaces{$interface}{noi} and 5465 !$interfaces{$interface}{noo}) { 5466 my($tmpt) = $interfaces{$curif}{desc}; 5467 $tmpt = substr($tmpt,0,$titlemaxlen) 5468 if(length($tmpt)>$titlemaxlen); 5469 push @params, "COMMENT:".decolon("$tmpt:\\l"); 5470 } 5471 } 5472 if(! $interfaces{$interface}{nolines} ) { 5473 $c=""; 5474 if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}) { 5475 $c = shift @clr; push @clr, $c; 5476 if( !$stacking ) { 5477 push @params, "LINE$linewidth:x$ds0$c$lin" ; 5478 } elsif( $stacking > 1 ) { 5479 push @params, "STACK:$ds0$c$lin" ; 5480 } else { 5481 push @params, "AREA:$ds0$c$lin" ; 5482 $stacking = 2; 5483 } 5484 } 5485 if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}) { 5486 my($tmpds) = $ds1; 5487 $c = "" if( $c and !$mirroring ); 5488 if(!$c) { $c = shift @clr; push @clr, $c; } 5489 if($mirroring) { 5490 push @params, "CDEF:mirror$ifcnt=$ds1,-1,*"; 5491 $tmpds = "mirror$ifcnt"; 5492 } elsif(!$stacking) { $tmpds = "x$ds1"; } 5493 if( !$stacking ) { 5494 push @params, "LINE$linewidth:$tmpds$c$lout" ; 5495 } elsif($mirroring) { 5496 if(@extraparams) { 5497 push @extraparams, "STACK:$tmpds$c$lout"; 5498 } else { 5499 push @extraparams, "AREA:$tmpds$c$lout"; 5500 } 5501 } elsif( $stacking > 1 ) { 5502 push @params, "STACK:$tmpds$c$lout"; 5503 } else { 5504 push @params, "AREA:$tmpds$c$lout"; 5505 $stacking = 2; 5506 } 5507 } 5508 } # nolines 5509 5510# now for the labels at the bottom 5511 if( !$interfaces{$interface}{nolegend} and 5512 !$interfaces{$interface}{nodetails} ) { 5513 if( $dwmy !~ /s/ ) { 5514 if( $max1 ) { 5515 if(!$interfaces{$interface}{noi} 5516 and !$interfaces{$curif}{noi}) { 5517 push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g" ; 5518 push @params ,"GPRINT:mpcin$ifcnt:MAX: (%2.0lf%%)\\g" 5519 if($interfaces{$curif}{percent}); 5520 push @params,"GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g" ; 5521 push @params ,"GPRINT:pcin$ifcnt:AVERAGE: (%2.0lf%%)\\g" 5522 if($interfaces{$curif}{percent}); 5523 push @params,"GPRINT:$ds0:LAST: $gcurlbl $sin\\g" ; 5524 push @params ,"GPRINT:pcin$ifcnt:LAST: (%2.0lf%%)\\g" 5525 if($interfaces{$curif}{percent}); 5526 push @params, "COMMENT:\\l" ; 5527 } 5528 if(!$interfaces{$interface}{noo} 5529 and !$interfaces{$curif}{noo}) { 5530 push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g" ; 5531 push @params ,"GPRINT:mpcout$ifcnt:MAX: (%2.0lf%%)\\g" 5532 if($interfaces{$curif}{percent}); 5533 push @params,"GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g" ; 5534 push @params ,"GPRINT:pcout$ifcnt:AVERAGE: (%2.0lf%%)\\g" 5535 if($interfaces{$curif}{percent}); 5536 push @params,"GPRINT:$ds1:LAST: $gcurlbl $sout\\g" ; 5537 push @params ,"GPRINT:pcout$ifcnt:LAST: (%2.0lf%%)\\g" 5538 if($interfaces{$curif}{percent}); 5539 push @params, "COMMENT:\\l" ; 5540 } 5541 } else { 5542 push @params, 5543 "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g", 5544 "GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g", 5545 "GPRINT:$ds0:LAST: $gcurlbl $sin\\l" 5546 if(!$interfaces{$interface}{noi} 5547 and !$interfaces{$curif}{noi}); 5548 push @params, 5549 "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g", 5550 "GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g", 5551 "GPRINT:$ds1:LAST: $gcurlbl $sout\\l" 5552 if(!$interfaces{$interface}{noo} 5553 and !$interfaces{$curif}{noo}); 5554 } 5555 } else { 5556 ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); 5557 $legendi = $interfaces{$curif}{legendi} if(defined $interfaces{$curif}{legendi}); 5558 $legendo = $interfaces{$curif}{legendo} if(defined $interfaces{$curif}{legendo}); 5559 if( $interfaces{$interface}{overridelegend} 5560 and $interfaces{$curif}{shdesc} 5561 and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} 5562 or $interfaces{$curif}{noo} or $interfaces{$curif}{noi} ) 5563 ) { 5564 $legendi = $legendo = $interfaces{$curif}{shdesc}.':'; 5565 } 5566 $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; 5567 $legendi =~ s/%/%%/g; $legendo =~ s/%/%%/g; 5568 5569# my $meurlfullesc = $meurlfull; 5570# $meurlfullesc =~ s/:/\\:/g; 5571 push @params, 5572# "PRINT:$mds0:MAX:".$q->a({href=>"$meurlfullesc?" 5573# .optionstring({if=>$curif})}, 5574# $q->b($legendi))." $maxlbl $ssin, ", 5575 "PRINT:$mds0:MAX:".$q->b($legendi)." $maxlbl $ssin, ", 5576 "PRINT:$ds0:AVERAGE:$avglbl $ssin, ", 5577 "PRINT:$ds0:LAST:$lastlbl $ssin ".$q->br 5578 if(!$interfaces{$interface}{noi} 5579 and !$interfaces{$curif}{noi}); 5580 push @params, 5581# "PRINT:$mds1:MAX:".$q->a({href=>"$meurlfullesc?" 5582# .optionstring({if=>$curif})}, 5583# $q->b($legendo))." $maxlbl $ssout, ", 5584 "PRINT:$mds1:MAX:".$q->b($legendo)." $maxlbl $ssout, ", 5585 "PRINT:$ds1:AVERAGE:$avglbl $ssout, ", 5586 "PRINT:$ds1:LAST:$lastlbl $ssout ".$q->br 5587 if(!$interfaces{$interface}{noo} 5588 and !$interfaces{$curif}{noo}); 5589 } # s mode 5590 } # not nolegend mode 5591 } # end of loop through interfaces 5592 5593 # Add onto the end extra interface stuff (for mirroring mainly) 5594 push @params, @extraparams; 5595 5596 # add total line(s) if necessary 5597 if($interfaces{$interface}{withtotal} 5598 or $interfaces{$interface}{withaverage} ) { 5599 push @params, $totindef if(!$interfaces{$interface}{noi} and $incnt); 5600 push @params, $totoutdef if(!$interfaces{$interface}{noo} and $outcnt); 5601 if($interfaces{$interface}{nogroup} and $incnt and $outcnt) { 5602 push @params,"CDEF:totinout=$totin,$totout,+"; 5603 $incnt += $outcnt; 5604 $outcnt = 0; 5605 ($totin,$totout) = ("totinout",""); 5606 } 5607 if(!$interfaces{$interface}{noo} and $outcnt) { 5608 if($interfaces{$interface}{scaleshift} 5609 and !$interfaces{$interface}{altscale}) { 5610 push @params, 5611 "CDEF:x$totout=$totout," 5612 .$interfaces{$interface}{shift}.",-," 5613 .$interfaces{$interface}{scale}.",/"; 5614 } else { 5615 push @params,"CDEF:x$totout=$totout" ; 5616 } 5617 } 5618 ($sin,$sout,$sext ,$ssin,$ssout,$ssext) = sinout($interface,0); 5619 $lin = langmsg(6100,"Total")." ".$interfaces{$interface}{legend1}; 5620 $lin = $interfaces{$interface}{legendti} 5621 if($interfaces{$interface}{legendti}); 5622 $lin = substr($lin.' ',0,30); 5623 if($interfaces{$interface}{noo} or !$outcnt) { $lin .= "\\l"; } 5624 $lout = langmsg(6100,"Total")." ".$interfaces{$interface}{legend2}."\\l"; 5625 $lout = $interfaces{$interface}{legendto}."\\l" 5626 if($interfaces{$interface}{legendto}); 5627 $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; 5628 $lin = ':'.$lin if($lin); $lout = ':'.$lout if($lout); 5629 if($interfaces{$interface}{withtotal} ) { 5630 if($interfaces{$interface}{nolegend} or $dwmy =~ /s/ ) { 5631 $lin = $lout = ""; 5632 } elsif($mirroring) { 5633 $lout = ""; 5634 $lin = langmsg(6101,"Total values"); $lin =~ s/:/\\:/g; 5635 $lin = ":$lin\\l"; 5636 } else { 5637 push @params, "COMMENT:" 5638 .decolon(langmsg(6101,"Total values").":\\l") 5639 if(!$interfaces{$interface}{noi} 5640 and !$interfaces{$interface}{noo} 5641 and !$interfaces{$interface}{nodesc} 5642 and !$interfaces{$interface}{nodetails}); 5643 } 5644 $c = ""; 5645 if(!$interfaces{$interface}{noi} and $incnt ) { 5646 $c = shift @clr; push @clr, $c; 5647 push @params, "LINE$linewidth:$totin$c$lin"; 5648 } 5649 if(!$interfaces{$interface}{noo} and $outcnt ) { 5650 $c = "" if( $c and !$mirroring ); 5651 if(!$c) { $c = shift @clr; push @clr, $c;} 5652 if($mirroring) { 5653 push @params, "CDEF:mtotout=$totout,-1,*"; 5654 push @params, "LINE$linewidth:mtotout$c$lout"; 5655 } else { 5656 push @params, "LINE$linewidth:x$totout$c$lout"; 5657 } 5658 } 5659 if( $dwmy !~ /s/ ) { 5660 if(!$interfaces{$interface}{nolegend} ) { 5661 push @params, 5662 "GPRINT:$totin:MAX:$gmaxlbl $sin\\g", 5663 "GPRINT:$totin:AVERAGE: $gavglbl $sin\\g", 5664 "GPRINT:$totin:LAST: $gcurlbl $sin\\l" 5665 if(!$interfaces{$interface}{noi} and $incnt); 5666 push @params, 5667 "GPRINT:$totout:MAX:$gmaxlbl $sout\\g", 5668 "GPRINT:$totout:AVERAGE: $gavglbl $sout\\g", 5669 "GPRINT:$totout:LAST: $gcurlbl $sout\\l" 5670 if(!$interfaces{$interface}{noo} and $outcnt); 5671 } 5672 } else { 5673 ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); 5674 $legendi = $interfaces{$interface}{legendi} 5675 if(defined $interfaces{$interface}{legendi}); 5676 $legendo = $interfaces{$interface}{legendo} 5677 if(defined $interfaces{$interface}{legendo}); 5678 5679 $legendi =~ s/:/\\:/g; 5680 $legendo =~ s/:/\\:/g; 5681 push @params, 5682 "PRINT:$totin:MAX:".$q->b(langmsg(2100,"Total")."\\:")." $maxlbl $ssin, ", 5683 "PRINT:$totin:AVERAGE:$avglbl $ssin, ", 5684 "PRINT:$totin:LAST:$lastlbl $ssin ".$q->br 5685 if(!$interfaces{$interface}{noi} and $incnt); 5686 push @params, 5687 "PRINT:$totout:MAX:".$q->b(langmsg(2100,"Total")."\\:")." $maxlbl $ssout, ", 5688 "PRINT:$totout:AVERAGE:$avglbl $ssout, ", 5689 "PRINT:$totout:LAST:$lastlbl $ssout ".$q->br 5690 if(!$interfaces{$interface}{noo} and $outcnt); 5691 } 5692 } 5693 } 5694 5695 # add average line if necessary 5696 if($interfaces{$interface}{withaverage} ) { 5697 # set avg to UNKN if we're in greyout, IE we have no data. 5698 push @params,"CDEF:avgin=$greydef,$incnt,$outcnt,+,EQ,UNKN,$totin,$incnt,/,IF" 5699 if(!$interfaces{$interface}{noi} and $incnt); 5700 if(!$interfaces{$interface}{noo} and $outcnt) { 5701 push @params, 5702 "CDEF:avgout=$greydef,$incnt,$outcnt,+,EQ,UNKN,$totout,$outcnt,/,IF"; 5703 if($interfaces{$interface}{scaleshift} 5704 and !$interfaces{$interface}{altscale}) { 5705 push @params, 5706 "CDEF:xavgout=avgout," 5707 .$interfaces{$interface}{shift}.",-," 5708 .$interfaces{$interface}{scale}.",/"; 5709 } else { 5710 push @params,"CDEF:xavgout=avgout" ; 5711 } 5712 } 5713 $lin = "Average ".$interfaces{$interface}{legend1}; 5714 $lin = $interfaces{$interface}{legendai} 5715 if($interfaces{$interface}{legendai}); 5716 $lin = substr($lin.' ',0,30); 5717 $lout= "Average ".$interfaces{$interface}{legend2}."\\l"; 5718 if($interfaces{$interface}{noo} or !$outcnt){ $lin .= "\\l"; } 5719 $lout = $interfaces{$interface}{legendao}."\\l" 5720 if($interfaces{$interface}{legendao}); 5721 $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; 5722 $lin = ':'.$lin if($lin); $lout = ':'.$lout if($lout); 5723 if($interfaces{$interface}{nolegend} or $dwmy=~ /s/ ) { 5724 $lin = $lout = ""; 5725 } elsif($mirroring) { 5726 $lout = ""; 5727 $lin = langmsg(6901,"Average values"); $lin =~ s/:/\\:/g; 5728 $lin = ":$lin\\l"; 5729 } else { 5730 push @params, "COMMENT:" 5731 .decolon(langmsg(6901,"Average values").":\\l") 5732 if(!$interfaces{$interface}{noi} 5733 and !$interfaces{$interface}{noo} 5734 and !$interfaces{$interface}{nodesc} 5735 and !$interfaces{$interface}{nodetails}); 5736 } 5737 $c = ""; 5738 if(!$interfaces{$interface}{noi} and $incnt) { 5739 $c = shift @clr; push @clr, $c; 5740 push @params, "LINE$linewidth:avgin$c$lin"; 5741 } 5742 if(!$interfaces{$interface}{noo} and $outcnt) { 5743 $c = "" if( $c and !$mirroring ); 5744 if(!$c) { $c = shift @clr; push @clr, $c;} 5745 if($mirroring) { 5746 push @params, "CDEF:mavgout=avgout,-1,*"; 5747 push @params, "LINE$linewidth:mavgout$c$lout"; 5748 } else { 5749 push @params, "LINE$linewidth:xavgout$c$lout"; 5750 } 5751 } 5752 if( $dwmy !~ /s/ ) { 5753 if(!$interfaces{$interface}{nolegend} ) { 5754 push @params, 5755 "GPRINT:avgin:MAX:$gmaxlbl $sin\\g", 5756 "GPRINT:avgin:AVERAGE: $gavglbl $sin\\g", 5757 "GPRINT:avgin:LAST: $gcurlbl $sin\\l" 5758 if(!$interfaces{$interface}{noi} and $incnt); 5759 push @params, 5760 "GPRINT:avgout:MAX:$gmaxlbl $sout\\g", 5761 "GPRINT:avgout:AVERAGE: $gavglbl $sout\\g", 5762 "GPRINT:avgout:LAST: $gcurlbl $sout\\l" 5763 if(!$interfaces{$interface}{noo} and $outcnt); 5764 } 5765 } else { 5766 ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); 5767 $legendi = $interfaces{$interface}{legendi} 5768 if(defined $interfaces{$interface}{legendi}); 5769 $legendo = $interfaces{$interface}{legendo} 5770 if(defined $interfaces{$interface}{legendo}); 5771 $legendi =~ s/:/\\:/g; 5772 $legendo =~ s/:/\\:/g; 5773 push @params, 5774 "PRINT:avgin:MAX:".$q->b("$avglbl\\:")." $maxlbl $ssin, ", 5775 "PRINT:avgin:AVERAGE:$avglbl $ssin, ", 5776 "PRINT:avgin:LAST:$lastlbl $ssin ".$q->br 5777 if(!$interfaces{$interface}{noi} and $incnt); 5778 push @params, 5779 "PRINT:avgout:MAX:".$q->b("$avglbl\\:")." $maxlbl $ssout, ", 5780 "PRINT:avgout:AVERAGE:$avglbl $ssout, ", 5781 "PRINT:avgout:LAST:$lastlbl $ssout ".$q->br 5782 if(!$interfaces{$interface}{noo} and $outcnt); 5783 } # small graph 5784 } # with average line 5785 5786 # if there were no lines AT ALL, we need to add a dummy one else 5787 # RRDtool gets unhappy 5788 if(!$ifcnt or (!$incnt and !$outcnt)) { 5789 my($t) = $interfaces{$interface}{targets}[0]; 5790 $greydef = "x,x,-"; # this is 'positive' but zero to trigger next sec 5791 $defrrd = $interfaces{$t}{rrd}; 5792 $defrrd =~ s/:/\\:/g; 5793 if($daemonsuffix) { 5794 my($pth) = $config{'routers.cgi-dbpath'}; 5795 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 5796 $defrrd =~ s/$pth\/*//; 5797 } 5798 push @params, "DEF:x=$defrrd:ds0:AVERAGE".$daemonsuffix; 5799 $ifcnt = $incnt = $outcnt = 0; # just in case 5800# $debugmessage .= "Dummy target = $t\nDummy RRD = $defrrd\n"; 5801 } 5802 5803 # Greyout if no data at all. 5804 if($greydef) { 5805 $greydef = "CDEF:greyout=$greydef,$incnt,$outcnt,+,EQ,INF,0,IF"; 5806 push @params, $greydef, "AREA:greyout#d0d0d0"; 5807 if( !$interfaces{$interface}{unknasprev} 5808 and !$interfaces{$interface}{unknazero}) { 5809 $greydef = "CDEF:mgreyout=greyout,-1,*"; 5810 push @params, $greydef, "AREA:mgreyout#d0d0d0"; 5811 push @params, "HRULE:0#000000"; # redraw axis 5812 } 5813 } 5814 5815} # usr_params 5816 5817sub rtr_params(@) 5818{ 5819 my($ds0,$ds1,$ds2,$mds0,$mds1, $mds2)=("","","","","",""); 5820 my($lin, $lout, $mlin, $mlout, $lextra); 5821 my($dwmy,$interface) = @_; 5822 my($ssin, $ssout, $sin, $sout, $ssext, $sext); 5823 my($l,$defrrd); 5824 my($workday) = 0; 5825 my($legendi,$legendo, $legendx); 5826 my(@clr, $escunit); 5827 my($max1, $max2); 5828 my($havepeaks) = 0; 5829 my($graphstyle) = ""; 5830 my($maxlbl,$avglbl,$curlbl,$lastlbl) = ('Max','Avg','Cur','Last'); 5831 my($gmaxlbl,$gavglbl,$gcurlbl,$glastlbl); 5832 my($cf) = "AVERAGE"; 5833 my($daemonsuffix) = ""; 5834 5835 if($rrdcached) { 5836 $daemonsuffix = "daemon=$rrdcached"; 5837 $daemonsuffix =~ s/:/\\:/g; 5838 $daemonsuffix = ":$daemonsuffix"; 5839 } 5840 5841 $maxlbl = langmsg(2200,$maxlbl); $avglbl = langmsg(2201,$avglbl); 5842 $curlbl = langmsg(2202,$curlbl); $lastlbl = langmsg(2203,$lastlbl); 5843 $gmaxlbl = langmsg(6200,$maxlbl); $gavglbl = langmsg(6201,$avglbl); 5844 $gcurlbl = langmsg(6202,$curlbl); $glastlbl = langmsg(6203,$lastlbl); 5845 5846 $graphstyle = lc $interfaces{$interface}{graphstyle} 5847 if( $interfaces{$interface}{graphstyle} ); 5848 # are we going to add peak lines on this graph? 5849 if($graphstyle !~ /stack/ ) { 5850 if(!defined $config{'routers.cgi-withpeak'} 5851 or $config{'routers.cgi-withpeak'} =~ /y/i ) { 5852 if( $dwmy =~ /[wmy]/ or ( $dwmy =~ /d/ and $usesixhour )) { 5853 my($pat) = ''; 5854 if( defined $interfaces{$interface}{withpeak} ) { 5855 $pat = '[a'.$interfaces{$interface}{withpeak}.']'; 5856 $havepeaks = 1 if( $dwmy =~ /$pat/i ); 5857 } else { $havepeaks = 1; } 5858 } 5859 } 5860 } 5861 5862 # are we going to work out the 'working day' averages as well? 5863 if( defined $config{'routers.cgi-daystart'} 5864 and defined $config{'routers.cgi-dayend'} 5865 and $config{'routers.cgi-daystart'}<$config{'routers.cgi-dayend'} 5866 and $dwmy !~ /y/ ){ 5867 $workday = 1; 5868 } 5869 5870 # identify colours 5871 if( defined $interfaces{$interface}{colours} ) { 5872 @clr = @{$interfaces{$interface}{colours}}; 5873 } 5874 if(! @clr ) { 5875 if( $gstyle =~ /b/ ) { 5876 @clr = ("#888888", "#000000", "#cccccc","#444444", "#222222"); 5877 } else { 5878 @clr = ("#00cc00", "#0000ff","#006600", "#ff00ff", "#ff0000" ); 5879 } 5880 } 5881 5882 $defrrd = $interfaces{$interface}{rrd}; 5883 $defrrd =~ s/:/\\:/g; 5884 if($rrdcached and $rrdcached!~/^unix:/) { 5885 my($pth) = $config{'routers.cgi-dbpath'}; 5886 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 5887 $defrrd =~ s/^$pth\/*//; 5888 } 5889 5890 $debugmessage .= "RRD: $defrrd\n"; 5891 5892 $escunit = $interfaces{$interface}{unit}; 5893 $escunit =~ s/%/%%/g; 5894 $escunit =~ s/:/\\:/g; 5895 $escunit =~ s/ / /g; 5896 5897 ($sin,$sout,$sext,$ssin,$ssout,$ssext) = sinout($interface,0); 5898 5899 if ( $dwmy =~ /s/ ) { 5900 $lin=""; $lout=""; $lextra=""; 5901 $mlin=""; $mlout=""; 5902 } else { 5903 $lin = langmsg(6405,"Inbound"); $lout = langmsg(6406,"Outbound"); 5904 $mlin = langmsg(6407,"Peak Inbound"); 5905 $mlout = langmsg(6408,"Peak Outbound"); 5906 $lin = $interfaces{$interface}{legend1} 5907 if( defined $interfaces{$interface}{legend1} ); 5908 $lout = $interfaces{$interface}{legend2} 5909 if( defined $interfaces{$interface}{legend2} ); 5910 $mlin = $interfaces{$interface}{legend3} 5911 if( defined $interfaces{$interface}{legend3} ); 5912 $mlout = $interfaces{$interface}{legend4} 5913 if( defined $interfaces{$interface}{legend4} ); 5914 if($interfaces{$interface}{noo} or $havepeaks 5915 or ( $graphstyle =~ /range/i )) { 5916 $lin .= "\\l"; 5917 } 5918 $lextra = "Other\\l"; 5919 $lextra = $interfaces{$interface}{legend5}."\\l" 5920 if( defined $interfaces{$interface}{legend5} ); 5921 $lin =~ s/:/\\:/g; $mlin =~ s/:/\\:/g; 5922 $lout =~ s/:/\\:/g; $mlout =~ s/:/\\:/g; 5923 $lin = ':'.$lin; $lout = ':'.$lout; 5924 $mlin = ':'.$mlin; $mlout = ':'.$mlout; 5925 $lextra = ':'.$lextra; 5926 } 5927 $lout .= "\\l" if($lout); 5928 $lin = substr( $lin." ",0,30 ) 5929 if($lin and !$interfaces{$interface}{noo} 5930 and $lin !~ /\\l$/ ); 5931 $mlout = substr( $mlout." ",0,30 ) 5932 if ($mlout); 5933 $mlin = substr( $mlin." ",0,30 ) 5934 if ($mlin); 5935 5936 if( $interfaces{$interface}{nolegend} ) { $mlin = $lin = $mlout = $lout = ""; } 5937 5938 ($ds0, $ds1) = ("ds0", "ds1"); 5939 if( $interfaces{$interface}{mode} eq "SERVER" ) { 5940 ($ds0, $ds1, $ds2) = ("user", "system", "wait") if($interface eq "CPU"); 5941 ($ds0, $ds1) = ("page", "page") if($interface eq "Page"); 5942 ($ds0, $ds1) = ("usercount", "usercount") if($interface eq "Users"); 5943 } 5944 push @params, 5945 "DEF:in=".$defrrd.":$ds0:" 5946 .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") 5947 .$daemonsuffix, 5948 "DEF:out=".$defrrd.":$ds1:" 5949 .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") 5950 .$daemonsuffix; 5951 push @params, 5952 "DEF:extra=".$defrrd.":$ds2:" 5953 .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") 5954 .$daemonsuffix 5955 if($ds2); 5956 ($ds0, $ds1) = ("in", "out"); 5957 $ds2 = "extra" if($ds2); 5958# Try to get around the race condition... This also hides the first UNK point 5959# if($RRDs::VERSION >= 1.00039 ) { 5960# push @params, 5961# "CDEF:racein=$ds0,UN,PREV($ds0),$ds0,IF", 5962# "CDEF:raceout=$ds1,UN,PREV($ds1),$ds1,IF"; 5963# ($ds0, $ds1) = ("racein", "raceout"); 5964# } 5965# Now for unknasprev 5966 if( $interfaces{$interface}{unknasprev} ) { 5967 if($RRDs::VERSION >= 1.00039 ) { 5968 push @params, 5969 "CDEF:unpin=$ds0,UN,PREV,$ds0,IF", 5970 "CDEF:unpout=$ds1,UN,PREV,$ds1,IF"; 5971 ($ds0, $ds1) = ("unpin", "unpout"); 5972 } 5973 } elsif( $interfaces{$interface}{unknaszero} ) { 5974# Now for unknaszero 5975 push @params, 5976 "CDEF:unin=$ds0,UN,0,$ds0,IF", 5977 "CDEF:unout=$ds1,UN,0,$ds1,IF"; 5978 ($ds0, $ds1) = ("unin", "unout"); 5979 } else { 5980 if($RRDs::VERSION >= 1.00039 ) { 5981 my($step) = $routers{$router}{interval}; 5982 if($step) { $step *= 60; } else { $step = 300; } 5983 push @params, 5984 "CDEF:unxin=NOW,TIME,-,$step,LT,$ds0,UN,+,2,EQ,PREV,$ds0,IF", 5985 "CDEF:unxout=NOW,TIME,-,$step,LT,$ds1,UN,+,2,EQ,PREV,$ds1,IF"; 5986 ($ds0, $ds1) = ("unxin", "unxout"); 5987 } 5988 } 5989 if( $interfaces{$interface}{c2fi} ) { 5990 push @params, "CDEF:c2fin=$ds0,1.8,*,32,+"; 5991 $ds0 = "c2fin"; 5992 } 5993 if( $interfaces{$interface}{c2fo} ) { 5994 push @params, "CDEF:c2fout=$ds1,1.8,*,32,+"; 5995 $ds1 = "c2fout"; 5996 } 5997### do this if we are using BITS 5998 if( $interfaces{$interface}{mult} and ($interfaces{$interface}{mult}!=1) ) { 5999 push @params, "CDEF:fin=$ds0,".$interfaces{$interface}{mult}.",*", 6000 "CDEF:fout=$ds1,".$interfaces{$interface}{mult}.",*"; 6001 ($ds0, $ds1) = ("fin", "fout"); 6002 } 6003### 6004 if( defined $interfaces{$interface}{factor} and $interfaces{$interface}{factor}!=1 ) { 6005 push @params, "CDEF:ffin=$ds0,".$interfaces{$interface}{factor}.",*", 6006 "CDEF:ffout=$ds1,".$interfaces{$interface}{factor}.",*"; 6007 ($ds0, $ds1) = ("ffin", "ffout"); 6008 } 6009# now for the peaks stuff 6010 ($mds0, $mds1) = ("ds0", "ds1"); 6011 if( $interfaces{$interface}{mode} eq "SERVER" ) { 6012 ($mds0,$mds1,$mds2) = ("user","system","wait") if($interface eq "CPU"); 6013 ($mds0,$mds1) = ("page", "page") if($interface eq "Page"); 6014 ($mds0,$mds1) = ("usercount", "usercount") if($interface eq "Users"); 6015 } 6016 push @params, 6017 "DEF:min=".$defrrd.":$mds0:MAX".$daemonsuffix 6018 .(($RRDs::VERSION >= 1.4)?":reduce=MAX":""), 6019 "DEF:mout=".$defrrd.":$mds1:MAX".$daemonsuffix 6020 .(($RRDs::VERSION >= 1.4)?":reduce=MAX":""); 6021 ($mds0, $mds1) = ("min", "mout"); 6022 if( $interfaces{$interface}{mode} eq "SERVER" and $mds2 ) { 6023 push @params, "DEF:mx=".$defrrd.":$mds2:MAX".$daemonsuffix 6024 .(($RRDs::VERSION >= 1.4)?":reduce=MAX":""); 6025 $mds2 = "mx"; 6026 } 6027### Do this if we are using BITS 6028 if( $interfaces{$interface}{mult} and ($interfaces{$interface}{mult}!=1)) { 6029 push @params, "CDEF:fmin=$mds0,".$interfaces{$interface}{mult}.",*", 6030 "CDEF:fmout=$mds1,".$interfaces{$interface}{mult}.",*"; 6031 ($mds0, $mds1) = ("fmin", "fmout"); 6032 } 6033### 6034 if( defined $interfaces{$interface}{factor} and $interfaces{$interface}{factor}!=1 ) { 6035 push @params, "CDEF:ffmin=$mds0,".$interfaces{$interface}{factor}.",*", 6036 "CDEF:ffmout=$mds1,".$interfaces{$interface}{factor}.",*"; 6037 ($mds0, $mds1) = ("ffmin", "ffmout"); 6038 } 6039 if( $interfaces{$interface}{c2fi} ) { 6040 push @params, "CDEF:mc2fin=$mds0,1.8,*,32,+"; 6041 $mds0 = "mc2fin"; 6042 } 6043 if( $interfaces{$interface}{c2fo} ) { 6044 push @params, "CDEF:mc2fout=$mds1,1.8,*,32,+"; 6045 $mds1 = "mc2fout"; 6046 } 6047 6048# Do the maxima 6049 $max1 = $max2 = $interfaces{$interface}{max}; 6050 $max1 = $interfaces{$interface}{max1} 6051 if(defined $interfaces{$interface}{max1}); 6052 $max2 = $interfaces{$interface}{max2} 6053 if(defined $interfaces{$interface}{max2}); 6054# Reverse calculations 6055 if($interfaces{$interface}{'reverse'}) { 6056 push @params, 6057 "CDEF:rin=$max1,$ds0,-", 6058 "CDEF:mrin=$max1,$mds0,-", 6059 "CDEF:rout=$max2,$ds1,-", 6060 "CDEF:mrout=$max2,$mds1,-"; 6061 ($ds0, $ds1) = ("rin", "rout"); 6062 ($mds0, $mds1) = ("mrin", "mrout"); 6063 } 6064# And the percentages 6065 if($interfaces{$interface}{aspercent}) { 6066 push @params, 6067 "CDEF:pcin=$ds0,100,*,$max1,/", 6068 "CDEF:mpcin=$mds0,100,*,$max1,/", 6069 "CDEF:pcout=$ds1,100,*,$max2,/", 6070 "CDEF:mpcout=$mds1,100,*,$max2,/"; 6071 ($mds0, $mds1) = ("mpcin", "mpcout"); 6072 ($ds0, $ds1) = ("pcin", "pcout"); 6073 } elsif($interfaces{$interface}{dorelpercent}) { 6074 # what if ds1=0? No way to avoid potential /0 6075 push @params, 6076 "CDEF:pcin=$ds0,100,*,$ds1,/", 6077 "CDEF:mpcin=$mds0,100,*,$mds1,/"; 6078 $mds0 = "mpcin"; # note we don't care about OUT as this implies NOO 6079 $ds0 = "pcin"; 6080 } else { 6081 if( $max1 && $dwmy !~ /s/ ) { 6082 push @params, 6083 "CDEF:pcin=$ds0,100,*,$max1,/", 6084 "CDEF:mpcin=$mds0,100,*,$max1,/"; 6085 } 6086 if( $max2 && $dwmy !~ /s/ ) { 6087 push @params, 6088 "CDEF:pcout=$ds1,100,*,$max2,/", 6089 "CDEF:mpcout=$mds1,100,*,$max2,/"; 6090 } 6091 } 6092 6093# Now the workday averages, if required 6094 if( $workday ) { 6095 # note we must have a DS in there even if it is not used 6096 push @params, "CDEF:wdtest=$ds0,POP," 6097 ."TIME,3600,/,$timezone,+,DUP,24,/,7,%,DUP,4,LT,EXC,2,GE,+,2,LT," 6098 ."EXC,24,%,DUP," 6099 .trim($config{'routers.cgi-daystart'}).",GE,EXC," 6100 .trim($config{'routers.cgi-dayend'}).",LT,+,2,EQ,1," 6101 ."0,IF,0,IF"; # Set to 1 if in working day 6102 push @params, "CDEF:wdin=wdtest,$ds0,UNKN,IF", 6103 "CDEF:wdout=wdtest,$ds1,UNKN,IF"; 6104 push @params, "CDEF:wdx=wdtest,$ds2,UNKN,IF" if($ds2); 6105 # mark the working day background, if not in b&w mode 6106 if( $gstyle !~ /b/ ) { 6107 push @params, "CDEF:wd=wdtest,INF,0,IF", "AREA:wd#ffffcc"; 6108# if($graphstyle=~/mirror/) { 6109 push @params, "CDEF:mwd=wd,-1,*", "AREA:mwd#ffffcc"; 6110# } 6111 } 6112 } 6113 6114 if( $interfaces{$interface}{available} ) { 6115 # availability percentage 6116 push @params, "CDEF:apc=in,UN,out,UN,+,2,EQ,0,100,IF"; 6117 # Now, the average of apc is the percentage availability! 6118 } 6119 6120 # For the scaleshift 6121 if( defined $interfaces{$interface}{scaleshift} 6122 and ($RRDs::VERSION >= 1.3) ) { 6123 push @params, 6124 "CDEF:x$ds1=$ds1," 6125 .$interfaces{$interface}{shift}.",-," 6126 .$interfaces{$interface}{scale}.",/", 6127 "CDEF:x$mds1=$mds1," 6128 .$interfaces{$interface}{shift}.",-," 6129 .$interfaces{$interface}{scale}.",/"; 6130 } else { 6131 push @params, "CDEF:x$ds1=$ds1", "CDEF:x$mds1=$mds1"; 6132 } 6133 6134 if( $interfaces{$interface}{mode} eq "SERVER" and $ds2 ) { 6135 push @params, "AREA:$ds0".$clr[0].$lin, 6136 "STACK:$ds1".$clr[1].$lout, 6137 "STACK:$ds2".$clr[4].$lextra; 6138 } else { 6139# now for the actual lines : put the peaklines for d only if we have a 6 hr 6140# dont forget to use more friendly colours if this is black and white mode 6141 push @params, "LINE$linewidth:$mds0".$clr[2].$mlin 6142 if($havepeaks and !$interfaces{$interface}{noi}); 6143 # outbound is done later... 6144 if(!$interfaces{$interface}{noi}) { 6145 if( $graphstyle =~ /lines/i ) { 6146 push @params, "LINE$linewidth:$ds0".$clr[0].$lin; 6147 } else { 6148 push @params, "AREA:$ds0".$clr[0].$lin; 6149 } 6150 } 6151 if(!$interfaces{$interface}{noo}) { 6152 if( $graphstyle =~ /stack/i ) { 6153 push @params, "STACK:$ds1".$clr[1].$lout; 6154 } elsif( $graphstyle =~ /range/i ) { 6155 push @params, "AREA:$ds1#ffffff"; # erase lower part 6156 # if workingday active, put HIGHLIGHTED lower in 6157 if( $workday and $gstyle !~ /b/) { 6158 push @params, "CDEF:lwday=wdin,UN,0,$ds1,IF", 6159 "AREA:lwday#ffffcc"; 6160 } 6161 push @params, "LINE$linewidth:$ds1".$clr[0]; # replace last pixel 6162 } elsif( $graphstyle =~ /mirror/i ) { 6163 if($havepeaks) { 6164 push @params, "CDEF:mmirror=$mds1,-1,*"; 6165 push @params, "LINE$linewidth:mmirror".$clr[3].$mlout; 6166 } 6167 push @params, "CDEF:mirror=$ds1,-1,*"; 6168 push @params, "AREA:mirror".$clr[1].$lout; 6169 } else { 6170 # we do it here so it isnt overwritten by the incoming area 6171 if($havepeaks) { 6172 push @params, "LINE$linewidth:x$mds1".$clr[3].$mlout; 6173 } # with peaks 6174 push @params, "LINE$linewidth:x$ds1".$clr[1].$lout; 6175 } 6176 } 6177 } # server mode 6178 6179# data unavailable 6180 if(!$interfaces{$interface}{unknaszero} 6181 and !$interfaces{$interface}{unknasprev}) { 6182 push @params, 6183 "CDEF:down=in,UN,out,UN,+,2,EQ,INF,0,IF","AREA:down#d0d0d0"; 6184# if($graphstyle=~/mirror/i) { 6185 push @params, "CDEF:mdown=down,-1,*","AREA:mdown#d0d0d0"; 6186 push @params, "HRULE:0#000000"; 6187# } 6188 } 6189# thresholds 6190 if( $dwmy !~ /s/ and !$interfaces{$interface}{nothresholds} ) { 6191 my($tdone) = 0; my( $tlab ) = ""; 6192 my($tlabbit); 6193 foreach ( qw/i o/ ) { 6194 $tlabbit = ""; 6195 if(defined $interfaces{$interface}{"threshmin$_"}) { 6196 $tlabbit = doformat($interfaces{$interface}{"threshmin$_"}, 6197 $interfaces{$interface}{fixunits},0) 6198 .$interfaces{$interface}{unit}; 6199 } 6200 if(defined $interfaces{$interface}{"threshmax$_"}) { 6201 $tlabbit .= ", " if($tlabbit); 6202 $tlabbit .= doformat($interfaces{$interface}{"threshmax$_"}, 6203 $interfaces{$interface}{fixunits},0) 6204 .$interfaces{$interface}{unit}; 6205 } 6206 if($tlabbit) { 6207 $tlab .= " (".$interfaces{$interface}{"legend$_"}." ".$tlabbit.")"; 6208 } 6209 } 6210 $tlab =~ s/:/\\:/g; 6211 foreach my $thresh ( qw/maxi maxo mini mino/ ) { 6212 if(defined $interfaces{$interface}{"thresh$thresh"} ) { 6213 my($tval) = $interfaces{$interface}{"thresh$thresh"}; 6214 if( $graphstyle =~ /mirror/ and $thresh =~ /o$/ ) { 6215 $tval = -$tval; 6216 } 6217 if($tdone) { 6218 push @params, "HRULE:".$tval."#ffa0a0"; 6219 } else { 6220 push @params, "HRULE:".$tval."#ffa0a0:" 6221 .langmsg(6105,"Thresholds")."$tlab\\l"; 6222 $tdone = 1; 6223 } 6224 } 6225 } # foreach 6226 } # dwmy != s 6227# the max line 6228 if($interfaces{$interface}{aspercent} 6229 or $interfaces{$interface}{dorelpercent}) { 6230 $interfaces{$interface}{max} = 100; 6231 $interfaces{$interface}{max1} = 100; 6232 $interfaces{$interface}{max2} = 100; 6233 } 6234 if( $interfaces{$interface}{max} 6235 and ! ( defined $config{'routers.cgi-maxima'} 6236 and $config{'routers.cgi-maxima'} =~ /n/i ) 6237 and !$interfaces{$interface}{nomax} 6238 ) { 6239 my( $lmax ) = ""; 6240 my( $lamax ) = ""; 6241 my( $lcol ) = "#ff0000"; 6242 $lcol = "#cccccc" if( $gstyle =~ /b/ ); 6243 if( $dwmy !~ /s/ ) { 6244 if( defined $interfaces{$interface}{mblegend} ) { 6245 $lmax = $interfaces{$interface}{mblegend}; 6246 $lmax =~ s/:/\\:/g; $lmax = ':'.$lmax; 6247 } elsif( $interfaces{$interface}{isif} ) { 6248 $lmax =":100% ".langmsg(6103,"Bandwidth"); 6249 } else { $lmax =":".langmsg(6102,"Maximum"); } 6250 if( $max1 and $max2 and ($max1 != $max2) ) { 6251 $lmax .= " (".doformat($max1,$interfaces{$interface}{fixunits},0) 6252 .$interfaces{$interface}{unit}."," 6253 .doformat($max2,$interfaces{$interface}{fixunits},0) 6254 .$interfaces{$interface}{unit}.")\\l"; 6255 } else { 6256 $lmax .= " (".doformat($interfaces{$interface}{max}, 6257 $interfaces{$interface}{fixunits},0) 6258 .$interfaces{$interface}{unit}.")\\l"; 6259 } 6260 if( defined $interfaces{$interface}{absmax} ) { 6261 if( defined $interfaces{$interface}{amlegend} ) { 6262 $lamax = ":".$interfaces{$interface}{amlegend}; 6263 } else { $lamax =":".langmsg(6104,"Hard Maximum"); } 6264 $lamax .= " (".doformat($interfaces{$interface}{absmax}, 6265 $interfaces{$interface}{fixunits},1) 6266 .$interfaces{$interface}{unit}.")\\l"; 6267 } 6268 if($interfaces{$interface}{aspercent} 6269 or $interfaces{$interface}{aspercent}) { $lmax=""; } 6270 } 6271 if( $graphstyle =~ /mirror/ ) { 6272 $max1 = $interfaces{$interface}{max} if(!$max1); 6273 $max2 = -$interfaces{$interface}{max} if(!$max2); 6274 $max2 = -$max2 if($max2>0); # put it below the axis! 6275 } 6276 if( $max1 and $max2 and ($max1 != $max2)) { 6277 push @params, "HRULE:".$max1.$lcol.$lmax; 6278 push @params, "HRULE:".$max2.$lcol; 6279 } else { 6280 push @params, "HRULE:".$interfaces{$interface}{max}.$lcol.$lmax; 6281 } 6282 if( defined $interfaces{$interface}{absmax} 6283 and !$interfaces{$interface}{noabsmax} ) { 6284 if( $gstyle =~ /b/ ) { 6285 push @params, "HRULE:".$interfaces{$interface}{absmax} 6286 ."#aaaaaa$lamax"; 6287 } else { 6288 push @params, "HRULE:".$interfaces{$interface}{absmax} 6289 ."#ff0080$lamax"; 6290 } 6291 if( $graphstyle =~ /mirror/ ) { 6292 if( $gstyle =~ /b/ ) { 6293 push @params, "HRULE:-".$interfaces{$interface}{absmax} 6294 ."#aaaaaa"; 6295 } else { 6296 push @params, "HRULE:-".$interfaces{$interface}{absmax} 6297 ."#ff0080"; 6298 } 6299 } 6300 } 6301 } 6302# now for the labels at the bottom 6303 if( $dwmy !~ /s/ 6304 and !$interfaces{$interface}{nodetails} 6305 and !$interfaces{$interface}{nolegend} 6306 ) { 6307 if( $max1 ) { 6308 if(!$interfaces{$interface}{noi}) { 6309 push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g" ; 6310 push @params ,"GPRINT:mpcin:MAX: (%2.0lf%%)\\g" 6311 if($interfaces{$interface}{percent}); 6312 push @params,"GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g" ; 6313 push @params ,"GPRINT:pcin:AVERAGE: (%2.0lf%%)\\g" 6314 if($interfaces{$interface}{percent}); 6315 push @params,"GPRINT:$ds0:LAST: $gcurlbl $sin\\g" ; 6316 push @params ,"GPRINT:pcin:LAST: (%2.0lf%%)\\g" 6317 if($interfaces{$interface}{percent}); 6318 push @params, "COMMENT:\\l" ; 6319 } 6320 if(!$interfaces{$interface}{noo}) { 6321 push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g" ; 6322 push @params ,"GPRINT:mpcout:MAX: (%2.0lf%%)\\g" 6323 if($interfaces{$interface}{percent}); 6324 push @params,"GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g" ; 6325 push @params ,"GPRINT:pcout:AVERAGE: (%2.0lf%%)\\g" 6326 if($interfaces{$interface}{percent}); 6327 push @params,"GPRINT:$ds1:LAST: $gcurlbl $sout\\g" ; 6328 push @params ,"GPRINT:pcout:LAST: (%2.0lf%%)\\g" 6329 if($interfaces{$interface}{percent}); 6330 push @params, "COMMENT:\\l" ; 6331 } 6332 if($ds2) { 6333 push @params, "GPRINT:$mds2:MAX:$gmaxlbl $sext\\g" ; 6334 push @params,"GPRINT:$ds2:AVERAGE: $gavglbl $sext\\g" ; 6335 push @params,"GPRINT:$ds2:LAST: $gcurlbl $sext\\g" ; 6336 push @params, "COMMENT:\\l" ; 6337 } 6338 if($workday) { 6339 push @params, "COMMENT:".decolon(langmsg(6106,"Working day averages")."\\g"); 6340 push @params,"GPRINT:wdin:AVERAGE: $sin\\g" 6341 if(!$interfaces{$interface}{noi}); 6342 push @params,"GPRINT:wdout:AVERAGE: $sout\\g" 6343 if(!$interfaces{$interface}{noo}); 6344 push @params,"GPRINT:wdx:AVERAGE: $sext\\g" 6345 if($ds2); 6346 push @params, "COMMENT:\\l"; 6347 } 6348 if( defined $config{'routers.cgi-maxima'} 6349 and $config{'routers.cgi-maxima'} =~ /n/i 6350 and !$interfaces{$interface}{nomax} ) { 6351 my( $comment ); 6352 if(defined $interfaces{$interface}{mblegend}) { 6353 $comment = $interfaces{$interface}{mblegend}; 6354 $comment = "COMMENT:".decolon($comment); 6355 } elsif($interfaces{$interface}{isif}) { 6356 $comment = "COMMENT:100% ".decolon(langmsg(6103,"Bandwidth")); 6357 } else { 6358 $comment = "COMMENT:".decolon(langmsg(6102,"Maximum value")); 6359 } 6360 $comment .= decolon(" ".doformat($interfaces{$interface}{max}, 6361 $interfaces{$interface}{fixunits},0) 6362 .$escunit."\\l"); 6363 push @params, $comment; 6364 } 6365 } else { 6366 push @params, 6367 "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g", 6368 "GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g", 6369 "GPRINT:$ds0:LAST: $gcurlbl $sin\\l" 6370 if(!$interfaces{$interface}{noi}); 6371 push @params, 6372 "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g", 6373 "GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g", 6374 "GPRINT:$ds1:LAST: $gcurlbl $sout\\l" 6375 if(!$interfaces{$interface}{noo}); 6376 push @params, 6377 "GPRINT:$mds2:MAX:$gmaxlbl $sext\\g", 6378 "GPRINT:$ds2:AVERAGE: $gavglbl $sext\\g", 6379 "GPRINT:$ds2:LAST: $gcurlbl $sext\\l" 6380 if($ds2); 6381 if($workday) { 6382 push @params, "COMMENT:".decolon(langmsg(6106,"Working day averages")."\\g"); 6383 push @params,"GPRINT:wdin:AVERAGE: $sin\\g" 6384 if(!$interfaces{$interface}{noi}); 6385 push @params,"GPRINT:wdout:AVERAGE: $sout\\g" 6386 if(!$interfaces{$interface}{noo}); 6387 push @params,"GPRINT:wdx:AVERAGE: $sext\\g" 6388 if($ds2); 6389 push @params, "COMMENT:\\l"; 6390 } 6391 } 6392 if( $interfaces{$interface}{available} ) { 6393 push @params, "GPRINT:apc:AVERAGE:".langmsg(6107,"Data availability")."\\: %.2lf%%\\l"; 6394 } 6395 } else { 6396 ($legendi,$legendo,$legendx) 6397 = (langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); 6398 $legendi = $interfaces{$interface}{legendi} 6399 if(defined $interfaces{$interface}{legendi}); 6400 $legendo = $interfaces{$interface}{legendo} 6401 if(defined $interfaces{$interface}{legendo}); 6402 $legendx = $interfaces{$interface}{legendx} 6403 if(defined $interfaces{$interface}{legendx}); 6404 $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; $legendx=~s/:/\\:/g; 6405 $legendi =~ s/%/%%/g; $legendo =~ s/%/%%/g; $legendx=~s/%/%%/g; 6406 6407 push @params, 6408 "PRINT:$mds0:MAX:".$q->b($legendi)." $maxlbl $ssin, ", 6409 "PRINT:$ds0:AVERAGE:$avglbl $ssin, ", 6410 "PRINT:$ds0:LAST:$lastlbl $ssin ".$q->br 6411 if(!$interfaces{$interface}{noi}); 6412 push @params, 6413 "PRINT:$mds1:MAX:".$q->b($legendo)." $maxlbl $ssout, ", 6414 "PRINT:$ds1:AVERAGE:$avglbl $ssout, ", 6415 "PRINT:$ds1:LAST:$lastlbl $ssout ".$q->br 6416 if(!$interfaces{$interface}{noo}); 6417 push @params, 6418 "PRINT:$mds2:MAX:".$q->b($legendx)." $maxlbl $ssext, ", 6419 "PRINT:$ds2:AVERAGE:$avglbl $ssext, ", 6420 "PRINT:$ds2:LAST:$lastlbl $ssext ".$q->br 6421 if($legendx and $ds2); 6422 6423 if($workday) { 6424 my($pfx) = "<TR><TD>".langmsg(3201,"Working day average")."\\:</TD>"; 6425 my($sfx) = ""; 6426 if(!$interfaces{$interface}{noi}) { 6427 $sfx = "</TR>" if($interfaces{$interface}{noo}); 6428 push @params, 6429 "PRINT:wdin:AVERAGE:$pfx<TD align=right>$ssin" 6430 ."</TD>$sfx"; 6431 $pfx = ""; 6432 } 6433 push @params, 6434 "PRINT:wdout:AVERAGE:$pfx<TD align=right>$ssout" 6435 ."</TD>$sfx" 6436 if(!$interfaces{$interface}{noo}); 6437 push @params, 6438 "PRINT:wdx:AVERAGE:$pfx<TD align=right>$ssext" 6439 ."</TD>$sfx" 6440 if($ds2); 6441 } 6442 } 6443} 6444 6445sub jscript_actuals($$$$@) { 6446 my($interface,$dwmy,$starttime,$endtime,@p) = @_; 6447 my($idx) = 0; 6448 my($js) = ""; 6449 my( $start, $step, $names, $values, $e ); 6450 my($t,$i,$dp,$factor,$incr); 6451 my($rrd); 6452 my($max1,$max2); 6453 my($intf); 6454 6455 # if we're in a summary 6456 return if($dwmy =~/s/); 6457 # Here, we can add the javascript to define the actual arrays for the 6458 # popup, if necessary. 6459 $factor = 1; 6460 $factor *= $interfaces{$interface}{mult} if($interfaces{$interface}{mult}); 6461 $factor *= $interfaces{$interface}{factor} if($interfaces{$interface}{factor}); 6462 $dp = 2; $dp = 0 if($interfaces{$interface}{integer}); 6463 if($dwmy=~/d/) { $idx=1; } 6464 elsif($dwmy=~/w/) { $idx=2; } 6465 elsif($dwmy=~/m/) { $idx=3; } 6466 elsif($dwmy=~/y/) { $idx=4; } 6467 $rrd = $interfaces{$interface}{rrd}; 6468 if($rrdcached and $rrdcached!~/^unix:/) { 6469 my($pth) = $config{'routers.cgi-dbpath'}; 6470 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 6471 $rrd =~ s/^$pth\/*//; 6472 } 6473 if( $config{'web-debug'} ) { 6474 print "\n<!-- Extraction params: $rrd ".(join " ",@p)." -->\n"; 6475 } 6476 ( $start, $step, $names, $values ) = RRDs::fetch($rrd,"AVERAGE",@p,@rrdcached); 6477 $e = RRDs::error(); 6478 if($e) { 6479 print "<!-- Error fetching: $e -->\n"; 6480 return; 6481 } 6482 if( $config{'web-debug'} ) { 6483 print "<!-- Asked for: $starttime to $endtime, 400 values-->\n"; 6484 print "<!-- Asked for: ".longdate($starttime)." to ".longdate($endtime)." -->\n"; 6485 print "<!-- Retrieved: $start to ".($start+$step*$#$values).", ".$#$values." values -->\n"; 6486 print "<!-- Retrieved: ".longdate($start)." to ".longdate($start+$step*$#$values)." -->\n"; 6487# print "<!-- Step: asked for ".$p[5]." retrieved $step -->\n"; 6488 } 6489 6490 $js = "xactual[$idx]=1;\nactual[$idx]=new Array(400);\n"; 6491 $i = 0; $t = $start; 6492 $incr = ($endtime-$starttime)/400; 6493 $max1 = $max2 = $interfaces{$interface}{max}; 6494 $max1 = $interfaces{$interface}{max1} 6495 if(defined $interfaces{$interface}{max1}); 6496 $max2 = $interfaces{$interface}{max2} 6497 if(defined $interfaces{$interface}{max2}); 6498 $intf = 0; 6499 $intf = $interfaces{$interface}{integer} 6500 if(defined $interfaces{$interface}{integer}); 6501 foreach my $row ( @$values ) { 6502 $i = int(($t-$starttime)/$incr); 6503 if(!defined $row->[0]) { $js .= "actual[$idx][$i] = \"\"\n"; } 6504 else { 6505 $js .= "actual[$idx][$i] = \""; 6506 if($interfaces{$interface}{dorelpercent}) { 6507 $js .= doformat(($row->[0]/$row->[1]*100.0),1,$intf)."\%" 6508 if($row->[1]); 6509 } elsif($interfaces{$interface}{aspercent}) { 6510 $js .= doformat($row->[0]/$interfaces{$interface}{maxbytes}*100.0, 6511 1,$intf)."\%" unless($interfaces{$interface}{noi}); 6512 $js .= ",<BR>" unless($interfaces{$interface}{noi} 6513 or $interfaces{$interface}{noo}); 6514 $js .= doformat($row->[1]/$interfaces{$interface}{maxbytes}*100.0, 6515 1,$intf)."\%" unless($interfaces{$interface}{noo}); 6516 } elsif($interfaces{$interface}{'reverse'}) { 6517 $js .= doformat(($max1-$row->[0])*$factor, 6518 $interfaces{$interface}{fixunits},$intf) 6519 .$interfaces{$interface}{unit} 6520 unless($interfaces{$interface}{noi}); 6521 $js .= ",<BR>" unless($interfaces{$interface}{noi} 6522 or $interfaces{$interface}{noo}); 6523 $js .= doformat(($max2-$row->[1])*$factor, 6524 $interfaces{$interface}{fixunits},$intf) 6525 .$interfaces{$interface}{unit2} 6526 unless($interfaces{$interface}{noo}); 6527 } else { 6528 $js .= doformat(($interfaces{$interface}{c2fi}? 6529 (($row->[0]*$factor*1.8)+32):$row->[0]*$factor), 6530 $interfaces{$interface}{fixunits},$intf) 6531 .$interfaces{$interface}{unit} 6532 unless($interfaces{$interface}{noi}); 6533 $js .= ",<BR>" unless($interfaces{$interface}{noi} 6534 or $interfaces{$interface}{noo}); 6535 $js .= doformat(($interfaces{$interface}{c2fo}? 6536 (($row->[1]*$factor*1.8)+32):$row->[1]*$factor), 6537 $interfaces{$interface}{fixunits},$intf) 6538 .$interfaces{$interface}{unit2} 6539 unless($interfaces{$interface}{noo}); 6540 } 6541 $js .= "\";\n"; 6542 } 6543 $t += $step; 6544 } 6545 6546 # and output 6547 print "\n<SCRIPT type=\"text/javascript\">//<![CDATA[\n$js\n//]></SCRIPT>\n"; 6548} 6549######################################################################## 6550# Actually create the necessary graph, and output the IMG tag. 6551 6552sub make_graph(@) 6553{ 6554 my($e, $thisgraph, $thisurl, $s, $autoscale); 6555 my($tstr, $gheight, $width, $gwidth, $gtitle, $col); 6556 my($titlemaxlen); 6557 my($maxwidth) = 30; 6558 my($endtime, $starttime, @tparams, $interval, $end, $start); 6559 my($inhtml,$dwmy,$graphif) = @_; 6560 my($optsuffix) = ""; 6561 my(@ctgt) = (); 6562 my($js) = ""; 6563 6564 $debugmessage .= "Graph: $graphif\n"; 6565 6566# Verify that the rrd file exists 6567 if(!$rrdcached) { 6568 if( $interfaces{$graphif}{usergraph} ) { 6569 # several to check 6570 @ctgt = @{$interfaces{$graphif}{targets}}; 6571 } else { 6572 @ctgt = ( $graphif ); 6573 } 6574 foreach (@ctgt) { 6575 if(!-r $interfaces{$_}{rrd}) { 6576 if ( $pagetype =~ /image/ ) { 6577 if($opt_I) { 6578 print "Interface: $graphif($_)\nDevice: $router\nError: RRD does not exist\nRRD: ".$interfaces{$_}{rrd}."\n"; 6579 } else { 6580 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 6581 } 6582 } else { 6583 print $q->h1(langmsg(3003,"RRD database file not found"))."\n"; 6584 print "The file ".$interfaces{$_}{rrd} 6585 ." does not exist, or is unreadable. This file is created by MRTG when it first runs successfully on the " 6586 .$routers{$router}{file}." file.\n".$q->br 6587 ."Please check that you have collected data via MRTG and stored it into the RRD database without errors.".$q->br."\n"; 6588 } 6589 return; 6590 } 6591 } 6592 } # rrdcached 6593 6594# Shall we scale it, etc 6595 $autoscale = 1; 6596 $s = $dwmy; $s =~ s/[^dwmy6]//g; # get rid of excess stuff 6597 if( $interfaces{$graphif}{unscaled} ) { 6598 $autoscale = 0 if ($interfaces{$graphif}{unscaled} =~ /$s/i); 6599 } 6600 6601 $tstr = "6-hour" if( $dwmy =~ /6/ ) ; 6602 $tstr = "Daily" if( $dwmy =~ /d/ ) ; 6603 $tstr = "Weekly" if( $dwmy =~ /w/ ) ; 6604 $tstr = "Monthly" if( $dwmy =~ /m/ ) ; 6605 $tstr = "Yearly" if( $dwmy =~ /y/ ) ; 6606 6607 $gtitle = $interfaces{$graphif}{desc}; 6608 if( ($dwmy.$gstyle)=~/s/ ) { 6609 if($gstyle=~/y/) { $maxwidth = 60; } 6610 elsif($gstyle=~/x/) { $maxwidth = 50; } 6611 elsif($gstyle=~/l/) { $maxwidth = 40; } 6612 else { $maxwidth = 30; } 6613 } 6614 if(!$gtitle or ((length($gtitle)>$maxwidth)and(($dwmy.$gstyle) =~ /s/))) { 6615 $gtitle = ""; 6616 $gtitle .= $routers{$router}{shdesc}.": " 6617 if( defined $routers{$router}{shdesc}); 6618 $gtitle .= $interfaces{$graphif}{shdesc}; 6619 } 6620 $gtitle = $q->unescape($gtitle); 6621 $gtitle =~ s/ / /g; $gtitle =~ s/&/&/g; 6622 6623 @params = (); 6624 $optsuffix = "r1" if($uopts =~ /r/ ); 6625 $optsuffix = "r2" if($uopts =~ /R/ ); 6626 $optsuffix = "-$optsuffix" if($optsuffix); 6627 $thisgraph = "${router}-${graphif}-${dwmy}-${gstyle}${optsuffix}.${graphsuffix}"; 6628 $thisgraph = "${archdate}-${thisgraph}" if($archdate); 6629 $thisgraph = "${language}-${thisgraph}" if($language); 6630 $thisgraph =~ s/[\?#\/\\]//g; 6631 $thisurl = $config{'routers.cgi-graphurl'}."/".$q->escape($thisgraph); 6632 $thisgraph = $config{'routers.cgi-graphpath'}.$pathsep.$thisgraph; 6633 6634 # width is the data unit width (400 max). gwidth is the pixel width of 6635 # the actual graph. Thus, if gwidth > width, it is stretched. 6636 # Short: for PDAs, unstretched, shorter data window 6637 # Stretch: normal graph size, short data window (for easier viewing) 6638 # Long: normal data width, slightly bigger graph (for 800/600 screens) 6639 # Xlong: normal data width, double graph size (for 1024/768 screens) 6640 # v and w are thumbnail sizes, with half/quarter data width intended to 6641 # be used with the 'g' graph-only option. 6642 # gheight is the height of the graphic. 6643 # The 1st char is the width indicator s,t,n,l,x,y,v,w 6644 # then optional height indicator -,0,2,3 6645 # Then opional b (monochrome), g (graph only), p (no javascript) 6646 # Also D,H,Q for double/half/quarter data width ( t == nH ) 6647 # A == w-g, B == v0g (thumbnails) 6648 # Note that the graph TYPE (dwmy) can have a trailing s to indicate 6649 # summary, which will reduce the size and data width and suppress the 6650 # legend. 6651 if ( $gstyle =~ /^s/ ) { $width = 200; $gwidth = 200; } #short 6652 elsif ( $gstyle =~ /^t/ ) { $width = 200; $gwidth = 400; } #stretch 6653 elsif ( $gstyle =~ /^l/ ) { $width = 400; $gwidth = 530; } #long 6654 elsif ( $gstyle =~ /^x/ ) { $width = 400; $gwidth = 800; } #xlong 6655 elsif ( $gstyle =~ /^y/ ) { $width = 400; $gwidth = 1000; } #supersize 6656 elsif ( $gstyle =~ /^[wA]/i ) { $width = 100; $gwidth = 50; } #thumbnail 6657 elsif ( $gstyle =~ /^[vB]/i ) { $width = 200; $gwidth = 100; } #thumbnail 6658 else { $width = 400; $gwidth = 400; } # default (normal) 6659 if ( $gstyle =~ /2/ ) { $gheight = 200; } # double height 6660 elsif ( $gstyle =~ /3/ ) { $gheight = 300; } # triple height 6661 elsif ( $gstyle =~ /[-A]/ ) { $gheight = 30; } # thumbnail 6662 elsif ( $gstyle =~ /[0B]/ ) { $gheight = 50; } # half height 6663 else { $gheight = 100; } # normal height 6664 if ( $gstyle =~ /D/ ) { $width *= 2; } # double data width, so n=tD 6665 elsif ( $gstyle =~ /H/ ) { $width /= 2; } # half data width, so t=nH 6666 elsif ( $gstyle =~ /Q/ ) { $width /= 2; } # quarter data width 6667 elsif ( $gstyle =~ /T/ ) { $width *= 3; } # triple data width 6668 # now, if $dwmy contains an s, this is a summary graph, and should be 6669 # half of the expected data width and half the expected screen width. 6670 # We also force the graph to be half height, or 100 (whichever is greater). 6671 # The magic 120 in the graph width is the width of the axis, as gwidth is 6672 # the width of the AXIS, not the width of the graphic. 6673 if ( $dwmy =~ /s/ ) { 6674 my $ratio = 0.5; 6675 if( $interfaces{$interface}{nodetails} ) { $ratio = 0.5; } 6676 elsif($gwidth>800) { $ratio = 0.75; } # y 6677 elsif($gwidth>400) { $ratio = 0.65; } # x,l 6678 elsif($gwidth>200) { $ratio = 0.5; } # n,s 6679 $width *= $ratio; $gwidth = ($gwidth+120)*$ratio - 120; 6680 $gheight/=2; $gheight = 100 if($gheight<100); 6681 } 6682 6683 push @params,"--only-graph" if($gstyle=~/[gAB]/); 6684 push @params, $thisgraph; 6685 if( $graphsuffix eq "png" ) { 6686 push @params, '--imgformat',uc $graphsuffix; 6687 } 6688 if($interfaces{$graphif}{kilo}) { 6689 push @params,"--base", $interfaces{$graphif}{kilo}; 6690 } else { 6691 push @params,"--base", $k; 6692 } 6693 push @params,"--lazy" if($dwmy !~ /s/ and $RRDs::VERSION != 1.3 6694 and (!defined $config{'routers.cgi-lazy'} 6695 or $config{'routers.cgi-lazy'}=~/[y1]/i)); 6696 # only if we dont need PRINT, and avoid RRD v1.3.0 bug 6697 push @params, "--interlaced"; # -l 0 removed 6698 if($interfaces{$graphif}{fixunits} and $RRDs::VERSION >= 1.00030 ) { 6699 if($interfaces{$graphif}{exponent}) { 6700 push @params,"--units-exponent",$interfaces{$graphif}{exponent}; 6701 } else { 6702 push @params,"--units-exponent",0; 6703 } 6704 } 6705 6706 push @params,"--force-rules-legend" if($RRDs::VERSION >= 1.00047); 6707 push @params,"--slope-mode" if(($RRDs::VERSION >= 1.2 ) 6708 and defined $config{'routers.cgi-slope'} 6709 and ($config{'routers.cgi-slope'}=~/[y1]/i) ); 6710 6711 # time window: save these, we may need them again 6712 @tparams = (); 6713 $end = 'now'; $endtime = time; 6714# $debugmessage .= "Endtime = $endtime\n"; 6715 if($basetime) { 6716 $end = $endtime = $basetime; 6717 } elsif($uselastupdate > 1 and $archivetime) { 6718 $end = $endtime = $archivetime; 6719 } elsif($lastupdate and $uselastupdate) { 6720 $end = $endtime = $lastupdate; 6721 } elsif( $interval ) { 6722 # Cannot be done because interval not yet set! 6723 $end = $endtime = $interval*int($endtime/$interval); # boundary 6724 } elsif( $dwmy =~ /6/ ) { 6725 $end = $endtime = 60*int($endtime/60); # 1min boundary 6726 } else { 6727 $end = $endtime = 300*int($endtime/300); # 5min boundary 6728 } 6729# $debugmessage .= "Endtime = $endtime\n"; 6730 if( $dwmy =~ /-/ ) { 6731 if ( $dwmy =~ /6/ ) { 6732 push @tparams, "-e", "$end-6h"; $endtime -= (6*3600); } 6733 if ( $dwmy =~ /d/ ) { 6734 push @tparams, "-e", "$end-24h"; $endtime -= (24*3600); } 6735 if ( $dwmy =~ /w/ ) { 6736 push @tparams, "-e", "$end-7d"; $endtime -= (7*24*3600); } 6737 if ( $dwmy =~ /m/ ) { 6738 push @tparams, "-e", "$end-30d"; $endtime -= (30*24*3600); } 6739 if ( $dwmy =~ /y/ ) { 6740 push @tparams, "-e", "$end-365d"; $endtime -= (365*24*3600); } 6741 } else { 6742 push @tparams, "-e", $end; 6743 } 6744 if ( $dwmy =~ /6/ ) { 6745 $interval = 60; 6746 $starttime = $endtime - $interval*$width; 6747 push @tparams, "-s", "end".(-1 * $width)."m" ; 6748 } elsif ( $dwmy =~ /d/ ) { 6749 $interval = 300; 6750 $starttime = $endtime - $interval*$width; 6751 push @tparams, "-s", "end".(-5 * $width)."m" ; 6752 } elsif ( $dwmy =~ /w/ ) { 6753 $interval = 1800; 6754 $starttime = $endtime - 1500*$width; # dont use $interval 6755 push @tparams, "-s", "end".(-25 * $width)."m" ; # dont set to 30 6756 } elsif ( $dwmy =~ /m/ ) { 6757 $interval = 7200; 6758 $starttime = $endtime - $interval*$width; 6759 push @tparams, "-s", "end".(-2 * $width)."h" ; 6760 } elsif ( $dwmy =~ /y/ ) { 6761 $interval = 86400; 6762 $starttime = $endtime - $interval*$width; 6763 push @tparams, "-s", "end".(-1 * $width)."d" ; 6764 } 6765 6766 push @params, @tparams; 6767 6768 # only force the minimum upper-bound of graph if we have a max, 6769 # and we dont have maxima=n, and we dont have unscaled=n 6770 if( $uopts =~ /r/i ) { 6771 # force upper limit to be 2xMax(avgs) if r, and Max(avgs) if R 6772 my($ulim) = 0; 6773 my($llim) = 0; 6774 my($ai,$ao, $e, $start, $names, $data); 6775 my(@t) = ($graphif); 6776 my($thistarg, $thislim,$lookback); 6777 # multiple targets? 6778 @t = @{$interfaces{$graphif}{targets}} 6779 if($interfaces{$graphif}{usergraph}); 6780 # find out average value 6781 $e = int($lastupdate/$interval)*$interval; 6782 $lookback = 10; 6783 $lookback = 200 if($uopts =~ /r/); # look back further 6784 # this _should_ return only one line of values... 6785 foreach $thistarg ( @t ) { 6786 my($trrd) = $interfaces{$thistarg}{rrd}; 6787 if($rrdcached and $rrdcached!~/^unix:/) { 6788 my($pth) = $config{'routers.cgi-dbpath'}; 6789 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 6790 $trrd =~ s/^$pth\/*//; 6791 } 6792 ($start,$interval,$names,$data) = 6793 RRDs::fetch($trrd, "AVERAGE", 6794 "-r", $interval, "-s", "end-".($lookback*$interval), "-e", $e, 6795 @rrdcached); 6796 ($ai,$ao) = get_avg($data); 6797 if( defined $interfaces{$interface}{graphstyle} 6798 and $interfaces{$interface}{graphstyle} =~ /mirror/i ) { 6799 if(!$interfaces{$thistarg}{noo}) { 6800 if( $interfaces{$graphif}{withtotal} 6801 and $interfaces{$graphif}{usergraph} ) { 6802 $ulim += $ao; 6803 } else { 6804 $ulim = $ao if($ao > $ulim); 6805 } 6806 } 6807 if(!$interfaces{$thistarg}{noi}) { 6808 if( $interfaces{$graphif}{withtotal} 6809 and $interfaces{$graphif}{usergraph} ) { 6810 $llim += $ai; 6811 } else { 6812 $llim = $ai if($ai > $llim); 6813 } 6814 } 6815 } else { 6816 if($ao > $ai) { $thislim = $ao; } else { $thislim = $ai; } 6817 $thislim = $ao if($interfaces{$thistarg}{noi}); 6818 $thislim = $ai if($interfaces{$thistarg}{noo}); 6819 if( $interfaces{$graphif}{withtotal} 6820 and $interfaces{$graphif}{usergraph} ) { 6821 $ulim += $thislim; 6822 } else { 6823 $ulim = $thislim if($thislim > $ulim); 6824 } 6825 } 6826 } 6827 $ulim *= 1.1; # just give a little more space 6828 # now we need to multiply, if appropriate 6829 $ulim *= $interfaces{$graphif}{mult} 6830 if($interfaces{$graphif}{mult}); 6831 $ulim *= $interfaces{$graphif}{factor} 6832 if(defined $interfaces{$graphif}{factor}); 6833 $ulim = int(2.0 * $ulim + 0.5) if($uopts =~ /r/); 6834 push @params, '-r', '-u', $ulim if($ulim > 0); 6835 if( defined $interfaces{$interface}{graphstyle} 6836 and $interfaces{$interface}{graphstyle} =~ /mirror/i ) { 6837 $llim *= -1.1; # just give a little more space 6838 $llim *= $interfaces{$graphif}{mult} 6839 if($interfaces{$graphif}{mult}); 6840 $llim *= $interfaces{$graphif}{factor} 6841 if(defined $interfaces{$graphif}{factor}); 6842 $llim = int(2.0 * $llim + 0.5) if($uopts =~ /r/); 6843 push @params, '-l', $llim if($llim < 0); 6844 } 6845 } else { 6846 if($interfaces{$graphif}{upperlimit}) { 6847 push @params, '-u', $interfaces{$graphif}{upperlimit}; 6848 } elsif( ! $autoscale ) { 6849 if( $interfaces{$graphif}{max} and ( 6850 !defined $config{'routers.cgi-maxima'} 6851 or $config{'routers.cgi-maxima'} !~ /n/i 6852 ) ) { 6853 push @params, '-u', $interfaces{$graphif}{max} ; 6854 } else { 6855 push @params, '-u', 0.1; # For sanity 6856 } 6857 } else { 6858 push @params, '-u', 0.1; # For sanity 6859 } 6860 # could have added a "-r" there to enforce the upper limit rigidly 6861 push @params, '--rigid' if($interfaces{$graphif}{rigid}); 6862 if($interfaces{$graphif}{lowerlimit}) { 6863 push @params, '--lower-limit', $interfaces{$graphif}{lowerlimit}; 6864 } 6865 } 6866 push @params, "-w", $gwidth, "-h", $gheight; 6867 6868 push @params,'--alt-y-grid' 6869 if($RRDs::VERSION>=1.2 and defined $config{'routers.cgi-altygrid'} 6870 and $config{'routers.cgi-altygrid'}=~/[y1]/i); 6871 6872 push @params,"--x-grid","MINUTE:15:HOUR:1:HOUR:1:0:$dailylabel" 6873 if ( $dwmy =~ /6/ ); 6874 push @params,"--x-grid","HOUR:1:HOUR:24:HOUR:2:0:$dailylabel" 6875 if ( $dwmy =~ /d/ ); 6876 push @params,"--x-grid","HOUR:6:DAY:1:DAY:1:86400:%a" 6877 if ( $dwmy =~ /w/ ); 6878 push @params,"--x-grid","DAY:1:WEEK:1:WEEK:1:604800:Week" 6879 .(($NT and $RRDs::VERSION < 1.00039)?"_":" ").$monthlylabel 6880 if ( $dwmy =~ /m/ and $RRDs::VERSION >= 1.00029 ); 6881 $titlemaxlen = $config{'routers.cgi-maxtitle'}?$config{'routers.cgi-maxtitle'}:128; 6882 $gtitle = substr($gtitle,0,$titlemaxlen) if(length($gtitle)>$titlemaxlen); 6883 push @params,"--title", $gtitle; 6884 6885 if ( defined $interfaces{$graphif}{ylegend} ) { 6886 push @params, "--vertical-label", $interfaces{$graphif}{ylegend}; 6887# push @params, "-U", $interfaces{$graphif}{unit} 6888# if($interfaces{$graphif}{unit}); 6889 } else { 6890 push @params, "--vertical-label", $interfaces{$graphif}{unit}; 6891 } 6892 6893 # Horizontal rules 6894 if( defined $interfaces{$graphif}{hrule} and $dwmy!~/s/ ) { 6895 $col = 4; 6896 foreach ( @{$interfaces{$graphif}{hrule}} ) { 6897 push @params, "HRULE:".$_->{value}."#" 6898 .($_->{colour}?$_->{colour}:((sprintf "%x",$col) x 6)) 6899 .":".$_->{desc}." ( " 6900 .doformat($_->{value},$interfaces{$graphif}{fixunits},0) 6901 .$interfaces{$graphif}{unit} .")\\l"; 6902 $col += 1; 6903 } 6904 } 6905 6906 # Scale modes and secondary axis 6907 push @params, "--logarithmic", "--units=si" 6908 if($interfaces{$graphif}{logscale}); 6909 push @params, "--right-axis-label", $interfaces{$graphif}{ylegend2} 6910 if($interfaces{$graphif}{ylegend2} and ($RRDs::VERSION >= 1.3)); 6911 push @params, "--right-axis", 6912 $interfaces{$graphif}{scale}.':'.$interfaces{$graphif}{shift} 6913 if($interfaces{$graphif}{scaleshift} and ($RRDs::VERSION >= 1.3)); 6914 push @params, "-P" if(defined $config{'routers.cgi-pango'} 6915 and $config{'routers.cgi-pango'}=~/[y1]/i); 6916 6917 push @params, "--watermark", "Generated by routers2.cgi Version $VERSION" 6918 if($RRDs::VERSION>=1.3004 and $dwmy !~ /s/); 6919 6920 push @params, "HRULE:0#000000"; # redraw zero axis 6921 6922 if( $interfaces{$graphif}{usergraph} ) { 6923 usr_params($dwmy,$graphif); 6924 } else { 6925 rtr_params($dwmy,$graphif); 6926 } 6927 6928 if( defined $interfaces{$graphif}{comment} ) { 6929 foreach ( @{$interfaces{$graphif}{comment}} ) { 6930 push @params, "COMMENT:".decolon(expandvars($_))."\\l"; 6931 } 6932 } 6933 6934 if ( defined $config{'routers.cgi-withdate'} 6935 and $config{'routers.cgi-withdate'}=~/[1y]/ ) { 6936 push @params, "COMMENT:".decolon(shortdate($endtime))."\\r"; 6937 } 6938 6939 ( $rrdoutput, $rrdxsize, $rrdysize ) = RRDs::graph(@params); 6940 $e = RRDs::error(); 6941 if ( $pagetype =~ /image/ ) { 6942 if($e or ! -f $thisgraph) { 6943 if($opt_I) { 6944 print "Device: $router\nTarget: $graphif\n"; 6945 print "Error: $e\n"; 6946 } else { 6947 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 6948 } 6949 } else { 6950 # output the graphic directly from disk 6951 open GRAPH, "<$thisgraph"; 6952 binmode GRAPH; 6953 binmode STDOUT; 6954 print $q->header({ -type=>"image/$graphsuffix", -expires=>"now", 6955 '-Content-Disposition'=>"filename=\"image.$graphsuffix\"" }) 6956 if(!$opt_I); 6957 while( <GRAPH> ) { print; } 6958 close GRAPH; 6959 } 6960 return; 6961 } 6962 if ( $e ) { 6963 if( $inhtml ) { 6964 if($config{'web-paranoia'} 6965 and $config{'web-paranoia'}=~/[yY1]/) { 6966 print $q->p("RRD Error!"),"\n"; 6967 } else { 6968 print $q->p("RRD Error: $e"),"\n"; 6969 print $q->p("You can visit the configuration verification page " 6970 .$q->a({href=>("$meurlfull?page=verify&rtr=" 6971 .$q->escape($router)),target=>"_new"},"here.")); 6972 print $q->p("RRD: ".$interfaces{$graphif}{rrd}.$q->br. 6973 "Device: [$router] ".$routers{$router}{desc}.$q->br. 6974 "Interface: $graphif".$q->br. 6975 "Interfaces: ".(join ",",keys(%interfaces)) 6976 ); 6977 print "Params: ".(join " ",@params).$q->br; 6978 } 6979 } else { 6980 print "Error generating graph:\n$e\n"; 6981 } 6982 } elsif( ! -f $thisgraph ) { 6983 if( $inhtml ) { 6984 print $q->h2("Graph was not created!"); 6985 print $q->p("Probably, no data is available for the requested time period."); 6986 print $q->p("RRD: ".$interfaces{$graphif}{rrd}.$q->br. 6987 "Device: [$router] ".$routers{$router}{desc}.$q->br. 6988 "Interface: $graphif" 6989 ); 6990 } else { 6991 print "Error generating graph: Probably no data available for that time period.\n"; 6992 } 6993 } else { 6994 print "<!-- RRD: ".$interfaces{$graphif}{rrd}." -->\n" 6995 ."<!-- OrigRRD: ".$interfaces{$graphif}{origrrd}." -->\n" 6996 ."<!-- ArchiveDate: $archdate -->\n" 6997 if( $config{'web-debug'} ); 6998 if($inhtml) { 6999 my($element) = "igraph$dwmy"; 7000 my($tzoffset) = ($timezone*3600); # default to server's timezone 7001 if($interfaces{$graphif}{timezone}) { 7002 my($savetz) = $ENV{TZ}; 7003 $ENV{TZ}=$interfaces{$graphif}{timezone}; 7004 POSIX::tzset(); 7005 $tzoffset = (localtime(86400))[2]; # -0 7006 $tzoffset -= 24 if( (localtime(86400))[3] != 2 ); 7007 $tzoffset *= 3600; 7008 $ENV{TZ}=$savetz; 7009 POSIX::tzset(); 7010 print "<!-- Timezone: ".$interfaces{$graphif}{timezone} 7011 ." = $tzoffset -->\n"; 7012 } 7013 # If we're able, get the actuals data 7014 # only if enabled, a simple graph, and not summary 7015 if(! $interfaces{$graphif}{usergraph} 7016 and ! $interfaces{$graphif}{issummary} 7017 and defined $config{'routers.cgi-actuals'} 7018 and $config{'routers.cgi-actuals'}=~/[y1]/i 7019 and (!defined $config{'routers.cgi-javascript'} 7020 or $config{'routers.cgi-javascript'}=~/[y1]/i) 7021 and $dwmy !~ /s/ 7022 ) { 7023 jscript_actuals($graphif,$dwmy,$starttime,$endtime, 7024 @tparams,'-r',$interval); 7025 } 7026 # Print out the actual image tag 7027 if($rrdxsize and $rrdysize and $rrdxsize < 10000 and $rrdysize < 10000 ) { 7028 print $q->img({src=>$thisurl,alt => $gtitle,border => 0, 7029 width => $rrdxsize, height => $rrdysize, name => $element, 7030 onMouseOver => "timepopup(this,'$element',$gwidth,$gheight,$interval,$endtime,$width,$tzoffset)", 7031 onMouseMove => "mousemove(event)", 7032 onMouseOut => "clearpopup()" }); 7033 } else { # avoid problems with RRD v1.3.0 7034 print $q->img({src=>$thisurl,alt => $gtitle,border => 0, 7035 name => $element, 7036 onMouseOver => "timepopup(this,'$element',$gwidth,$gheight,$interval,$endtime,$width,$tzoffset)", 7037 onMouseMove => "mousemove(event)", 7038 onMouseOut => "clearpopup()" }); 7039 } 7040 7041 } 7042 if( $archiveme ) { 7043 # copy this graph into the archive dir, 7044 # graphdir/file/target/ymdhm-siz.ext 7045 my( $arch ) = ""; 7046 my( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); 7047 $year += 2000 if($year < 100); 7048 $year += 1900 if($year < 1000); 7049 $arch = $router; $arch =~ s/[\?#\/\\]//g; 7050 $arch = $config{'routers.cgi-graphpath'}.$pathsep.$arch; 7051 mkdir $arch,0755 if(! -d $arch); 7052 $arch .= $pathsep.$graphif; 7053 mkdir $arch,0755 if(! -d $arch); 7054 $min = '0'.$min if($min < 10); 7055 $mday = '0'.$mday if($mday < 10); 7056 $mon += 1; $mon = '0'.$mon if($mon < 10); 7057 $arch .= $pathsep.$year.'-'.$mon.'-' 7058 .$mday.'-'.$hour.'-'.$min.'-'.$dwmy.'.'.$graphsuffix; 7059 print "<!-- Archiving $thisgraph\ninto $arch -->\n" 7060 if( $config{'web-debug'} ); 7061 if( open ARCH, '>'.$arch ) { 7062 binmode ARCH; 7063 if( open GRAPH, '<'.$thisgraph ) { 7064 binmode GRAPH; 7065 while ( <GRAPH> ) { print ARCH; } 7066 if($inhtml) { 7067 print $q->br.$q->b(langmsg(9001,"Archived OK")).$q->br."\n"; 7068 } else { print langmsg(9001,"Graph archive OK.")."\n"; } 7069 close GRAPH; 7070 } else { 7071 if($inhtml) { 7072 print $q->br.$q->b(langmsg(8001,"Archiving FAILED")." (cannot read?!)"); 7073 } else { print "Graph archive FAILED (cannot read?!).\n"; } 7074 } 7075 close ARCH; 7076 } else { 7077 if($inhtml) { 7078 print $q->br.$q->b(langmsg(8001,"Archiving FAILED")." (cannot write)"); 7079 } else { print "Graph archive FAILED (cannot write).\n"; } 7080 } 7081 } 7082 } 7083 if($js and $inhtml) { 7084 # Now, load the values into the array 7085 print "<script type=\"text/javascript\">//<![CDATA[\n" 7086 .$js."\n//]]></script>\n"; 7087 } 7088 if( $config{'web-debug'} ) { 7089 print "\n<!-- Start comment -->\n<!-- \nrrdtool graph "; 7090 print (join "\n ",@params); # For some browsers, this creates a 7091 # line too long and makes an error 7092 print "\n-->\n<!-- end comment -->\n"; 7093 } 7094} 7095 7096############### 7097# Calculations of average and max from fetched data 7098sub get_max($) 7099{ 7100 my($rows) = $_[0]; 7101 my($maxin, $maxout) = (0,0); 7102 7103 foreach ( @$rows ) { 7104 $maxin = $$_[0] if($$_[0]>$maxin); 7105 $maxout = $$_[1] if($$_[1]>$maxout); 7106 } 7107 return ($maxin, $maxout); 7108} 7109sub get_avg($) 7110{ 7111 my($rows) = $_[0]; 7112 my($avgin, $avgout) = (0,0); 7113 my($numrows) = $#$rows; 7114 7115 return (0,0) if($numrows < 1); 7116 foreach ( @$rows ) { 7117 $avgin += $$_[0]; 7118 $avgout += $$_[1]; 7119 } 7120 $avgin /= ($numrows+1); 7121 $avgout /= ($numrows+1); 7122 7123 return ($avgin,$avgout); 7124} 7125####################################################### 7126# For the compact summary. This will call the bar function a lot! 7127# bar images are: $meurl?page=bar&IN=xx&OUT=yy for percentages xx yy 7128# images are 400x15 pixels 7129sub do_compact($) 7130{ 7131my ($csvmode) = $_[0]; 7132my ($javascript); 7133my ($curif); 7134my ($e, $interval, $resolution, $rrd, $seconds); 7135my ($curin, $curout, $avgin, $avgout, $maxin, $maxout ); 7136my ($curinpc, $curoutpc, $avginpc, $avgoutpc, $maxinpc, $maxoutpc ); 7137my ($perinpc, $peroutpc, $perin, $perout); 7138my ($start, $from, $step, $names, $values); 7139my ($c,$a,$m,$p,$io, $heading); 7140my ($d, $inarr, $outarr,$barlen); 7141my (@iforder); 7142my ($legendi,$legendo,$fix,$intf); 7143my ($unit) = ""; 7144my ($max1, $max2); 7145 7146if(!$csvmode) { 7147 $javascript = make_javascript({}); 7148 start_html_ss({ -expires => "+5s", -script => $javascript, 7149 -onload => "LoadMenu()", -class=>'compact' }); 7150 print "<DIV class=pagetop>"; 7151 print expandvars($config{'routers.cgi-pagetop'}),"\n" 7152 if( defined $config{'routers.cgi-pagetop'} ); 7153 print "</DIV>"; 7154} else { 7155 $comma = substr( $config{'web-comma'},0,1 ) 7156 if(defined $config{'web-comma'}); 7157 $comma = ',' if(!$comma); 7158 print "Target".$comma."Description".$comma."Type".$comma 7159 ."Metric 1".$comma."Metric 2\n"; 7160} 7161# 7162# Now for the RRD stuff 7163eval { require RRDs; }; 7164if( $@ ) { 7165 if($csvmode) { print "".langmsg(8999,"Error").$comma 7166 ."Cannot find RRDs.pm: $@\n"; 7167 return; 7168 } 7169 if($config{'web-paranoia'} 7170 and $config{'web-paranoia'}=~/[yY1]/) { 7171 print $q->h1(langmsg(8999,"Error"))."<CODE>Cannot find RRDs.pm</CODE>\n"; 7172 } else { 7173 print $q->h1(langmsg(8999,"Error"))."<CODE>Cannot find RRDs.pm in ".(join " ",@INC )."</CODE>\n"; 7174 print $q->p("You can visit the configuration verification page " 7175 .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), 7176 target=>"_new"},"here.")); 7177 } 7178 do_footer(); 7179 return; 7180} 7181 7182# First, the header to select which are visible: 7183($c,$a,$m,$p,$io) = ("","","","","i"); 7184$c = $1 if( $baropts =~ /(c)/i ); # this preserves the case 7185$a = $1 if( $baropts =~ /(a)/i ); 7186$m = $1 if( $baropts =~ /(m)/i ); 7187$p = $1 if( $baropts =~ /(p)/i ); 7188if( $baropts =~ /o/i ) { $io = "o"; } else { $io = "i"; } 7189if(!$csvmode) { 7190print "<DIV class=icons>"; 7191print "<TABLE width=100% border=0 cellspacing=0 cellpadding=0 class=compactmenu><TR>\n"; 7192print "<TD><SMALL>".langmsg(2302,"Last:")." " 7193 .$q->a({href=>"$meurlfull?".optionstring({bars=>"Ci".(lc "$a$m$p")})}, 7194 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", 7195 border=>0,height=>10,width=>10,alt=>"Sort by current incoming"}) 7196 ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Co".(lc "$a$m$p")})}, 7197 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", 7198 border=>0,height=>10,width=>10,alt=>"Sort by current outgoing"}) 7199 ); 7200if( $c ) { 7201 print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$m$p$io"})}, 7202 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", 7203 border=>0,height=>10,width=>10,alt=>"Remove current bar"}) 7204 ); 7205} else { 7206 print $q->a({href=>"$meurlfull?".optionstring({bars=>"c$a$m$p$io"})}, 7207 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", 7208 border=>0,height=>10,width=>10,alt=>"Add Current bar"}) 7209 ); 7210} 7211print "</SMALL></TD>\n"; 7212print "<TD><SMALL>".langmsg(2303,"Average:")." " 7213 .$q->a({href=>"$meurlfull?".optionstring({bars=>"Ai".(lc "$c$m$p")})}, 7214 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", 7215 border=>0,height=>10,width=>10,alt=>"Sort by average incoming"}) 7216 ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Ao".(lc "$c$m$p")})}, 7217 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", 7218 border=>0,height=>10,width=>10,alt=>"Sort by average outgoing"}) 7219 ); 7220if( $a ) { 7221 print $q->a({href=>"$meurlfull?".optionstring({bars=>"$c$m$p$io"})}, 7222 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", 7223 border=>0,height=>10,width=>10,alt=>"Remove Average bar"}) 7224 ); 7225} else { 7226 print $q->a({href=>"$meurlfull?".optionstring({bars=>"a$c$m$p$io"})}, 7227 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", 7228 border=>0,height=>10,width=>10,alt=>"Add Average bar"})); 7229} 7230print "</SMALL></TD>\n"; 7231print "<TD><SMALL>".langmsg(2304,"Maximum:")." " 7232 .$q->a({href=>"$meurlfull?".optionstring({bars=>"Mi".(lc "$c$a$p")})}, 7233 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", 7234 border=>0,height=>10,width=>10,alt=>"Sort by Maximum incoming"}) 7235 ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Mo".(lc "$c$a$p")})}, 7236 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", 7237 border=>0,height=>10,width=>10,alt=>"Sort by Maximum outgoing"}) 7238 ); 7239if( $m ) { 7240 print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$c$p$io"})}, 7241 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", 7242 border=>0,height=>10,width=>10,alt=>"Remove Maximum bar"})); 7243} else { 7244 print $q->a({href=>"$meurlfull?".optionstring({bars=>"m$a$c$p$io"})}, 7245 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", 7246 border=>0,height=>10,width=>10,alt=>"Add Maximum bar"})); 7247} 7248print "</SMALL></TD>\n"; 7249if( defined $config{'routers.cgi-percentile'} 7250 and $config{'routers.cgi-percentile'} =~ /y/i ) { 7251 print "<TD><SMALL>".langmsg(2305,"$PERCENT<SUP>th</SUP> Percentile:")." " 7252 .$q->a({href=>"$meurlfull?".optionstring({bars=>"Pi".(lc "$c$a$m")})}, 7253 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", 7254 border=>0,height=>10,width=>10,alt=>"Sort by Incoming ${PERCENT}th percentile"}) 7255 ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Po".(lc "$c$a$m")})}, 7256 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", 7257 border=>0,height=>10,width=>10,alt=>"Sort by Outgoing ${PERCENT}th percentile"}) 7258 ); 7259 if( $p ) { 7260 print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$m$c$io"})}, 7261 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", 7262 border=>0,height=>10,width=>10,alt=>"Remove ${PERCENT}th percentile bar"})); 7263 } else { 7264 print $q->a({href=>"$meurlfull?".optionstring({bars=>"p$a$m$c$io"})}, 7265 $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", 7266 border=>0,height=>10,width=>10,alt=>"Add ${PERCENT}th percentile bar"})); 7267 } 7268 print "</SMALL></TD>\n"; 7269} 7270print "</TR></TABLE></DIV>\n"; 7271} # end if csvmode 7272 7273# Now, we set up the necessary resolution variables to use in the fetch: 7274$resolution = 60; $interval = "6h"; $seconds = 6*3600; 7275$heading = langmsg(2310,"Six hourly calculations"); 7276if ( $gtype =~ /d/ ) { $resolution=300; $interval="24h"; $seconds=86400; 7277 $heading = langmsg(2311,"Daily calculations"); } 7278elsif ($gtype =~ /w/){ $resolution=1800; $interval="7d"; $seconds=7*86400; 7279 $heading = langmsg(2312,"Weekly calculations"); } 7280elsif ($gtype =~ /m/){ $resolution=7200; $interval="1month"; $seconds=30*86400; 7281 $heading = langmsg(2313,"Monthly calculations"); } 7282elsif ($gtype =~ /y/){ $resolution=86400; $interval="1y"; $seconds=365*86400; 7283 $heading = langmsg(2314,"Yearly calculations"); } 7284 7285if(!$csvmode) { 7286print $q->center($q->h2({class=>'compact'},$routers{$router}{desc}))."\n" 7287 if($routers{$router}{desc}); 7288print $q->h3({class=>'compact'},$heading); 7289} 7290 7291# we now process each interface with incompact=>1 in turn. 7292foreach $curif ( keys(%interfaces) ) { 7293 next if(!$curif); # avoid rogue records 7294 next if(!$interfaces{$curif}{incompact}); 7295 next if(!$interfaces{$curif}{max}); 7296 next if($interfaces{$curif}{nomax}); 7297 7298 $interfaces{$curif}{errors} = ""; 7299 7300 # now we fetch the necessary information from the RRD 7301 $curin = $maxin = $avgin = -1; # error 7302 $curout= $maxout= $avgout= -1; # error 7303 $from = "now"; $e = 0; 7304 $rrd = $interfaces{$curif}{rrd}; 7305 if($rrdcached and $rrdcached!~/^unix:/) { 7306 my($pth) = $config{'routers.cgi-dbpath'}; 7307 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 7308 $rrd =~ s/^$pth\/*//; 7309 } 7310 if($basetime) { 7311 $from = $basetime; 7312 } elsif( $gtype =~ /-/ ) { 7313 $from = "now-$interval"; 7314 } elsif($uselastupdate > 1 and $archivetime) { 7315 $from = $archivetime; 7316 } elsif($uselastupdate) { 7317 $from = RRDs::last($rrd,@rrdcached); 7318 $e = RRDs::error(); 7319 if($e) { 7320 $from = "now"; 7321 $interfaces{$curif}{errors}.= $q->br.$q->small(langmsg(8999,"Error").": $e")."\n"; 7322 } 7323 } else { 7324 $from = "now-5min"; 7325 } 7326 $max1 = $max2 = $interfaces{$curif}{max}; 7327 $max1 = $interfaces{$curif}{max1} if(defined $interfaces{$curif}{max1}); 7328 $max2 = $interfaces{$curif}{max2} if(defined $interfaces{$curif}{max2}); 7329 $lastupdate = $from; 7330 if( $c ) { 7331 ( $start, $step, $names, $values ) = 7332 RRDs::fetch($rrd,"AVERAGE","-s","$from-$resolution", 7333 "-e",$from,"-r",$resolution,@rrdcached); 7334 $e = RRDs::error(); 7335 if($e) { 7336 $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); 7337 } else { 7338 ( $curin, $curout ) = @{$values->[0]}; 7339 $curin *= $interfaces{$curif}{mult}; 7340 $curout *= $interfaces{$curif}{mult}; 7341 $curin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7342 $curout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7343 $curin = 0 if($interfaces{$curif}{noi}); 7344 $curout= 0 if($interfaces{$curif}{noo} and !$interfaces{$curif}{dorelpercent}); 7345 } 7346 if( $interfaces{$curif}{dorelpercent} ) { 7347 if(defined $curin and $curout) { 7348 $curinpc = 100.0 * $curin / $curout; 7349 $curin = $curinpc; 7350 } else { 7351 $curinpc = 0; $curin = -1; 7352 } 7353 $curoutpc = 0; 7354 $curout = -1; 7355 } else { 7356 if(defined $curin) { $curinpc = $curin*100.0/$max1; } 7357 else { $curin = -1; $curinpc = 0; } 7358 if(defined $curout) { $curoutpc = $curout*100.0/$max2; } 7359 else { $curout = -1; $curoutpc = 0; } 7360 } 7361 $interfaces{$curif}{barcurin} = $curin; 7362 $interfaces{$curif}{barcurinpc} = $curinpc; 7363 $interfaces{$curif}{barcurout} = $curout; 7364 $interfaces{$curif}{barcuroutpc} = $curoutpc; 7365 } # c 7366 if( $a ) { 7367 ( $start, $step, $names, $values ) = 7368 RRDs::fetch($rrd,"AVERAGE","-s","$from-$interval", 7369 "-e",$from,"-r",$seconds,@rrdcached); 7370 $e = RRDs::error(); 7371 if($e) { 7372 $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); 7373 } else { 7374 ($avgin, $avgout) = get_avg($values); 7375 $avgin *= $interfaces{$curif}{mult}; 7376 $avgout *= $interfaces{$curif}{mult}; 7377 $avgin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7378 $avgout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7379 $avgin = 0 if($interfaces{$curif}{noi}); 7380 $avgout= 0 if($interfaces{$curif}{noo} and !$interfaces{$curif}{dorelpercent}); 7381 } 7382 if( $interfaces{$curif}{dorelpercent} ) { 7383 if(defined $avgin and $avgout) { 7384 $avginpc = 100.0 * $avgin / $avgout; 7385 $avgin = $avginpc; 7386 } else { 7387 $avginpc = 0; $avgin = -1; 7388 } 7389 $avgoutpc = 0; 7390 $avgout = -1; 7391 } else { 7392 if(defined $avgin) { $avginpc = $avgin*100.0/$max1; } 7393 else { $avgin = -1; $avginpc = 0; } 7394 if(defined $avgout) { $avgoutpc = $avgout*100.0/$max2; } 7395 else { $avgout = -1; $avgoutpc = 0; } 7396 } 7397 $interfaces{$curif}{baravgin} = $avgin; 7398 $interfaces{$curif}{baravgout} = $avgout; 7399 $interfaces{$curif}{baravginpc} = $avginpc; 7400 $interfaces{$curif}{baravgoutpc} = $avgoutpc; 7401 } # a 7402 if( $m ) { 7403 ( $start, $step, $names, $values ) = 7404 RRDs::fetch($rrd,"MAX","-s","$from-$interval", 7405 "-e",$from,"-r",$seconds,@rrdcached); 7406 $e = RRDs::error(); 7407 if($e) { 7408 $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); 7409 } else { 7410 ($maxin, $maxout) = get_max($values); 7411 $maxin *= $interfaces{$curif}{mult}; 7412 $maxout *= $interfaces{$curif}{mult}; 7413 $maxin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7414 $maxout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); 7415 $maxin = 0 if($interfaces{$curif}{noi}); 7416 $maxout= 0 if($interfaces{$curif}{noo} and !$interfaces{$curif}{dorelpercent}); 7417 } 7418 if( $interfaces{$curif}{dorelpercent} ) { 7419 if(defined $maxin and $maxout) { 7420 $maxinpc = 100.0 * $maxin / $maxout; 7421 $maxin = $maxinpc; 7422 } else { 7423 $maxinpc = 0; $maxin = -1; 7424 } 7425 $maxoutpc = 0; 7426 $maxout = -1; 7427 } else { 7428 if(defined $maxin) { $maxinpc = $maxin*100.0/$max1; } 7429 else { $maxin = -1; $maxinpc = 0; } 7430 if(defined $maxout) { $maxoutpc = $maxout*100.0/$max2; } 7431 else { $maxout = -1; $maxoutpc = 0; } 7432 } 7433 $interfaces{$curif}{barmaxin} = $maxin; 7434 $interfaces{$curif}{barmaxout} = $maxout; 7435 $interfaces{$curif}{barmaxinpc} = $maxinpc; 7436 $interfaces{$curif}{barmaxoutpc} = $maxoutpc; 7437 } # m 7438 if( $p ) { 7439 ($d,$inarr,$outarr) = calc_percentile($curif,$gtype,$PERCENT); 7440 $perin = ${$inarr}[0]; 7441 $perout= ${$outarr}[0]; 7442 if( $interfaces{$curif}{dorelpercent} ) { 7443 if(defined $perin and $perout) { 7444 $perinpc = 100.0 * $perin / $perout; 7445 $perin = $perinpc; 7446 } else { 7447 $perinpc = 0; $perin = -1; 7448 } 7449 $peroutpc = 0; 7450 $perout = -1; 7451 } else { 7452 $perin = 0 if($interfaces{$curif}{noi}); 7453 $perout= 0 if($interfaces{$curif}{noo}); 7454 if(defined $perin) { $perinpc = $perin*100.0/$max1; } 7455 else { $perin = -1; $perinpc = -1; } 7456 if(defined $perout) { $peroutpc = $perout*100.0/$max2; } 7457 else { $perout = -1; $peroutpc = -1; } 7458 } 7459 $interfaces{$curif}{barperin} = $perin; 7460 $interfaces{$curif}{barperout} = $perout; 7461 $interfaces{$curif}{barperinpc} = $perinpc; 7462 $interfaces{$curif}{barperoutpc} = $peroutpc; 7463 if(!$d) { 7464 $interfaces{$curif}{errors} .= $q->br.$q->small($$inarr[2]) 7465 .$q->br.$q->small($$outarr[2]); 7466 } 7467 } # p 7468} # end of data collection 7469 7470# Work out the order of the interfaces 7471$traffic = ""; 7472if ( $c eq "C" ) { 7473 $traffic = "cur"; 7474} elsif( $a eq "A" ) { 7475 $traffic = "avg"; 7476} elsif( $m eq "M" ) { 7477 $traffic = "max"; 7478} elsif( $p eq "P" and defined $config{'routers.cgi-percentile'} 7479 and $config{'routers.cgi-percentile'} =~ /y/i ) { 7480 $traffic = "per"; 7481} 7482if($traffic) { 7483 $traffic .= 'in' if( $io eq "i" ); 7484 $traffic .= 'out' if( $io eq "o" ); 7485 $traffic = 'bar'.$traffic.'pc'; 7486 @iforder = sort bytraffic keys(%interfaces); 7487} else { 7488 @iforder = sort byifdesc keys(%interfaces); 7489} 7490 7491# we now print the bars. 7492$barlen = 400; # 800x600 7493$barlen = 600 if ( $gstyle =~ /x/i ); # 1024x768 7494$barlen = 280 if ( $gstyle =~ /[nts]/i ); # 640x480 and pda 7495print "<TABLE border=0 cellpadding=0 cellspacing=0 nowrap class=compact>\n" 7496 if(!$csvmode); 7497foreach $curif ( @iforder ) { 7498 next if(!$curif); # avoid rogue records 7499 next if(!$interfaces{$curif}{incompact}); 7500 7501 # the unit string, if any 7502 $unit = ""; 7503 $unit = $interfaces{$curif}{unit} 7504 if(!defined $config{'routers.cgi-legendunits'} 7505 or $config{'routers.cgi-legendunits'} =~ /y/i ); 7506 $fix = $interfaces{$curif}{fixunits}; 7507 $fix = 0 if(!defined $fix); 7508 $intf = $interfaces{$curif}{integer}; 7509 $intf = 0 if(!defined $intf); 7510 7511 # the legends 7512 ($legendi,$legendo)=(langmsg(2204,"IN"),langmsg(2205,"OUT")); 7513 $legendi = $interfaces{$curif}{legendi} if(defined $interfaces{$curif}{legendi}); 7514 $legendo = $interfaces{$curif}{legendo} if(defined $interfaces{$curif}{legendo}); 7515 $legendi = "" if($interfaces{$curif}{noi}); 7516 $legendo = "" if($interfaces{$curif}{noo}); 7517 7518 if(!$csvmode) { 7519 print "<TR class=compact><TD align=left colspan=2 width=$barlen class=compact>\n"; 7520 print $q->a({href=>"$meurlfull?".optionstring({if=>$curif})}, 7521 $q->small($interfaces{$curif}{desc} 7522 .(($interfaces{$curif}{desc} ne $interfaces{$curif}{shdesc})? 7523 (" (".$interfaces{$curif}{shdesc}.")"):"") 7524 ))."\n"; 7525 print $interfaces{$curif}{errors}; 7526 print "</TD><TD align=center valign=bottom><B><FONT color=#00d000><SMALL>$legendi</SMALL></FONT></B></TD><TD align=center valign=bottom><B><FONT color=#0000ff><SMALL>$legendo</SMALL></FONT></B></TD></TR>\n"; 7527 } # csvmode 7528 7529 # now print the bar graphs up 7530 if( $c ) { 7531 $curin = $interfaces{$curif}{barcurin}; 7532 $curout= $interfaces{$curif}{barcurout}; 7533 $curinpc = $interfaces{$curif}{barcurinpc}; 7534 $curoutpc= $interfaces{$curif}{barcuroutpc}; 7535 if($csvmode) { 7536 print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma 7537 .'"'.langmsg(2203,"Last").'"'.$comma 7538 .($legendi?doformat($curin,$fix,$intf):"").$comma 7539 .($legendo?doformat($curout,$fix,$intf):"").$comma 7540 ."\n"; 7541 } else { 7542 print "<TR><TD align=left><SMALL>".langmsg(2203,"Last") 7543 ."</SMALL></TD>"; 7544 do_bar_html($barlen,dp($curinpc,1),dp($curoutpc,1),$legendi,$legendo); 7545 print "<TD align=right nowrap>"; 7546 print $q->small(" <FONT color=#00d000>" 7547 .doformat($curin,$fix,$intf)."$unit</FONT>") 7548 if($curin>=0 and $legendi); 7549 print $q->small(" <FONT color=#00d000>(".doformat($curinpc,1,0)."%)</FONT>") 7550 if($curinpc>=0 and $legendi and $interfaces{$curif}{percent}); 7551 print "</TD><TD align=right nowrap>"; 7552 print $q->small(" <FONT color=#0000ff>" 7553 .doformat($curout,$fix,$intf)."$unit</FONT>") 7554 if($curout>=0 and $legendo); 7555 print $q->small(" <FONT color=#0000ff>(".doformat($curoutpc,1,0)."%)</FONT>") 7556 if($curoutpc>=0 and $legendo and $interfaces{$curif}{percent}); 7557 print "</TD></TR>\n"; 7558 } # csvmode 7559 } # c 7560 if( $a ) { 7561 $avgin = $interfaces{$curif}{baravgin}; 7562 $avgout= $interfaces{$curif}{baravgout}; 7563 $avginpc = $interfaces{$curif}{baravginpc}; 7564 $avgoutpc= $interfaces{$curif}{baravgoutpc}; 7565 if($csvmode) { 7566 print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma 7567 .'"'.langmsg(2201,"Avg").'"'.$comma 7568 .($legendi?doformat($avgin,$fix,$intf):"").$comma 7569 .($legendo?doformat($avgout,$fix,$intf):"").$comma 7570 ."\n"; 7571 } else { 7572 print "<TR><TD align=left><SMALL>".langmsg(2201,"Avg") 7573 ."</SMALL></TD>"; 7574 do_bar_html($barlen,dp($avginpc,1),dp($avgoutpc,1),$legendi,$legendo); 7575 print "<TD align=right nowrap>"; 7576 print $q->small(" <FONT color=#00d000>".doformat($avgin,$fix,$intf)."$unit</FONT>") 7577 if($avgin>=0 and $legendi); 7578 print $q->small(" <FONT color=#00d000>(".doformat($avginpc,1,0)."%)</FONT>") 7579 if($avginpc>=0 and $legendi and $interfaces{$curif}{percent}); 7580 print "</TD><TD align=right nowrap>"; 7581 print $q->small(" <FONT color=#0000ff>".doformat($avgout,$fix,$intf)."$unit</FONT>") 7582 if($avgout>=0 and $legendo); 7583 print $q->small(" <FONT color=#0000ff>(".doformat($avgoutpc,1,0)."%)</FONT>") 7584 if($avgoutpc>=0 and $legendo and $interfaces{$curif}{percent}); 7585 print "</TD></TR>\n"; 7586 } # csvmode 7587 } # a 7588 if( $m ) { 7589 $maxin = $interfaces{$curif}{barmaxin}; 7590 $maxout= $interfaces{$curif}{barmaxout}; 7591 $maxinpc = $interfaces{$curif}{barmaxinpc}; 7592 $maxoutpc= $interfaces{$curif}{barmaxoutpc}; 7593 if($csvmode) { 7594 print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma 7595 .'"'.langmsg(2200,"Max").'"'.$comma 7596 .($legendi?doformat($maxin,$fix,$intf):"").$comma 7597 .($legendo?doformat($maxout,$fix,$intf):"").$comma 7598 ."\n"; 7599 } else { 7600 print "<TR><TD align=left><SMALL>" 7601 .langmsg(2200,"Max")."</SMALL></TD>"; 7602 do_bar_html($barlen,dp($maxinpc,1),dp($maxoutpc,1),$legendi,$legendo); 7603 print "<TD align=right nowrap>"; 7604 print $q->small(" <FONT color=#00d000>".doformat($maxin,$fix,$intf)."$unit</FONT>") 7605 if($maxin>=0 and $legendi); 7606 print $q->small(" <FONT color=#00d000>(".doformat($maxinpc,1,0)."%)</FONT>") 7607 if($maxinpc>=0 and $legendi and $interfaces{$curif}{percent}); 7608 print "</TD><TD align=right nowrap>"; 7609 print $q->small(" <FONT color=#0000ff>".doformat($maxout,$fix,$intf)."$unit</FONT>") 7610 if($maxout>=0 and $legendo); 7611 print $q->small(" <FONT color=#0000ff>(".doformat($maxoutpc,1,0)."%)</FONT>") 7612 if($maxoutpc>=0 and $legendo and $interfaces{$curif}{percent}); 7613 print "</TD></TR>\n"; 7614 } # csvmode 7615 } # m 7616 if( $p ) { 7617 $perin = $interfaces{$curif}{barperin}; 7618 $perout= $interfaces{$curif}{barperout}; 7619 $perinpc = $interfaces{$curif}{barperinpc}; 7620 $peroutpc= $interfaces{$curif}{barperoutpc}; 7621 if($csvmode) { 7622 print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma 7623 .'"'.langmsg(2206,$PERCENT."th").'"'.$comma 7624 .($legendi?doformat($perin,$fix,$intf):"").$comma 7625 .($legendo?doformat($perout,$fix,$intf):"").$comma 7626 ."\n"; 7627 } else { 7628 print "<TR><TD align=left><SMALL>".langmsg(2206,"$PERCENT<sup>th</sup>") 7629 ."</SMALL></TD>"; 7630 do_bar_html($barlen,dp($perinpc,1),dp($peroutpc,1),$legendi,$legendo); 7631 print "<TD align=right nowrap>"; 7632 print $q->small(" <FONT color=#00d000>".doformat($perin,$fix,$intf)."$unit</FONT>") 7633 if($perin>=0 and $legendi); 7634 print $q->small(" <FONT color=#00d000>(".doformat($perinpc,1,0)."%)</FONT>") 7635 if($perinpc>=0 and $legendi and $interfaces{$curif}{percent}); 7636 print "</TD><TD align=right nowrap>"; 7637 print $q->small(" <FONT color=#0000ff>".doformat($perout,$fix,$intf)."$unit</FONT>") 7638 if($perout>=0 and $legendo); 7639 print $q->small(" <FONT color=#0000ff>(".doformat($peroutpc,1,0)."%)</FONT>") 7640 if($peroutpc>=0 and $legendo and $interfaces{$curif}{percent}); 7641 print "</TD></TR>\n"; 7642 } # csvmode 7643 } # p 7644} # foreach interface 7645print "</TABLE>\n" if(!$csvmode); 7646 7647# Page foot 7648if(!$csvmode) { 7649print "<DIV class=pagefoot>"; 7650print expandvars($config{'routers.cgi-pagefoot'}),"\n" 7651 if( defined $config{'routers.cgi-pagefoot'} ); 7652print "</DIV>"; 7653if( $gstyle !~ /p/ ) { 7654 my( $ngti, $ngto ) = ("",""); 7655 print "<DIV class=icons>".$q->hr; 7656 print "\n",$q->a({href=>"javascript:location.reload(true)"}, 7657 $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh.gif", 7658 alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20}))," \n" 7659 if(!$archdate); 7660# print $q->a({href=>"javascript:parent.makebookmark('" 7661# .$q->escape($router)."','__compact','$gtype','$gstyle','$gopts','$baropts','".$q->escape($extra)."')"}, 7662# $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", 7663# alt=>"Bookmark",border=>"0",width=>100,height=>20}))," \n"; 7664 print $q->a({href=>"$meurlfull?".optionstring({page=>"", xmtype=>"", 7665 if=>"__compact", xgstyle=>""}), target=>"_top" }, 7666 $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", 7667 alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20}))," \n"; 7668 print $q->a({href=>"$meurlfull?".optionstring({page=>"compactcsv"}), target=>"graph"}, 7669 $q->img({src=>"${config{'routers.cgi-iconurl'}}csv.gif", 7670 alt=>langmsg(5019,"CSV Download"),border=>"0",width=>100,height=>20})),"\n"; 7671 if( $gtype eq "6" ) { $ngto = "d"; } 7672 elsif( $gtype eq "d" ) { $ngto = "w"; $ngti = "6" if($usesixhour); } 7673 elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } 7674 elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } 7675 elsif( $gtype eq "y" ) { $ngti = "m"; } 7676 if( $ngti ) { 7677 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, 7678 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", 7679 alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20}))," \n"; 7680 } 7681 if( $ngto ) { 7682 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, 7683 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", 7684 alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20}))," \n"; 7685 } 7686 print "</DIV>"; 7687 print $q->br,"\n"; 7688 } # csvmode 7689} 7690 7691if(!$csvmode){ 7692 print "<!-- CAMPIO=[$c][$a][$m][$p][$io] gtype=$gtype baropts=$baropts -->\n"; 7693 do_footer(); 7694} # csvmode 7695} 7696 7697####################################################### 7698# This is for the summary of interfaces view 7699sub do_summary() 7700{ 7701# Start off. We use onload() and Javascript to force reload the 7702# lefthand (menu) panel. 7703my ($javascript, $e); 7704my ($rrd, $curif); 7705my ($m, $a, $l ); 7706my ($start,$step, $names, $data); 7707my ($savetz) = ""; 7708my ($legendi, $legendo, $legendx); 7709my ($donehead) = 0; 7710my ($withdetails) = 1; 7711my ($doneone) = 0; 7712my ($inhtml) = 1; 7713my (@sorted); 7714my ($gheight) = 100; 7715 7716calctimezone(); 7717 7718$javascript = make_javascript({}).graphpopupscript(); 7719 7720$withdetails = 0 if($interfaces{$interface}{nodetails}); 7721 7722if ( $gstyle =~ /2/ ) { $gheight = 200; } # double height 7723elsif ( $gstyle =~ /3/ ) { $gheight = 300; } # triple height 7724else { $gheight = 100; } # normal height 7725 7726start_html_ss({ -expires => "+5s", -script => $javascript, 7727 -onload => "LoadMenu()", -class=>'summary' }, 7728 $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); 7729 7730print $q->center($q->h2($routers{$router}{desc}))."\n" 7731 if($routers{$router}{desc}); 7732 7733print "<DIV class=pagetop>"; 7734print expandvars($config{'routers.cgi-pagetop'}),"\n" 7735 if( defined $config{'routers.cgi-pagetop'} ); 7736if( defined $config{'routers.cgi-mrtgpagetop'} 7737 and $config{'routers.cgi-mrtgpagetop'} =~ /y/i 7738 and $interfaces{$interface}{pagetop}) { 7739 print expandvars($interfaces{$interface}{pagetop}),"\n"; 7740} 7741print "</DIV>"; 7742# 7743# Now for the RRD stuff 7744eval { require RRDs; }; 7745if( $@ ) { 7746 if($config{'web-paranoia'} 7747 and $config{'web-paranoia'}=~/[yY1]/) { 7748 print $q->h1(langmsg(8999,"Error"))."<CODE>Cannot find RRDs.pm</CODE>\n"; 7749 } else { 7750 print $q->h1(langmsg(8999,"Error"))."<CODE>Cannot find RRDs.pm in ".(join " ",@INC )."</CODE>\n"; 7751 print $q->p("You can visit the configuration verification page " 7752 .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), 7753 target=>"_new"},"here.")); 7754 } 7755 do_footer(); 7756 return; 7757} 7758 7759if( $interfaces{$interface}{sortby} ) { 7760 @sorted = sorttargets($interface,$gtype,$interfaces{$interface}{sortby}); 7761} else { 7762 # for historical compatibility 7763 @sorted = sort byifdesc @{$interfaces{$interface}{targets}}; 7764} 7765 7766print "<TABLE border=0 width=100% align=center class=summary>\n"; 7767 7768$savetz = $ENV{TZ}; 7769$doneone = 0; 7770foreach $curif ( @sorted ) { 7771 next if(!$curif); # avoid rogue records 7772 7773 if($interfaces{$interface}{active}) { 7774 next if(!isactive($curif)); 7775 } 7776 7777 ($legendi,$legendo,$legendx)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); 7778 $legendi = $interfaces{$curif}{legendi} 7779 if(defined $interfaces{$curif}{legendi}); 7780 $legendo = $interfaces{$curif}{legendo} 7781 if(defined $interfaces{$curif}{legendo}); 7782 $legendx = $interfaces{$curif}{legendx} 7783 if(defined $interfaces{$curif}{legendx}); 7784 7785 if($interfaces{$interface}{overridelegend} and $interfaces{$curif}{shdesc} 7786 and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} 7787 or $interfaces{$curif}{noo} or $interfaces{$curif}{noi} ) 7788 ){ 7789 $legendi = $legendo = $interfaces{$curif}{shdesc}.':'; 7790 } 7791 7792 # timezone information 7793 if($interfaces{$curif}{timezone}) { 7794 $ENV{TZ} = $interfaces{$curif}{timezone} ; 7795 POSIX::tzset(); 7796 } 7797 7798 print "<TR WIDTH=100% VALIGN=TOP>" if($withdetails or !$doneone); 7799 print "<TD VALIGN=TOP>"; 7800 7801 if( $interfaces{$curif}{usergraph} ) { 7802 $rrd = $interfaces{$interfaces{$interface}{targets}->[0]}{rrd}; 7803 } elsif( defined $interfaces{$curif}{rrd} ) { 7804 $rrd = $interfaces{$curif}{rrd}; 7805 } else { 7806 $rrd = ""; 7807 } 7808 if($rrdcached and $rrd and $rrdcached!~/^unix:/) { 7809 my($pth) = $config{'routers.cgi-dbpath'}; 7810 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 7811 $rrd =~ s/^$pth\/*//; 7812 } 7813 if( $interfaces{$curif}{usergraph} ) { 7814 $lastupdate = RRDs::last($rrd,@rrdcached); 7815 $e = RRDs::error(); 7816 } elsif( defined $interfaces{$curif}{rrd} ) { 7817 # Last update stuff. 7818 $lastupdate = RRDs::last($rrd,@rrdcached); 7819 $e = RRDs::error(); 7820 } else { 7821 $e = langmsg(8002,"No RRD file defined for interface")." '$curif'"; 7822 } 7823 if( $e ) { 7824 print $q->p($q->b(langmsg(8003,"Error reading RRD database")." $rrd") 7825 .$q->br."<I>$e</I>".$q->br 7826 ."Check that MRTG has run successfully on this device, and has created the RRD file.")."\n"; 7827 print $q->p("Check that rrdcached is running correctly on $rrdcached") 7828 if($rrdcached and ($e=~/No such file/)); 7829 if(!$withdetails) { 7830 print "</TD>"; 7831 if($doneone) { print "</TR>\n" ; $doneone = 0; } 7832 else { $doneone = 1; } 7833 } else { 7834 print "</TD><TD>\n"; 7835 print $q->h3($interfaces{$curif}{shdesc}),"\n"; 7836 print $q->p($interfaces{$curif}{desc}),$q->br; 7837# print $q->dump; 7838 print "</TD></TR>\n"; 7839 } 7840 next; 7841 } 7842 if(!$withdetails) { 7843 if($interfaces{$interface}{withtop}) { 7844 print $q->br."\n".$interfaces{$curif}{pagetop}.$q->br 7845 if($interfaces{$curif}{pagetop}); 7846 } 7847 } 7848 print "<A href=".$meurlfull."?".optionstring({if=>"$curif"}, 7849 target=>"graph").">"; 7850 make_graph($inhtml,$gtype."s",$curif); 7851 print "</A>"; 7852 if($interfaces{$curif}{usergraph}) { 7853 print $q->br.$q->small("User Graph: ".$q->i($curif)); 7854 } else { 7855 print $q->br.$q->small("Target: ".$q->i($interfaces{$curif}{target})) 7856 if($interfaces{$curif}{target}); 7857 } 7858 if(!$withdetails) { 7859 if($interfaces{$interface}{withfoot}) { 7860 print $q->br."\n".$interfaces{$curif}{pagefoot} 7861 if($interfaces{$curif}{pagefoot}); 7862 } 7863 print "</TD>\n"; 7864 if($doneone) { print "</TR>\n" ; $doneone = 0; } 7865 else { $doneone = 1; } 7866 next; 7867 } 7868 print "</TD><TD>\n"; 7869 print "<DIV class=summarydetails style=\"max-height: ${gheight}px;\" >"; 7870 print $q->a({href=>"$meurlfull?".optionstring({if=>"$curif"}), 7871 target=>"graph"}, $q->b($interfaces{$curif}{desc})); 7872 if($interfaces{$interface}{withtop} and $interfaces{$curif}{pagetop}) { 7873 print $q->br.$interfaces{$curif}{pagetop}."\n"; 7874 } 7875 print $q->br,langmsg(3203,"Last update").": ".longdate($lastupdate), 7876 $q->br,"\n"; 7877 print langmsg(3204,"Timezone").": ".$interfaces{$curif}{timezone}.$q->br."\n" 7878 if($interfaces{$curif}{timezone}); 7879 7880 if($interfaces{$curif}{usergraph}) { 7881 if($rrdoutput) { 7882 $donehead = 0; 7883 foreach ( @$rrdoutput ) { 7884 if( /^<TR>/i and !$donehead ) { 7885 $donehead = 1; next; 7886 } 7887 print if(!$donehead); 7888 } 7889 } 7890 } else { 7891 if ( $interfaces{$curif}{max} 7892 and !$interfaces{$curif}{nomax} ) { 7893 if ( defined $interfaces{$curif}{mblegend} ) { 7894 print $interfaces{$curif}{mblegend}; 7895 } elsif ( $interfaces{$curif}{isif} ) { print langmsg(2103,"Bandwidth"); } 7896 else { print langmsg(2102,"Maximum"); } 7897 if(defined $interfaces{$curif}{max1} 7898 and defined $interfaces{$curif}{max2}) { 7899 print ": ".doformat( $interfaces{$curif}{max1}, 7900 $interfaces{$curif}{fixunits},0) 7901 .$interfaces{$curif}{unit}."/" 7902 .doformat( $interfaces{$curif}{max2}, 7903 $interfaces{$curif}{fixunits},0) 7904 .$interfaces{$curif}{unit}.$q->br,"\n"; 7905 } else { 7906 print ": ".doformat( $interfaces{$curif}{max}, 7907 $interfaces{$curif}{fixunits},0); 7908 print $interfaces{$curif}{unit}.$q->br,"\n"; 7909 } 7910 if( defined $interfaces{$curif}{absmax} 7911 and !$interfaces{$curif}{noabsmax} ) { 7912 if ( defined $interfaces{$curif}{amlegend} ) { 7913 print $interfaces{$curif}{amlegend}; 7914 } else { print langmsg(2104,"Hard Maximum"); } 7915 print ": ".doformat ($interfaces{$curif}{absmax}, 7916 $interfaces{$curif}{fixunits},0) 7917 .$interfaces{$curif}{unit}.$q->br,"\n"; 7918 } 7919 } 7920 print "Address: ".$interfaces{$curif}{address},$q->br,"\n" 7921 if ( $interfaces{$curif}{address} ); 7922 print "Interface IP: ".$interfaces{$curif}{ipaddress},$q->br,"\n" 7923 if ( $interfaces{$curif}{ipaddress} ); 7924 print "Interface # ".$interfaces{$curif}{ifno},$q->br,"\n" 7925 if(defined $interfaces{$curif}{ifno}); 7926 print "Interface name: ".$interfaces{$curif}{ifdesc},$q->br,"\n" 7927 if($interfaces{$curif}{ifdesc}); 7928# insert here the last/current/max values. 7929# print @$rrdoutput if($rrdoutput); 7930 $donehead = 0; 7931 if($rrdoutput) { 7932 foreach ( @$rrdoutput ) { 7933 if( /^<TR>/i and !$donehead ) { 7934 $donehead = 1; 7935 print "<TABLE border=1 cellspacing=0 class=summarydata><TR><TD></TD>"; 7936 print $q->td($q->b($legendi)) if(!$interfaces{$curif}{noi}); 7937 print $q->td($q->b($legendo)) if(!$interfaces{$curif}{noo}); 7938 print $q->td($q->b($legendx)) if($legendx); 7939 print "</TR>\n"; 7940 } 7941 print; 7942 } 7943 } 7944# now the 95th percentile, if required 7945 if( 7946# ( defined $config{'routers.cgi-percentile'} 7947# and $config{'routers.cgi-percentile'} =~ /y/i ) 7948 $interfaces{$curif}{total} 7949 or $interfaces{$curif}{percentile} 7950 ) { 7951 my( $pcdesc, $inarr, $outarr ); 7952 if(!$donehead) { 7953 print "<TABLE border=1 cellspacing=0 class=summarydata><TR><TD></TD>"; 7954 print $q->td($q->b($legendi)) if(!$interfaces{$curif}{noi}); 7955 print $q->td($q->b($legendo)) if(!$interfaces{$curif}{noo}); 7956 print $q->td($q->b($legendx)) if($legendx); 7957 print "</TR>\n"; 7958 $donehead = 1; 7959 } 7960 ( $pcdesc, $inarr, $outarr ) = calc_percentile($curif,$gtype,$PERCENT); 7961 if($pcdesc) { 7962 if($interfaces{$curif}{total}) { 7963 print "<TR>".$q->td(langmsg(2301,"Total over")." $pcdesc:"); 7964 print $q->td({ align=>"right"},doformat($$inarr[1], 7965$interfaces{$curif}{fixunits},$interfaces{$curif}{integer}) 7966 .$interfaces{$curif}{totunit}) if(!$interfaces{$curif}{noi}); 7967 print $q->td({ align=>"right"},doformat($$outarr[1], 7968$interfaces{$curif}{fixunits},$interfaces{$curif}{integer}) 7969 .$interfaces{$curif}{totunit2}) if(!$interfaces{$curif}{noo}); 7970 print "</TR>\n"; 7971 } 7972 if($interfaces{$curif}{percentile}) { 7973 print "<TR>".$q->td(langmsg(2300,$PERCENT."th Percentile for")." $pcdesc:"); 7974 print $q->td({ align=>"right"},doformat($$inarr[0], 7975$interfaces{$curif}{fixunits},0) 7976 .$interfaces{$curif}{unit}) if(!$interfaces{$curif}{noi}); 7977 print $q->td({ align=>"right"},doformat($$outarr[0], 7978$interfaces{$curif}{fixunits},0) 7979 .$interfaces{$curif}{unit2}) if(!$interfaces{$curif}{noo}); 7980 } 7981 } else { 7982 print "<TR>".$q->td(langmsg(8004,"Error in ${PERCENT}th percentile calcs").":") 7983 .$q->td($$inarr[2]).$q->td($$outarr[2])."\n"; 7984 } 7985 } 7986 print "</TABLE>".$q->br."\n" if($donehead); 7987 } # not usergraph 7988 if($interfaces{$interface}{withfoot} and $interfaces{$curif}{pagefoot}) { 7989 print $interfaces{$curif}{pagefoot}."\n"; 7990 } 7991 print "</DIV>"; 7992 print "</TD></TR>\n"; 7993 if($savetz){ $ENV{TZ}=$savetz; POSIX::tzset(); } 7994} # foreach 7995print "<TD></TD></TR>" if(!$withdetails and $doneone); 7996print "</TABLE>\n"; 7997 7998# Page foot 7999print "<DIV class=pagefoot>"; 8000if( defined $config{'routers.cgi-mrtgpagefoot'} 8001 and $config{'routers.cgi-mrtgpagefoot'} =~ /y/i 8002 and $interfaces{$interface}{pagefoot}) { 8003 print expandvars($interfaces{$interface}{pagefoot}),"\n"; 8004} 8005print expandvars($config{'routers.cgi-pagefoot'}),"\n" 8006 if( defined $config{'routers.cgi-pagefoot'} ); 8007print "</DIV><DIV class=icons>"; 8008if( $gstyle !~ /p/ ) { 8009 my( $u, $ngti, $ngto ) = ("","",""); 8010 print $q->hr; 8011 print "\n",$q->a({href=>"javascript:location.reload(true)"}, 8012 $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh.gif", 8013 alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20}))," \n" 8014 if(!$archdate); 8015 print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", xmtype=>"", 8016 xgstyle=>""}), target=>"_top" }, 8017 $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", 8018 alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20}))," \n"; 8019 if( $gtype eq "6" ) { $ngto = "d"; } 8020 elsif( $gtype eq "d" ) { $ngto = "w"; $ngti = '6' if($usesixhour); } 8021 elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } 8022 elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } 8023 elsif( $gtype eq "y" ) { $ngti = "m"; } 8024 if( $ngti ) { 8025 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, 8026 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", 8027 alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20}))," \n"; 8028 } 8029 if( $ngto ) { 8030 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, 8031 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", 8032 alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20}))," \n"; 8033 } 8034 8035 print $q->br,"\n"; 8036} 8037print "</DIV>"; 8038do_footer(); 8039} 8040 8041sub do_empty() 8042{ 8043 my ($javascript); 8044 8045 $javascript = make_javascript({}); 8046 8047 start_html_ss({ -expires => "+5s", -script => $javascript, 8048 -onload => "LoadMenu()", -bgcolor => "#ffffff", -class=>'empty' }); 8049 8050 if( $router eq "none" ) { 8051 print $q->h3(langmsg(9002,"Please select a device")); 8052 } else { 8053 print $q->h3(langmsg(9003,"Please select a target")); 8054 } 8055 do_footer(); 8056} 8057 8058sub do_graph($) 8059{ 8060# Start off. We use onload() and Javascript to force reload the 8061# lefthand (menu) panel. 8062my ($javascript, $e); 8063my ($rrd, $curif); 8064my ($iconsuffix) = ""; 8065my ($bgcolor,$legendi,$legendo,$legendx); 8066my ($inhtml) = $_[0]; # true if we want HTML page 8067 8068calctimezone(); 8069 8070$iconsuffix = "-bw" if( $gstyle =~ /b/ ); 8071 8072$javascript = make_javascript({}).graphpopupscript(); 8073# We need to subsequently add the javascript for the actuals array if necessary 8074$bgcolor = $defbgcolour; 8075$bgcolor = $interfaces{$interface}{background} if($interface and defined $interfaces{$interface} and defined $interfaces{$interface}{background}); 8076 8077if($inhtml) { 8078 my($class) = $interfaces{$interface}{mode}?$interfaces{$interface}{mode}:'generic'; 8079 $class =~ s/^\177_//; 8080 start_html_ss({ -expires => "+5s", -script => $javascript, 8081 -onload => "LoadMenu()", -bgcolor => $bgcolor, 8082 -class => $class }, 8083 $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); 8084} 8085 8086# Catch for if there are NO cfg files. 8087if( ! $interface or ! $router 8088 or $interface eq "none" or $interface =~ /^__/ 8089 or $router eq "none" ) { 8090 if(!$inhtml) { 8091 if($opt_I) { 8092 print "Device: $router\nTarget: $interface\nError: no valid target was specified!\n"; 8093 } else { 8094 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 8095 } 8096 return; 8097 } 8098 print $q->h3(langmsg(9004,"No valid target is selected")); 8099 if( $#cfgfiles eq -1 8100 and $config{'routers.cgi-cfgfiles'} ne 'none' ) { 8101 print $q->p("You have no valid MRTG configuration files. You should check your configuration in $conffile.".$q->br."[" 8102 .$config{'routers.cgi-confpath'}.$pathsep 8103 .$config{'routers.cgi-cfgfiles'}."]"),"\n"; 8104 print $q->p("NT users should check that this includes the correct drive letter.")."\n" if($config{'web-NT'}); 8105 print $q->p("confpath = ".$config{'routers.cgi-confpath'}); 8106 print $q->p("cfgfiles = ".$config{'routers.cgi-cfgfiles'}); 8107 } 8108 do_footer(); 8109 return; 8110} 8111 8112# Now for the RRD stuff 8113eval { require RRDs; }; 8114if( $@ ) { 8115 if(!$inhtml) { 8116 if($opt_I) { 8117 print "Error: $@\n"; 8118 } else { 8119 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 8120 } 8121 return; 8122 } 8123 if($config{'web-paranoia'} 8124 and $config{'web-paranoia'}=~/[yY1]/) { 8125 print $q->h1(langmsg(8999,"Error")),"<CODE>cannot find RRDs.pm</CODE>\n"; 8126 } else { 8127 print $q->h1(langmsg(8999,"Error")),"<CODE>cannot find RRDs.pm in ".(join " ",@INC)."</CODE>\n"; 8128 print $q->p("You can visit the configuration verification page " 8129 .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), 8130 target=>"_new"},"here.")); 8131 } 8132 do_footer(); 8133 return 0; 8134} 8135# Now, we have to do this differently depending on which gtype we have 8136# We do a switch for the different graphs. 8137# We have to call RRD to create them, and the IMG tag is created ready to 8138# stuff into the page! 8139$rrd = ""; 8140if ( $interface =~ /^__/ ) { # compact and summary 8141 $curif = (keys(%interfaces))[0]; 8142 $rrd = $interfaces{$curif}{rrd}; 8143} elsif ( $interfaces{$interface}{usergraph} ) { # user defined 8144 $rrd = $interfaces{$interfaces{$interface}{targets}->[0]}{rrd}; 8145} else { 8146 $rrd = $interfaces{$interface}{rrd} 8147 if( defined $interfaces{$interface}{rrd} ); 8148} 8149if($rrd and $rrdcached and $rrdcached!~/^unix:/) { 8150 my($pth) = $config{'routers.cgi-dbpath'}; 8151 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 8152 $rrd =~ s/^$pth\/*//; 8153} 8154 8155# Timezone 8156if($interfaces{$interface}{timezone}) { 8157 $ENV{TZ} = $interfaces{$interface}{timezone} ; 8158 POSIX::tzset(); 8159} 8160 8161# Last update stuff. 8162if( $rrd ) { 8163 $lastupdate = RRDs::last($rrd,@rrdcached); 8164 $e = RRDs::error(); 8165} else { 8166 $e = langmsg(8002,"No RRD file defined for interface")." '$interface'"; 8167} 8168if( $e ) { 8169 if(!$inhtml) { 8170 if($opt_I) { 8171 print "Error: $e\n"; 8172 } else { 8173 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 8174 } 8175 return; 8176 } 8177 print $q->h3("$interfaces{$interface}{shdesc}"),"\n"; 8178 print $q->p("$interfaces{$interface}{desc}"),"\n"; 8179 if($config{'web-paranoia'} 8180 and $config{'web-paranoia'}=~/[yY1]/) { 8181 print $q->p($q->b(langmsg(8003,"Error reading RRD database")).$q->br."Check that MRTG has run successfully on this device, and has created the RRD file. If using rrdcached, check that this is running and available.")."\n"; 8182 } else { 8183 print $q->p($q->b(langmsg(8003,"Error reading RRD database")." $rrd").$q->br.$e.$q->br."Check that MRTG has run successfully on this device, and has created the RRD file.")."\n"; 8184 print $q->p("Check that rrdcached is running on $rrdcached") 8185 if($rrdcached and ($e=~/No such file/)); 8186 # We may need to give a more helpful error message here if the 8187 # user is asking for a nonexistant archive date 8188 print $q->p("You can visit the configuration verification page " 8189 .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), 8190 target=>"_new"},"here.")); 8191 } 8192# print $q->dump; 8193} else { 8194 # any defined pagetop stuff 8195 if($inhtml) { 8196 print "<DIV class=pagetop>"; 8197 print expandvars($config{'routers.cgi-pagetop'}),"\n" 8198 if( defined $config{'routers.cgi-pagetop'} ); 8199 if((( defined $config{'routers.cgi-mrtgpagetop'} 8200 and $config{'routers.cgi-mrtgpagetop'} =~ /y/i 8201 and !$interfaces{$interface}{usergraph}) 8202 or $interfaces{$interface}{withtop} ) 8203 and $interfaces{$interface}{pagetop} 8204 ) { 8205 print expandvars($interfaces{$interface}{pagetop}),"\n"; 8206 } 8207 print "</DIV>"; 8208 } 8209 my $suffix = ( $gtype =~ /s/ ) ? "s" : ""; 8210 $suffix .= "-" if( $gtype =~ /-/ ); 8211 if( defined $interfaces{$interface}{suppress} ) { 8212 my $pat = "[".$interfaces{$interface}{suppress}."]"; 8213 $gtype =~ s/$pat//g; 8214 } 8215 foreach my $gt ( '6','d','w','m','y' ) { 8216 next if ( $gtype !~ /$gt/ ); 8217 print $q->h4($gtypes{$gt}) if((length($gtype)>1) and ($gtype!~/s/)); 8218 make_graph($inhtml,"$gt$suffix",$interface) ; 8219 print $q->br,"\n" if($inhtml and (length($gtype) > 2 or $uopts=~/s/) 8220 and ($gtype!~/s/)); 8221 } 8222 8223 return if(!$inhtml); # we can leave now 8224 8225 print $q->br; 8226 print "<TABLE border=0>"; 8227 print "<TR><TD>".langmsg(3205,"Data archived") 8228 .":</TD><TD>$archdate</TD></TR>\n" if($archdate and !$basetime); 8229 print "<TR><TD>".langmsg(3203,"Last update").": </TD><TD>" 8230 .longdate($lastupdate)."</TD></TR>\n" unless($basetime); 8231 print "<TR><TD>".langmsg(3204,"Timezone").":</TD><TD>" 8232 .$interfaces{$interface}{timezone}."</TD></TR>\n" 8233 if($interfaces{$interface}{timezone}); 8234 print "</TABLE>\n"; 8235 if(( 8236# ( defined $config{'routers.cgi-percentile'} 8237# and $config{'routers.cgi-percentile'} =~ /y/i ) 8238 $interfaces{$interface}{total} 8239 or $interfaces{$interface}{percentile} 8240 ) and !$interfaces{$interface}{nodetails} 8241 and !$interfaces{$interface}{nolegend} 8242 ) { 8243 my( $i, $pcdesc, $inarr, $outarr, $sfx ); 8244 8245 print "<TABLE border=0 >\n"; 8246 8247 # Loop through interfaces, if on userdefined graph 8248 foreach $curif ( $interfaces{$interface}{usergraph}? 8249 (@{$interfaces{$interface}{targets}}):($interface) ) { 8250 # Skip this if it is not an active graph 8251 if($interfaces{$interface}{active}) { next if(!isactive($curif)); } 8252 print "<TR><TD colspan=5 align=left>" 8253 .$q->a({href=>("$meurlfull?".optionstring({ 8254 'if'=>$curif, 'page'=>'graph' 8255 } ))}, $q->i($interfaces{$curif}{desc})) 8256 ."</TD></TR>\n" 8257 if($interfaces{$interface}{usergraph}); 8258 8259 $sfx = ""; 8260 ($legendi,$legendo,$legendx)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); 8261 $legendi=$interfaces{$curif }{legendi} 8262 if(defined $interfaces{$curif }{legendi}); 8263 $legendo=$interfaces{$curif }{legendo} 8264 if(defined $interfaces{$curif }{legendo}); 8265 $legendx=$interfaces{$curif }{legendx} 8266 if(defined $interfaces{$curif }{legendx}); 8267 $legendi =~ s/ / /g; $legendo =~ s/ / /g; 8268 $sfx = "-" if( $gtype =~ /-/ ); 8269 # Loop through time periods, if on multiple graphs 8270 foreach $i ( qw/d w m y/ ) { 8271 next if((index $gtype, $i) < 0); 8272 ( $pcdesc, $inarr, $outarr ) = calc_percentile($curif,$i.$sfx,$PERCENT); 8273 if($pcdesc) { 8274# print "<TR>".$q->td("").$q->td($q->b($legendi)) 8275# .$q->td($q->b($legendo)); 8276 if($interfaces{$interface}{total}) { 8277 print "<TR>".$q->td($q->b(langmsg(2301,"Total over")." $pcdesc:")); 8278 print $q->td($legendi).$q->td({align=>"right"},doformat($$inarr[1], 8279$interfaces{$curif }{fixunits},$interfaces{$curif }{integer}) 8280 .$interfaces{$curif }{totunit}) 8281 .$q->td("") if(!$interfaces{$interface}{noi}); 8282 print $q->td($legendo).$q->td({align=>"right"},doformat($$outarr[1], 8283$interfaces{$curif }{fixunits},$interfaces{$curif }{integer}) 8284 .$interfaces{$curif }{totunit2}) 8285 .$q->td("") if(!$interfaces{$interface}{noo}); 8286 print "</TR>\n"; 8287 } 8288 if($interfaces{$interface}{percentile}) { 8289 my($pclabel); 8290 print "<TR>".$q->td($q->b(langmsg(2300,$PERCENT."th Percentile for")." $pcdesc:")); 8291 if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}) { 8292 $pclabel = ""; 8293 $pclabel = " (" 8294 .doformat(($$inarr[0]/$interfaces{$curif}{max}*100.0),1,0) 8295 ."%)" if($interfaces{$curif}{percent} and $interfaces{$curif}{max}); 8296 print $q->td($legendi).$q->td({align=>"right"}, 8297 doformat($$inarr[0], $interfaces{$curif}{fixunits},0) 8298 .$interfaces{$curif}{unit}) ; 8299 print $q->td($pclabel); 8300 } 8301 if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}) { 8302 $pclabel = ""; 8303 $pclabel = " (" 8304 .doformat(($$outarr[0]/$interfaces{$curif}{max}*100.0),1,0) 8305 ."%)" 8306 if($interfaces{$curif}{percent} 8307 and $interfaces{$curif}{max}); 8308 print $q->td($legendo).$q->td({align=>"right"}, 8309 doformat($$outarr[0], $interfaces{$curif}{fixunits},0) 8310 .$interfaces{$curif}{unit2}) ; 8311 print $q->td($pclabel); 8312 } 8313 print "</TR>\n"; 8314 } 8315 } else { 8316 print "<TR><TD>".langmsg(8004,"Error in ${PERCENT}th percentile") 8317 .":</TD><TD colspan=5>" 8318 ."[".$$inarr[2]."]".$q->br 8319 ."[".$$outarr[2]."]</TD></TR>" if($$inarr[2] or $$outarr[2]); 8320 } # pcdesc 8321 } # foreach timeperiod 8322 } # foreach interface 8323 print "</TABLE>\n"; 8324 } 8325 8326 print $q->br."<DIV class=pagefoot>"; 8327 if((( defined $config{'routers.cgi-mrtgpagefoot'} 8328 and $config{'routers.cgi-mrtgpagefoot'} =~ /y/ 8329 and !$interfaces{$interface}{usergraph}) 8330 or $interfaces{$interface}{withfoot}) 8331 and $interfaces{$interface}{pagefoot} 8332 ) { 8333 print expandvars($interfaces{$interface}{pagefoot}),"\n"; 8334 } 8335 print expandvars($config{'routers.cgi-pagefoot'}),"\n" 8336 if( defined $config{'routers.cgi-pagefoot'} ); 8337 print "</DIV><DIV class=extensions>"; 8338 8339 # any extensions defined for this target? 8340 if( defined $interfaces{$interface}{extensions} 8341 and $uopts !~/s/ ) { 8342 my($ext, $u, $targ); 8343 print $q->hr,"\n"; 8344 foreach $ext ( @{$interfaces{$interface}{extensions}} ) { 8345 if($seclevel<$ext->{level}) { 8346# print $ext->{desc}." (".$ext->{level}.")".$q->br."\n"; 8347 next; 8348 } 8349 $targ = "graph"; 8350 $targ = $ext->{target} if( defined $ext->{target} ); 8351 $u=$ext->{url}; 8352 if(!$ext->{noopts}) { 8353 $u .= "?x=2" if( $u !~ /\?/ ); 8354 $u .= "&fi=".$q->escape($router)."&ta=" 8355 .$q->escape($interface)."&url=".$q->escape($q->url()); 8356 $u .= "&t=".$q->escape($targ); 8357 $u .= "&L=".$seclevel; 8358 $u .= "&uopts=".$uopts if($uopts); 8359 $u .= "&h=".$q->escape($interfaces{$interface}{hostname}) 8360 if(defined $interfaces{$interface}{hostname}); 8361 $u .= "&c=".$q->escape($interfaces{$interface}{community}) 8362 if(defined $interfaces{$interface}{community} 8363 and $ext->{insecure}); 8364 $u .= "&ifno=".$interfaces{$interface}{ifno} 8365 if(defined $interfaces{$interface}{ifno}); 8366 $u .= "&b=".$q->escape("javascript:history.back();history.back()") 8367 ."&conf=".$q->escape($conffile); 8368 $u .= "&ad=$archdate" if($archdate); 8369 } elsif( $ext->{noopts} == 2 ) { 8370 $u .= "&L=$seclevel&xgtype=$gtype&xgstyle=$gstyle"; 8371 $u .= "&arch=$archdate" if($archdate); 8372 } 8373 print $q->img( { height=>15, width=>15, 8374 src=>($config{'routers.cgi-smalliconurl'}.$ext->{icon}) }) 8375 ." "; 8376# print $q->img( { height=>15, width=>15, 8377# src=>($config{'routers.cgi-iconurl'}."alert-sm.gif") }) 8378# ." " if($ext->{insecure}); 8379 print $q->a( { href=>$u, target=>$targ }, 8380 expandvars($ext->{desc})).$q->br."\n"; 8381 } 8382 } 8383 8384 print "</DIV><DIV class=icons>"; 8385 # routers.cgi page footer 8386 if( $gstyle !~ /p/ ) { 8387 my( $u, $ngti, $ngto ) = ("","",""); 8388 print $q->hr; 8389 print "\n",$q->a({href=>"javascript:location.reload(true)"}, 8390 $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh$iconsuffix.gif",alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20})),"\n" 8391 if(!$archdate); 8392# print $q->a({href=>"javascript:parent.makebookmark('" 8393# .$q->escape($router)."','".$q->escape($interface) 8394# ."','$gtype','$gstyle','$gopts','$baropts','".$q->escape($extra)."')"}, 8395 print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", 8396 xmtype=>"", xgstyle=>""}), target=>"_top" }, 8397 $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark$iconsuffix.gif",alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20})), "\n"; 8398 if( $gtype eq "6" ) { $ngto = "d"; } 8399 elsif( $gtype eq "d" ) { $ngto = "w"; $ngti='6' if($usesixhour); } 8400 elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } 8401 elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } 8402 elsif( $gtype eq "y" ) { $ngti = "m"; } 8403 if( $ngti ) { 8404 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, 8405 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", 8406 alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20})),"\n"; 8407 } 8408 if( $ngto ) { 8409 print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, 8410 $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", 8411 alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20})),"\n"; 8412 } 8413# if(!$interfaces{$interface}{usergraph}) { 8414 print $q->a({href=>"$meurlfull?".optionstring({page=>"csv"}), target=>"graph"}, 8415 $q->img({src=>"${config{'routers.cgi-iconurl'}}csv.gif", 8416 alt=>langmsg(5019,"CSV Download"),border=>"0",width=>100,height=>20})),"\n"; 8417# } 8418 if( defined $config{'routers.cgi-archive'} 8419 and $config{'routers.cgi-archive'} =~ /[y1]/i ) { 8420 print $q->a({href=>"$meurlfull?".optionstring({page=>"archive"}), 8421 target=>"graph"}, 8422 $q->img({src=>"${config{'routers.cgi-iconurl'}}archive.gif", 8423 alt=>langmsg(5020,"Add to archive"),border=>"0",width=>100,height=>20})),"\n"; 8424 } 8425 my($nuopts) = $uopts; # 3-way toggle 8426 if($nuopts =~ /r/) { 8427 $nuopts =~ s/r/R/g; 8428 } elsif($nuopts =~ /R/) { 8429 $nuopts =~ s/[rR]//g; 8430 } else { 8431 $nuopts .= 'r'; 8432 } 8433 print $q->a({href=>"$meurlfull?".optionstring({uopts=>"$nuopts"}), 8434 target=>"graph"}, 8435 $q->img({src=>"${config{'routers.cgi-iconurl'}}rescale.gif", 8436 alt=>langmsg(5021,"Rescale"),border=>"0",width=>100,height=>20})),"\n"; 8437 8438 print $q->br,"\n"; 8439 8440 8441 } # gstyle not p 8442 print "</DIV>"; 8443} 8444# Finish off the page (this does the ending body and html tags) 8445do_footer(); 8446} 8447 8448# Information on this router 8449sub do_info() 8450{ 8451# Start off. We use onload() and Javascript to force reload the 8452# lefthand (menu) panel. 8453my ($javascript, $ifkey,$x, $icon); 8454my ($acount,$archivepat,@archive,$archives); 8455 8456$javascript = make_javascript({}); 8457 8458start_html_ss({ -expires => "+5s", -script => $javascript, 8459 -onload => "LoadMenu()", -class=>'info' }); 8460 8461# Here we build up a page of info, with lotsalinks. 8462 8463print $q->center($q->h2($routers{$router}{desc}))."\n"; 8464 8465print $q->h3(langmsg(3004,"Device Information")),"\n"; 8466 8467print $q->a({href=>"$meurlfull?".optionstring({page=>"graph",if=>"_summary_"}), 8468 target=>"graph"}, 8469 $q->b("$router: ".$routers{$router}{shdesc}.": " 8470 .$routers{$router}{desc})),$q->br,"\n"; 8471print $q->br.$q->b(langmsg(3005,"MRTG config file").": ").$routers{$router}{file}."\n"; 8472print $q->br.$q->p("WorkDir: ".($routers{$router}{workdir}?$routers{$router}{workdir}:$config{'routers.cgi-dbpath'}))."\n"; 8473print $q->b("Targets:").$q->br(); 8474print "<UL>"; 8475$ifkey = ""; # we want this later 8476foreach (sort byifdesc keys (%interfaces)) { 8477 next if(!$_); # avoid rogue records 8478 next if(/^__/); 8479 next if($interfaces{$_}{mode} =~ /^\177_AUTO/); # system created 8480 # count archived copies 8481 $archivepat = $router; $archivepat =~ s/[\?#\\\/]//g; 8482 $archivepat = $config{'routers.cgi-graphpath'}.$pathsep 8483 .$archivepat.$pathsep.$_.$pathsep."*.*"; 8484 @archive = glob($archivepat); 8485 $acount = $#archive + 1; 8486 # now the data line 8487 $icon = $q->img({src=>($config{'routers.cgi-smalliconurl'}.$interfaces{$_}{icon}) 8488 ,width=>15,height=>15})." "; 8489 $ifkey = $_ if(!$ifkey and $interfaces{$_}{community} 8490 and $interfaces{$_}{hostname}); 8491 if( $acount == 1 ) { 8492 $archives = $q->br.langmsg(3300,"This target has one archived graph."); 8493 } elsif( $acount > 1 ) { 8494 $archives = $q->br.langmsg(3301,"This target has") 8495 ." $acount ".langmsg(3302,"archived graphs."); 8496 } else { 8497 $archives = ""; 8498 } 8499 if( $interfaces{$_}{usergraph} ) { 8500 print $q->li( $icon.$q->a( 8501 {href=>"$meurlfull?".optionstring({if=>"$_"}), 8502 target=>"graph"}, 8503 $interfaces{$_}{desc})." [$_] " 8504 .($interfaces{$_}{graphstyle}?("<".$interfaces{$_}{graphstyle}.">"):"") 8505 .($interfaces{$_}{default}?"[DEFAULT]":"") 8506 ." \n$archives"); 8507 } elsif( defined $interfaces{$_}{ifno} ) { 8508 # interface number 8509 print $q->li( $icon.$q->a( 8510 {href=>"$meurlfull?".optionstring({if=>"$_"}), 8511 target=>"graph"}, 8512 "#".$interfaces{$_}{ifno}.": ".$interfaces{$_}{desc} 8513 )." [".$interfaces{$_}{target}."] ".langmsg(6200,"Max")." " 8514 .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) 8515 .$interfaces{$_}{unit} 8516 ." {".$interfaces{$_}{mode}."} " 8517 .($interfaces{$_}{default}?"[DEFAULT]":"") 8518 ."\n$archives"),"\n"; 8519 } elsif( defined $interfaces{$_}{ifdesc} ) { 8520 # interface description 8521 print $q->li( $icon.$q->a( 8522 {href=>"$meurlfull?".optionstring({if=>"$_"}), 8523 target=>"graph"}, 8524 $interfaces{$_}{shdesc}.": ".$interfaces{$_}{desc} 8525 )." [".$interfaces{$_}{target}."] ".langmsg(6200,"Max")." " 8526 .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) 8527 .$interfaces{$_}{unit} 8528 ." {".$interfaces{$_}{mode}."} " 8529 .($interfaces{$_}{default}?"[DEFAULT]":"") 8530 ."\n$archives"),"\n"; 8531 } elsif( defined $interfaces{$_}{ipaddress} ) { 8532 # IP address 8533 print $q->li( $icon.$q->a( 8534 {href=>"$meurlfull?".optionstring({if=>"$_"}), 8535 target=>"graph"}, 8536 $interfaces{$_}{ipaddress}.": ".$interfaces{$_}{desc} 8537 )." [".$interfaces{$_}{target}."] " 8538 .langmsg(6200,"Max")." " 8539 .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) 8540 .$interfaces{$_}{unit} 8541 ." {".$interfaces{$_}{mode}."} " 8542 .($interfaces{$_}{default}?"[DEFAULT]":"") 8543 ."\n$archives"),"\n"; 8544 } else { 8545 # userdefined and unknown 8546 print $q->li( $icon.$q->a( 8547 {href=>"$meurlfull?".optionstring({if=>"$_"}), 8548 target=>"graph"}, 8549 $interfaces{$_}{desc})." [".$interfaces{$_}{target}."] " 8550 .langmsg(6200,"Max")." " 8551 .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) 8552 .$interfaces{$_}{unit} 8553# ."(f=".$interfaces{$_}{factor}.",m=".$interfaces{$_}{mult}.")" 8554 ." {".$interfaces{$_}{mode}."}" 8555 .($interfaces{$_}{graphstyle}?("<".$interfaces{$_}{graphstyle}.">"):"") 8556 .($interfaces{$_}{default}?"[DEFAULT]":"") 8557 ."\n$archives" 8558 ),"\n"; 8559 } 8560} 8561print "</UL>\n"; 8562 8563# Can we call out to the routingtable.cgi program? 8564if( defined $config{'routers.cgi-routingtableurl'} 8565 and ( !defined $routers{$router}{routingtable} 8566 or $routers{$router}{routingtable} eq "y" )) { 8567 if($ifkey) { 8568 print $q->a({target=>"_self", 8569 href=>($config{'routers.cgi-routingtableurl'} 8570 ."?r=".$q->escape($interfaces{$ifkey}{hostname}) 8571 ."&h=".$q->escape($interfaces{$ifkey}{hostname}) 8572 ."&c=".$q->escape($interfaces{$ifkey}{community}) 8573 ."&url=".$q->escape($q->url()) 8574 ."&t=graph&b=javascript:".$q->escape("history.back();history.back()") 8575 ."&conf=".$q->escape($conffile))}, 8576 langmsg(3303,"Show routing table for this device"))." (may take some time)", 8577 $q->br,$q->br,"\n"; 8578 } else { 8579 print langmsg(3304,"Routing table information not available."),$q->br, 8580 $q->br,"\n"; 8581 } 8582} 8583 8584# Finish off the page (this does the ending body and html tags) 8585do_footer(); 8586} 8587 8588############################################################################ 8589# Export of data to CSV format -- single RRD 8590sub do_export() 8591{ 8592 my( $start, $step, $names, $data, $line); 8593 my( $mstart, $mstep, $mnames, $maxdata, $mline ); 8594 my( $rrd, @opts, $e, $d, $t, $i, $r, @dat ); 8595 my( $thisif, $startpoint, $endpoint, $resolution ); 8596 8597 my( @allifs ); 8598 8599 $comma = substr( $config{'web-comma'},0,1 ) 8600 if(defined $config{'web-comma'}); 8601 $comma = ',' if(!$comma); 8602 8603 eval { require RRDs; }; 8604 if( $@ ) { 8605 print "ERROR".$comma."Cannot find RRDs.pm!".$comma.$@; 8606 return; 8607 } 8608 if( !$interface ) { 8609 print langmsg(9004,"No interface selected!"); 8610 return; 8611 } 8612 8613 # If this is a normal one, then just one interface. If it is a 8614 # userdefined, then we wil have a list of targets to process. 8615 @allifs = ( $interface ); 8616 @allifs = @{$interfaces{$interface}{targets}} 8617 if( $interfaces{$interface}{targets} ); 8618 8619 foreach $thisif ( @allifs ) { 8620 8621 # Header line 8622 print "\"Hostname\"$comma\"Target\"$comma\"Sample Date YMD\"$comma\"Sample Time HHMM\"$comma\"Count in seconds\""; 8623 if( $interfaces{$thisif}{aspercent}) { 8624 print "$comma\"Raw data 1\"" 8625 if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); 8626 print "$comma\"Raw data 2\"" 8627 if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); 8628 } elsif( $interfaces{$thisif}{dorelpercent} ) { 8629 print "$comma\"Raw data 1\""; 8630 print "$comma\"Raw data 2\""; 8631 } 8632 print "$comma\"".$interfaces{$thisif}{legend1}.($interfaces{$thisif}{unit}? 8633 (' in '.$interfaces{$thisif}{unit}):'').'"' 8634 if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); 8635 print "$comma\"".$interfaces{$thisif}{legend2}.($interfaces{$thisif}{unit}? 8636 (' in '.$interfaces{$thisif}{unit}):'').'"' 8637 if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); 8638 if( $gtype !~ /6/ ) { 8639 if( $interfaces{$thisif}{aspercent} ) { 8640 print "$comma\"Raw max data 1\"" 8641 if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); 8642 print "$comma\"Raw max data 2\"" 8643 if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); 8644 } elsif( $interfaces{$thisif}{dorelpercent} ) { 8645 print "$comma\"Raw max data 1\""; 8646 print "$comma\"Raw max data 2\""; 8647 } 8648 print "$comma\"".$interfaces{$thisif}{legend3}.($interfaces{$thisif}{unit}? 8649 (' in '.$interfaces{$thisif}{unit}):'').'"' 8650 if($interfaces{$thisif}{legend3} and !$interfaces{$thisif}{noi}); 8651 print "$comma\"".$interfaces{$thisif}{legend4}.($interfaces{$thisif}{unit}? 8652 (' in '.$interfaces{$thisif}{unit}):'').'"' 8653 if($interfaces{$thisif}{legend4} and !$interfaces{$thisif}{noo}); 8654 } 8655 print "\r\n"; 8656 $i = $interfaces{$thisif}{shdesc}; 8657 $r = $routers{$router}{desc}; 8658 $r = $interfaces{$thisif}{hostname} if(!$r); 8659 $r = $router if(!$r); 8660 $r = "Unknown" if(!$r); 8661 8662 $rrd = $interfaces{$thisif}{rrd}; 8663 if($rrd and $rrdcached and $rrdcached!~/^unix:/) { 8664 my($pth) = $config{'routers.cgi-dbpath'}; 8665 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 8666 $rrd =~ s/^$pth\/*//; 8667 } 8668 foreach ( $gtype ) { 8669 /y/ and do { $resolution = 3600; $startpoint = "-1y"; 8670 last; }; 8671 /m/ and do { $resolution = 1800; $startpoint = "-1month"; 8672 last; }; 8673 /w/ and do { $resolution = 300; $startpoint = "-7d"; 8674 last; }; 8675 /6/ and do { $resolution = 60*$interfaces{$thisif}{interval}; 8676 $startpoint = "-6h"; last; }; 8677 $resolution = 60*$interfaces{$thisif}{interval}; # interval 8678 $startpoint = "-24h"; # 1 day 8679 } 8680 $resolution = 300 if(!$resolution); 8681 8682 if($basetime) { 8683 @opts = ( $rrd, "AVERAGE", "-e", $basetime, 8684 "-s", "end".$startpoint ); 8685 } elsif( $gtype =~ /-/ ) { 8686 @opts = ( $rrd, "AVERAGE", "-e", "now".$startpoint, 8687 "-s", "end".$startpoint ); 8688 } elsif( $uselastupdate ) { 8689 $lastupdate = RRDs::last($rrd,@rrdcached); 8690 $e = RRDs::error(); 8691 if(!$lastupdate) { 8692 print "Error reading rrd:\n$e\n"; 8693 return; 8694 } 8695 if($archivetime and $uselastupdate > 1 ) { 8696 @opts = ( $rrd, "AVERAGE", "-e", $archivetime, "-s", "end".$startpoint ); 8697 } else { 8698 @opts = ( $rrd, "AVERAGE", "-e", $lastupdate, "-s", "end".$startpoint ); 8699 } 8700 } else { 8701 @opts = ( $rrd, "AVERAGE", "-s", $startpoint ); 8702 } 8703 8704 # Fetch data 8705 ( $start, $step, $names, $data ) = RRDs::fetch( @opts,@rrdcached ); 8706 if( !$start or !$data ) { 8707 $e = RRDs::error(); 8708 print "Error retrieving data - do you have enough stored?\n"; 8709 print "Check that you have enough real data gathered to be able to export.\n"; 8710 print "$e\n"; 8711 return; 8712 } 8713 if( $gtype !~ /6/ ) { 8714 $opts[1] = 'MAX'; 8715 ( $mstart, $mstep, $mnames, $maxdata ) = RRDs::fetch( @opts,@rrdcached ); 8716 # maxdata may now be null, if we dont have a MAX RRA available. 8717 } else { 8718 $maxdata = 0; # 6-hour graphs never have MAX available. 8719 } 8720 8721 # Print data 8722 foreach $line ( @$data ) { 8723 @dat = localtime $start; 8724 $d = sprintf "%04d/%02d/%02d",($dat[5]+1900),($dat[4]+1),$dat[3]; 8725 $t = sprintf "%02d:%02d",$dat[2],$dat[1]; # hh:mm 8726 print "\"$r\"$comma\"$i\"$comma$d$comma$t$comma$start"; 8727 if($interfaces{$thisif}{aspercent} ) { 8728 printf "$comma%12.4f", ($$line[0]*$interfaces{$thisif}{mult}) 8729 if(!$interfaces{$thisif}{noi}); 8730 printf "$comma%12.4f", ($$line[1]*$interfaces{$thisif}{mult}) 8731 if(!$interfaces{$thisif}{noo}); 8732 printf "$comma%12.4f", 100.0*($$line[0]/$interfaces{$thisif}{max}) 8733 if(!$interfaces{$thisif}{noi}); 8734 printf "$comma%12.4f", 100.0*($$line[1]/$interfaces{$thisif}{max}) 8735 if(!$interfaces{$thisif}{noo}); 8736 } elsif( $interfaces{$thisif}{dorelpercent}) { 8737 printf "$comma%12.4f", ($$line[0]*$interfaces{$thisif}{mult}); 8738 printf "$comma%12.4f", ($$line[1]*$interfaces{$thisif}{mult}); 8739 printf "$comma%12.4f", 100.0*($$line[0]/$$line[1]); 8740 } else { 8741 printf "$comma%12.4f", ($$line[0]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8742 if(!$interfaces{$thisif}{noi}); 8743 printf "$comma%12.4f", ($$line[1]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8744 if(!$interfaces{$thisif}{noo}); 8745 } 8746 if($gtype !~ /6/) { 8747 if($maxdata) { 8748 $mline = shift @$maxdata; 8749 $mline = [ 0,0 ] if(!$mline); # in case data runs out 8750 if($interfaces{$thisif}{aspercent} ) { 8751 printf "$comma%12.4f", ($$mline[0]*$interfaces{$thisif}{mult}) 8752 if(!$interfaces{$thisif}{noi}); 8753 printf "$comma%12.4f", ($$mline[1]*$interfaces{$thisif}{mult}) 8754 if(!$interfaces{$thisif}{noo}); 8755 printf "$comma%12.4f", 100.0*($$mline[0]/$interfaces{$thisif}{max}) 8756 if(!$interfaces{$thisif}{noi}); 8757 printf "$comma%12.4f", 100.0*($$mline[1]/$interfaces{$thisif}{max}) 8758 if(!$interfaces{$thisif}{noo}); 8759 } elsif( $interfaces{$thisif}{dorelpercent}) { 8760 printf "$comma%12.4f", ($$mline[0]*$interfaces{$thisif}{mult}); 8761 printf "$comma%12.4f", ($$mline[1]*$interfaces{$thisif}{mult}); 8762 printf "$comma%12.4f", 100.0*($$mline[0]/$$mline[1]); 8763 } else { 8764 printf "$comma%12.4f", ($$mline[0]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8765 if(!$interfaces{$thisif}{noi}); 8766 printf "$comma%12.4f", ($$mline[1]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8767 if(!$interfaces{$thisif}{noo}); 8768 } 8769 } else { 8770 printf "$comma%12.4f", ($$line[0]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8771 if(!$interfaces{$thisif}{noi}); 8772 printf "$comma%12.4f", ($$line[1]*$interfaces{$thisif}{mult}*$interfaces{$thisif}{factor}) 8773 if(!$interfaces{$thisif}{noo}); 8774 if($interfaces{$thisif}{aspercent}) { 8775 printf "$comma%12.4f", 100.0*($$line[0]/$interfaces{$thisif}{max}) 8776 if(!$interfaces{$thisif}{noi}); 8777 printf "$comma%12.4f", 100.0*($$line[1]/$interfaces{$thisif}{max}) 8778 if(!$interfaces{$thisif}{noo}); 8779 } # aspercent 8780 } # maxdata exists 8781 } # not 6 8782 printf "\r\n"; 8783 $start += $step; 8784 } # foreachline 8785 8786 } # next interface in list 8787 8788} 8789############################################################################ 8790# Help page 8791 8792sub do_help() 8793{ 8794 my($vurl,$iurl); 8795 my($javascript); 8796 8797 $javascript = make_javascript({if=>"__none",rtr=>"none"}); 8798 8799 start_html_ss({-script => $javascript, -onload => "LoadMenu()", 8800 -class=>'help' }); 8801 8802 $vurl = "$meurlfull?page=verify&rtr=".$q->escape($router); 8803 $iurl = $config{'routers.cgi-smalliconurl'}; 8804 8805 print $q->h1(langmsg(3006,"Information and Help")); 8806 8807 print <<EOT 8808<h2>Updates and support</h2> 8809Updates to the routers.cgi script may be obtained from 8810<a href=$APPURL>$APPURL</a>. During development phases there may be daily 8811updates, so check every so often. Support is available via the 8812<a href=$FURL>support forum</a>, 8813<a href=$MLURL>mailing list</a> and 8814directly - check <a href=$APPURL>this link</a> for more details. 8815<HR> 8816<h2>Publications</h2> 8817The new MRTG/RRD/Routers2 book, 8818<a href=$BURL target=_top>Using MRTG with RRDtool and Routers2</a>, can be 8819obtained in dead-tree format from <A HREF=$BURL target=_top>here</a>. 8820This should be able to help you to make the most of your MRTG installation, 8821and also help with any installation and configuration problems! 8822<hr> 8823<h2>Online help</h2> 8824<UL> 8825<li>Diagnose configuration problems 8826<a target=_new href=$vurl>here</a> (opens new window)</li> 8827<li>Show available link icons 8828<a target=_new href=$iurl>here</a> (opens new window)</li> 8829</UL> 8830<hr> 8831<h2>Credits</h2> 8832Thanks to the following people for supporting the development of 8833this software by <a target=_new href=$WLURL > 8834sending me a gift</a> on my Wishlist! 8835All listed in no particular order, in case you were wondering. 8836<UL> 8837<LI>Pall Wiberg Joensen, Faroese Telecom, Faroe Islands</li> 8838<li>Ben Higgins, Dovetail Internet, USA</li> 8839<li>Mike Bernhardt, Arsin, USA</li> 8840<li>EDS Europe</li> 8841<li>Ruedi Kehl, Manor AG, Switzerland (twice!)</li> 8842<li>Allied Domecq, UK</li> 8843<li>Rob</li> 8844<li>Peter Cohen, Telia, USA</li> 8845<li>Jay Christopherson</li> 8846<li>David Hares, Network One</li> 8847<li>Reuben Farrelly, Netfilter, Australia</li> 8848<li>Network Operations, Roche Diagnostics GmbH, Germany</li> 8849<li>Keith Johnson, UK</li> 8850<li>J Herrera, Brown Publishing</LI> 8851<li>Kristin Gorman, New York, USA</li> 8852<li>Inigo T Storm, ASV AG, Hamburg, Germany</li> 8853<li>M Williams, London, UK</li> 8854<li>Joseph Truong, USA</li> 8855<LI>Babul Mukherjee, The Montopolis Group, San Antonio, USA</li> 8856<li>Matevz Turk, Slovenia</li> 8857<li>Barry Basselgia; the most generous contributor so far</li> 8858<li>Gary Higgs</li> 8859<li>Scott Monk, USA</li> 8860<li>Robert Gibson, Texas, USA</li> 8861<li>Andrew McClure, Santa Barbara, USA</li> 8862<li>Innokentiy Georgeievskiy, Moscow, Russia (Twice!)</li> 8863<li>Kirsten Johnson</li> 8864<li>Matti Wiersmuller, Switzerland</li> 8865<li>University of Auckland, New Zealand</li> 8866<li>Steven Hay, Alberta, Canada.</li> 8867<LI>Dan Lowry, Scituate, USA</li> 8868<LI>Alan Dean, Prospect, USA</li> 8869<LI>Thomas Thong, Alameda, USA</li> 8870<LI>Steve McDonald, Indiana, USA</li> 8871<LI>Harry Edmondson, USA</li> 8872<LI>Saul Herbert/Hugh David, ADV Films, UK and Australia</li> 8873<li>Francesco Duranti, Kuwait Petroleum Italia</li> 8874<li>Herman Poon, Ontario, Canada</li> 8875<li>Peter Hall, Texas, USA</li> 8876<li>Casey Scott, F5 Networks, USA</li> 8877<li>Steve Litchfield, Georgia, USA</li> 8878<li>Rodrigo Schneider</li> 8879<li>Christopher Noyes, CT, USA</li> 8880<li>GroundWork Open Systems, USA</li> 8881<li>Ask.com, USA</li> 8882<li>Andrew Lewis</li> 8883<li>Yuriy Vlasov</li> 8884<li>Scott Neader</li> 8885<LI>Dave Diamond, USA</LI> 8886<LI>Timothy Graham</li> 8887<LI>Matthew Elmore, AL, USA</LI> 8888<li>Plus various generous but anonymous people</li> 8889 8890</ul> 8891V2.0 Beta testers: 8892<UL> 8893<li>Garry Cook, MacTec Inc.</li> 8894<li>Ed Stalnaker, Rollins Corp, USA</li> 8895<li>Francesco Duranti, Kuwait Petroleum Italia</li> 8896<li>Neil Pike, Protech Computing</li> 8897<li>Brian Wilson, North Carolina State University</li> 8898<li>Martijn Koopsen, Energis NL</li> 8899</UL> 8900Contributors: 8901<UL> 8902<li>Ed Stalnaker (modified cfgmaker script)</li> 8903<li>Brian Wilson, Garry Cook, Aid Arslanagic, Andy Jezierski, Leo Artnts, James Keane, Todd Wiese, Jim Harbin (alternative icon sets)</li> 8904<li>Many other people for suggestions and bug reports.</li> 8905</UL> 8906Additional thanks to all the other people who have assisted by sending in 8907bug reports and suggestions for improvement. Also, major thanks to 8908Tobi Oetiker, the author of <a href=http://www.mrtg.org/ target=_new>MRTG</a> 8909and <a href=http://www.rrdtool.org/ target=_new>RRDTool</a>, without whom 8910this interface would never have been created. 8911<hr> 8912<h2>Legal Jargon</h2> 8913This software is available under the GNU GPL. More information is available 8914in the text files accompanying this software, or on the web site. Please note 8915that this software is provided without any warranty, or guarantee, and you 8916use it at your own risk. In no event shall myself, my employers, or the 8917owner of any 8918web site distributing this software, be held liable for any loss or damage 8919caused as a result of the use or misuse of this software or the instructions 8920that accompany it. 8921<p> 8922EOT 8923; 8924 do_footer(); 8925} 8926 8927# set cookies etc. for defaults. 8928# the way we do this is by refreshing ourself with extra parameters. 8929# The existence of the extra parameters causes the cookie to be set. 8930sub do_config() 8931{ 8932 my ( $javascript, %routerdesc, $k ); 8933 my (%langs,$langfile,$langdir,$cc); 8934 my ($explore); 8935 8936 $javascript = make_javascript({if=>"__none",rtr=>"none"}); 8937 8938 start_html_ss({-script => $javascript, -onload => "LoadMenu()", 8939 -class=>'config' }); 8940 print $q->h2(langmsg(3007,"Personal Preferences")),"\n"; 8941 8942 $explore = 'y'; 8943 $explore = $config{'routers.cgi-allowexplore'} 8944 if( defined $config{'routers.cgi-allowexplore'} ); 8945 8946 if( $q->param('xset') ) { 8947 print $q->p($q->b(langmsg(9005,"Options have been saved."))),"\n"; 8948 } 8949 8950 # Load language definitions 8951 %langs = (); 8952 $langs{''} = langmsg(3008,"No Preference"); 8953 if(defined $config{'web-langdir'}) { $langdir = $config{'web-langdir'} ; } 8954 else { $langdir = dirname($conffile); } 8955 foreach $langfile ( glob( $langdir.$pathsep."lang_*.conf" ) ) { 8956 if( -r $langfile and $langfile =~ /lang_(.+)\.conf/ ) { 8957 $cc = $1; 8958 open LANG,"<$langfile"; 8959 while ( <LANG> ) { 8960 chomp; 8961 if( /^\s*description\s*=\s*(.*)/ ) { $langs{$cc} = $1; last; } 8962 } 8963 close LANG; 8964 } 8965 } 8966 8967 # Load routers definitions 8968 foreach ( keys %routers ) { $routerdesc{$_} = $routers{$_}{desc}; } 8969 $routerdesc{''} = langmsg(3008,"No preference"); 8970 8971 if($config{'routers.cgi-6hour'} =~ /y/i ) { 8972 @gorder = ( '6', @gorder ) if($gorder[0] ne "6"); 8973 } 8974 8975 print $q->p(langmsg(3107,"Options set here will persist over future invocations of this script. Note that this uses cookies, so you must have them enabled.")); 8976 8977 print $q->hr; 8978 print "<FORM METHOD=GET ACTION=$meurlfull>\n"; 8979 8980# now a couple of hidden fields to preserve mtype and page 8981 print $q->hidden({ name=>"page", value=>"config", -override=>1 }),"\n", 8982 $q->hidden({ name=>"xmtype", value=>$mtype, -override=>1 }) ,"\n", 8983 $q->hidden({ name=>"xset", value=>"yes" }) ,"\n"; 8984 8985# Now the main fields, defrouter and defgtype. Dropdown lists. In a table. 8986 8987 $defgstyle = $q->cookie('gstyle'); 8988 $defgstyle = 'n' if(!$defgstyle); 8989 8990 print $q->table( { -border=>0 }, 8991 (( $explore =~ /[1y]/i )? 8992 $q->Tr( { -border=>"0", align=>"left" } , 8993 $q->td(langmsg(3100,"Default device:") )."\n", $q->td( 8994 $q->popup_menu( {name=>"defrouter", 8995 values=>["",sort bydesc keys(%routers)], 8996 labels=>{%routerdesc}, default=>$q->cookie('router')}) 8997 )."\n" 8998 ):""), 8999 (( $explore =~ /[1yi]/i )? 9000 $q->Tr( { -border=>"0", align=>"left" } , 9001 $q->td(langmsg(3101,"Default target/interface:") )."\n", $q->td( 9002 $q->popup_menu({ name=>"defif", values=>["", 9003 "__first", 9004 "__interface","__cpu","__memory","__summary", 9005 "__compact", "__incoming","__outgoing","__info", 9006 "__userdef" ], 9007 labels=>{__first=>langmsg(3012,"First target"), 9008 __summary=>langmsg(3013,"Summary page"), 9009 __info=>langmsg(3021,"Info Page"), 9010 __cpu=>langmsg(3016,"CPU performance"), 9011 __memory=>langmsg(3017,"Memory Usage"), 9012 __userdef=>langmsg(3018,"First user graph"), 9013 __interface=>langmsg(3019,"First Interface target"), 9014 __incoming=>langmsg(3014,"Incoming Graph"), 9015 __outgoing=>langmsg(3015,"Outgoing graph"), 9016 __compact=>langmsg(3020,"Compact Summary"), 9017 ""=>langmsg(3008,"No preference") }, 9018 default=>$q->cookie('if') }) 9019 )."\n" 9020 ):""), 9021 $q->Tr( { -border=>"0", align=>"left" } , 9022 $q->td(langmsg(3102,"Default graph type:") )."\n", $q->td( 9023 $q->popup_menu({ name=>"defgtype", values=>[@gorder], 9024 labels=>{%gtypes}, default=>$q->cookie('gtype') }) 9025 )."\n" 9026 ), 9027 $q->Tr( { -border=>"0", align=>"left" } , 9028 $q->td(langmsg(3103,"Default graph style:") )."\n", $q->td( 9029 $q->popup_menu({ name=>"defgstyle", values=>[@sorder], 9030 labels=>{%gstyles}, default=>"$defgstyle" }) 9031 )."\n" 9032 ), 9033 $q->Tr( { -border=>"0", align=>"left" } , 9034 $q->td(langmsg(3106,"Default language:") )."\n", $q->td( 9035 $q->popup_menu({ name=>"deflang", values=>[sort keys %langs], 9036 labels=>{%langs}, default=>"$language" }) 9037 )."\n" 9038 ), 9039 $q->Tr( { align=>"left" }, 9040 $q->td(""),$q->td( 9041 $q->submit({ name=>"Submit", value=>langmsg(3104,"Set Defaults") }) 9042 )."\n" 9043 ) 9044 ),"\n"; 9045 9046 print "</FORM>"; 9047 9048 print $q->br({clear=>"BOTH"}),"\n"; 9049 9050 print $q->center($q->b($q->a({target=>"_top",href=>$meurlfull}, 9051 langmsg(3105,"Go to the current default page")))).$q->br,"\n"; 9052 9053 do_footer(); 9054} 9055 9056########################### 9057# Show an archive graph. 9058 9059sub do_archive($) 9060{ 9061 my( $javascript, $thisgraph, $thisgraphurl ); 9062 my( $inhtml ) = $_[0]; 9063 9064 $javascript = make_javascript({archive=>$archive}); 9065 9066 if($inhtml) { 9067 start_html_ss({ -script => $javascript, -onload => "LoadMenu()" , 9068# -class=>($interfaces{$interface}{mode}?$interfaces{$interface}{mode}:'archive') 9069 -class=>'archive' 9070 }, $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); 9071 } 9072 9073 $thisgraphurl = $router; $thisgraphurl =~ s/[\?#\\\/]//g; 9074 $thisgraph = $thisgraphurl; 9075 $thisgraph = $config{'routers.cgi-graphpath'}.$pathsep.$thisgraph 9076 .$pathsep.$interface.$pathsep.$archive; 9077 $thisgraphurl = $config{'routers.cgi-graphurl'}.'/'.$thisgraphurl 9078 .'/'.$interface.'/'.$archive; 9079 9080 if($inhtml) { 9081 print $q->h2({class=>'archive'},langmsg(3009,"Archive graph")); 9082 # any defined pagetop stuff 9083 print "<DIV class=pagetop>"; 9084 print expandvars($config{'routers.cgi-pagetop'}),"\n" 9085 if( defined $config{'routers.cgi-pagetop'} ); 9086 if( defined $config{'routers.cgi-mrtgpagetop'} 9087 and $config{'routers.cgi-mrtgpagetop'} =~ /y/i 9088 and $interfaces{$interface}{pagetop} 9089 and !$interfaces{$interface}{usergraph} ) { 9090 print expandvars($interfaces{$interface}{pagetop}),"\n"; 9091 } 9092 print "</DIV>"; 9093 } 9094 9095 if( -f $thisgraph ) { 9096 if($inhtml) { 9097 print $q->img({ src=>$thisgraphurl, alt=>$archive }).$q->br."\n"; 9098 } else { 9099 #output the graph in binmode XXX 9100 } 9101 } else { 9102 if($inhtml) { 9103 print $q->p($q->b(langmsg(3010,"This graph has been deleted.")))."\n"; 9104 } else { 9105 # redirect to error 9106 if($opt_I) { 9107 print "Error: This graph has been deleted.\n"; 9108 } else { 9109 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 9110 } 9111 return; 9112 } 9113 } 9114 9115 if( $inhtml and $archive =~ /(\d+)-(\d+)-(\d+)-(\d+)-(\d+)-([dwmys6]+)\./ ) { 9116 # try to get local formatting 9117 my( $dformat ) = "%c"; 9118 $dformat = $config{'web-dateonlyformat'} 9119 if(defined $config{'web-dateonlyformat'}); 9120 $dformat = $config{'web-shortdateformat'} 9121 if(defined $config{'web-shortdateformat'}); 9122 if(!$dformat) { 9123 print $q->br, $q->p(langmsg(3200,"Archive time").": $4:$5 $3/$2/$1 (" 9124 .$gtypes{$6}.")"); 9125 } else { 9126 print $q->br, $q->p(langmsg(3200,"Archive time").": " 9127 .POSIX::strftime($dformat,0,$5,$4,$3,($2-1),($1-1900)) 9128 ." (".$gtypes{$6}.")"); 9129 } 9130 } 9131 if($inhtml) { 9132 print $q->br."<DIV class=pagefoot>"; 9133 if( defined $config{'routers.cgi-mrtgpagefoot'} 9134 and $config{'routers.cgi-mrtgpagefoot'} =~ /y/ 9135 and $interfaces{$interface}{pagefoot} 9136 and !$interfaces{$interface}{usergraph} ) { 9137 print expandvars($interfaces{$interface}{pagefoot}),"\n"; 9138 } 9139 print expandvars($config{'routers.cgi-pagefoot'}),"\n" 9140 if( defined $config{'routers.cgi-pagefoot'} ); 9141 print "</DIV>"; 9142 9143 print "<DIV class=icons>"; 9144 print $q->hr."\n"; 9145# print $q->a({href=>"javascript:parent.makearchmark('" 9146# .$q->escape($router)."','".$q->escape($interface) 9147# ."','".$q->escape($extra)."','$archive')"}, 9148 print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", xmtype=>"", 9149 archive=>"$archive", xgtype=>"", xgstyle=>""}), target=>"_top"}, 9150 $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", 9151 alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20})),"\n"; 9152 9153 # only for Yes, not for Read 9154 if( $config{'routers.cgi-archive'} =~ /y/i ) { 9155 print $q->a( { href=>$meurlfull.'?'.optionstring({archive=>$archive, 9156 page=>'graph',delete=>1}) }, 9157 $q->img({ border=>0, alt=>langmsg(5022,"Delete this graph"), width=>100, height=>20, 9158 src=>$config{'routers.cgi-iconurl'}."delete.gif" })).$q->br; 9159 } 9160 print "</DIV>"; 9161 do_footer(); 9162 } # inhtml 9163} 9164 9165########################### 9166# Verification of everything. 9167# This is more a debug utility, really. We display all the routers and 9168# interfaces, also the available icons and check the sanity of the 9169# routers.conf, and the graph directory. 9170 9171sub yesno($) 9172{ 9173 if(!$_[0]) { print $q->td({bgcolor=>"#ff0000",align=>"center",class=>"no"},"No"); } 9174 else { print $q->td({bgcolor=>"#00ff00",align=>"center",class=>"yes"},"Yes"); } 9175} 9176sub do_verify() 9177{ 9178 my($server,$iconpath, $ipath, $confpath, $iconurl,$graphpath, $graphurl); 9179 my($curif, $key, $rtr); 9180 my($testfile, $okfile); 9181 my($username) = ""; 9182 my($e,$rrdok, $rrdinfo); 9183 my($archroot,@days,$rrdfilename); 9184 my($s)=""; 9185 9186 $server = "localhost"; 9187 $server = $2 if($meurl =~ /http(s?):\/\/([\w\.\-]+)\//); 9188 $s = "s" if($1); 9189 $confpath = $config{'routers.cgi-confpath'}; 9190 $graphpath = $config{'routers.cgi-graphpath'}; 9191 $graphurl = $config{'routers.cgi-graphurl'}; 9192 $iconurl = $config{'routers.cgi-smalliconurl'}; 9193 $ipath = $iconurl; $ipath =~ s#/#\\#g if($NT); 9194 $iconpath = $graphpath.$pathsep."..".$ipath; 9195 $iconpath = $graphpath.$pathsep."..".$pathsep."..".$ipath 9196 if(!-d $iconpath); 9197 $iconpath = "" if(!-d $iconpath); 9198 $username = $q->remote_user if($q->remote_user); 9199 9200 start_html_ss({-title=>langmsg(3011,"Configuration Verification"), 9201 -class=>'verify'}); 9202 9203 print $q->h1(langmsg(3011,"Configuration Verification")); 9204 print $q->ul( 9205 $q->li($q->a({href=>"#conf"},"Check routers.conf")), 9206 $q->li($q->a({href=>"#files"},"Check MRTG files")), 9207 $q->li($q->a({href=>"#targets"},"Check MRTG targets")), 9208 $q->li($q->a({href=>"#icons"},"Check available icons")), 9209 $q->li($q->a({href=>"#settings"},"Configuration settings")) 9210 ).$q->hr."\n"; 9211 9212 print $q->a({name=>"conf"},$q->h2("routers.conf check"))."\n"; 9213 print $q->p("This will check a number of the more critical definitions in the routers.conf file, and will give you any warnings for items that are a worry.")."\n"; 9214 print "<TABLE align=center border=1 class=verify>\n"; 9215 print "<TR><TD>Script name</TD><TD>$myname (Version $VERSION)</TD></TR>\n"; 9216 print "<TR><TD>Configuration file<br>$conffile</TD>\n"; 9217 if( -r $conffile ) { print "<TD>Exists and is readble</TD></TR>\n"; } 9218 else { print "<TD background=#ff0000>Unable to read file</TD></TR>\n"; } 9219 print "<TR><TD>Authenticated username</TD><TD>$username</TD></TR>\n" 9220 if($username); 9221 print "<TR><TD>Graphs path<br>$graphpath</TD>\n"; 9222 if( -d $graphpath ) { 9223 $testfile = $graphpath.$pathsep 9224 ."verylongfilename-------------testfile.png"; 9225 if( open TEST, ">$testfile" ) { 9226 print "<TD>Directory exists and is writeable</TD></TR>\n"; 9227 close TEST; 9228 unlink $testfile; 9229 } else { 9230 print "<TD background=#ff0000>Unable to create files in directory!</TD></TR>\n"; 9231 } 9232 } else { 9233 print "<TD background=#ff0000>Directory does not exist!</TD></TR>\n"; 9234 } 9235 print "<TR><TD>Graph URL<br>$graphurl</TD>\n"; 9236 $testfile = $graphpath.$pathsep."redsquare.png"; 9237 unlink $testfile if( -f $testfile ); 9238 if( open GRAPH, ">$testfile" ) { 9239 binmode GRAPH; 9240 # this generates a PNG of a red square. 9241 print GRAPH 9242"\211PNG\r\n\032\n\0\0\0\rIHDR\0\0\0\017\0\0\0\017\001\003\0\0\0\001\030" 9243."\a\t\0\0\0\003PLTE\377\0\0\031\342\t7\0\0\0\fIDATx\234c` \001\0\0\0-\0" 9244."\001\305\327\300\206\0\0\0\0IEND\256B`\202"; 9245 close GRAPH; 9246 print "<TD>This should show a red square -->" 9247 .$q->img({src=>$graphurl."/redsquare.png",alt=>"Red Square", 9248 width=>15,height=>15}) 9249 ."<--<br>\n"; 9250 print "If it doesn't, then your graphurl does not match your graphpath.</TD></TR>\n"; 9251 } else { 9252 print "<TD background=#ff0000>Unable to create test file!<br>Check your graphpath setting above.</TD></TR>\n"; 9253 } 9254 9255 print "<TR><TD>Icon URL<br>$iconurl</TD><TD>\n"; 9256 print "This should show a target -->" 9257 .$q->img({src=>$iconurl."target-sm.gif",width=>15, height=>15}) 9258 ."<--<br>\n" 9259 ."If it doesn't, then there is a problem.</td></tr>\n"; 9260 print "<TR><TD>MRTG files<br>Path: ".$confpath 9261 .$q->br."Files: ".$config{'routers.cgi-cfgfiles'}."</TD>\n"; 9262 if( @cfgfiles ) { 9263 print "<TD>".($#cfgfiles + 1)." files detected OK."; 9264 } else { 9265 if(!-d $confpath) { 9266 print "<TD gcolor=#ff0000>Directory does not exist or is not readable!"; 9267 } else { 9268 print "<TD gcolor=#ff0000>No files found that match this pattern!"; 9269 } 9270 } 9271 print "</TD></TR>\n"; 9272 print "<TR><TD>Perl libraries<br>RRDs, GD</TD><TD>\n"; 9273 eval { require RRDs; }; 9274 if($@) { 9275 print $q->b("RRDs library NOT FOUND.")." This may however not be a problem if the library path is amended by the <b>LibAdd</b> birective in the MRTG files.".$q->br; 9276 print $@.$q->br; 9277 $rrdok = 0; 9278 } else { 9279 my($v); 9280 # RRDTool v1.0.x reported version as 1.000xx for 1.0.xx 9281 # RRDTool v1.{2,3,4}.x report version as 1.abbb for 1.a.bbb 9282 $RRDs::VERSION =~ /(\d+)\.(\d)(\d+)/ ; 9283 $v = "$1.".($2 + 0).".".($3 + 0); 9284 print "RRDs library found OK (Version $v)<br>"; 9285 print "You should upgrade to at least v1.0.36 to avoid problems.<BR>" 9286 if($RRDs::VERSION < 1.00036); 9287 $rrdok = 1 9288 if($RRDs::VERSION < 1.00036); 9289 } 9290 if( $config{'routers.cgi-stylesheet'} ) { 9291 print "GD library not required as operating in StyleSheet mode<BR>\n"; 9292 } elsif( $config{'routers.cgi-compact'} =~ /n/i ) { 9293 print "GD library not required as compact is disabled in routers.conf<BR>\n"; 9294 } else { 9295 eval { require GD; }; 9296 if($@) { 9297 print $q->b("GD library NOT FOUND.")." This would not be a problem if you had compact=no in the routers.conf.".$q->br; 9298 print $@; 9299 } else { 9300 print "GD library found OK"; 9301 my $gd = new GD::Image(1,1); 9302 eval { print ": Ver ".$GD::VERSION."<BR>"; }; 9303 eval { # must eval because old versions dont have 'can' or VERSION 9304 if( $gd->can('png') ) { print "- PNG Supported<BR>"; } 9305 else { print "- PNG NOT supported<BR>"; } 9306 if( $gd->can('gif') ) { print "- GIF Supported<BR>"; } 9307 else { print "- GIF NOT supported<BR>"; } 9308 if( $config{'web-png'} and !$gd->can('png')) { 9309 print "WARNING: You have PNG enabled in the routers2.conf but your GD does not support it!<BR>"; 9310 } 9311 if( !$config{'web-png'} and !$gd->can('gif')) { 9312 print "WARNING: You do not have PNG enabled in the routers2.conf but your GD does not support GIFs!<BR>"; 9313 } 9314 }; 9315 } 9316 } 9317 if( $config{'web-rrdcached'} or $ENV{RRDCACHED_ADDRESS} ) { 9318 print "Config file sets rrdcached options to ".$config{'web-rrdcached'}."<BR>" if($config{'web-rrdcached'}); 9319 print "Environment sets rrdcached options to ".$ENV{RRDCACHED_ADDRESS}."<BR>" if($ENV{RRDCACHED_ADDRESS}); 9320 if( $RRDs::VERSION < 1.4 ) { 9321 print "You cannot use rrdcached with this version of the RRD library!<BR>\n"; 9322 } elsif( $RRDs::VERSION < 1.4999 ) { 9323 print "You cannot ONLY use rrdcached with UNIX sockets with this version of the RRD library!<BR>\n"; 9324 } 9325 9326 } 9327 print "</TD></TR><TR><TD>Routingtable extensions</TD><TD>"; 9328 if(defined $config{'routers.cgi-routingtableurl'}) { 9329 eval { require Net::SNMP; }; 9330 if($@) { 9331 print $q->b("Net::SNMP library NOT FOUND.")." This means that the routingtable extensions will NOT WORK. You should therefore either install this package, or disable the extensions in the routers.conf.".$q->br; 9332 print $@; 9333 } else { 9334 print "Net::SNMP library found OK and extensions are enabled."; 9335 } 9336 } else { 9337 print "Routing table extensions are not enabled."; 9338 } 9339 print "</TD></TR></TABLE>\n"; 9340 9341 print $q->hr.$q->a({name=>"files"},$q->h2("MRTG files check"))."\n"; 9342 print $q->p("There files are taken from the <b>cfgpath</b> and <b>cfgfiles</b> directives in the <b>[routers.cgi]</b> section of the routers.conf file. If no files are listed below, then you should check that these definitions are correct."); 9343 print "confpath = ".$q->code($confpath).$q->br."\n"; 9344 print "cfgfiles = ".$q->code($config{'routers.cgi-cfgfiles'}).$q->br."\n"; 9345 9346 print $q->br."<TABLE align=center border=1 class=verify>\n"; 9347 print "<TR><TD>MRTG file name</td><td>Description</td><td>Visible</td><td>Valid</td><td>Notes</td></tr>\n"; 9348 foreach $rtr ( keys %routers ) { 9349 print "<TR><TD>"; 9350 print $q->img({src=>$iconurl.$routers{$rtr}{icon},width=>15, height=>15})." " if(defined $routers{$rtr}{icon}); 9351 print $q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($rtr))},$rtr); 9352 9353 if( $rtr !~ /^#/ ) { 9354 $okfile = $confpath.$pathsep.$rtr; 9355 $okfile =~ s/\.conf$/.ok/; $okfile =~ s/\.cfg$/.ok/; 9356 print "<BR><B><font color=#ff0000>No .ok file found</font></b><br>\n" 9357 ."Have you successfully run MRTG on this file yet?" 9358 if(!-f $okfile); 9359 } 9360 print "</TD><TD>".$routers{$rtr}{shdesc}."</TD>"; 9361 yesno $routers{$rtr}{inmenu}; 9362 yesno $routers{$rtr}{hastarget}; 9363 print "<TD><TABLE border=0>"; 9364 print "<TR><TD>Group:</TD><TD>".$routers{$rtr}{group}."</TD></TR>" 9365 if($routers{$rtr}{group}); 9366 print "<TR><TD>Server:</TD><TD>".$routers{$rtr}{server}."</TD></TR>" 9367 if($routers{$rtr}{server}); 9368 print "<TR><TD>Hostname:</TD><TD>".$routers{$rtr}{hostname}."</TD></TR>" 9369 if($routers{$rtr}{hostname}); 9370 print "</TABLE></TD></TR>\n"; 9371 } 9372 print "</TABLE>"; 9373 9374 print $q->hr.$q->a({name=>"targets"},$q->h2("MRTG targets check"))."\n"; 9375 print "Current device: ".$q->b($router)." (".$routers{$router}{desc}.")".$q->br."\n"; 9376 print "MRTG file: ".$q->code($routers{$router}{file}).$q->br."\n" 9377 if($routers{$router}{file}); 9378 print $q->p("These targets are read from the MRTG file, and then displayed according to how they are interpreted."); 9379 print "<BR><TABLE border=1 align=center>\n"; 9380 print "<TR><TD>Target<br>RRD File</TD><TD>Mode</TD><TD>In Menu</TD><TD>In Summary</TD><TD>In/Out</TD><TD>In Compact</TD><TD>Archives</TD><TD>Notes</TD></TR>\n"; 9381 foreach $curif ( keys %interfaces ) { 9382 next if($interfaces{$curif}{usergraph}); 9383 print "<TR><TD>"; 9384 print $q->img({src=>$iconurl.$interfaces{$curif}{icon},width=>15, height=>15})." " if(defined $interfaces{$curif}{icon}); 9385 print "$curif<br>".$interfaces{$curif}{rrd}; 9386 if(!$rrdcached and !-r $interfaces{$curif}{rrd}) { 9387 print "<BR><B><font color=#ff0000>Unable to read RRD file!</font></B>" 9388 } 9389 print "</TD><TD>".$interfaces{$curif}{mode}."</TD>"; 9390 yesno $interfaces{$curif}{inmenu}; 9391 yesno $interfaces{$curif}{insummary}; 9392 yesno $interfaces{$curif}{inout}; 9393 yesno $interfaces{$curif}{incompact}; 9394 print "<TD>"; 9395 @days = (); 9396 if(defined $interfaces{$curif}{origrrd}) { 9397 $rrdfilename = $interfaces{$curif}{origrrd}; 9398 } else { 9399 $rrdfilename = $interfaces{$curif}{rrd}; 9400 } 9401 if($rrdfilename) { 9402 $archroot = dirname($rrdfilename).$pathsep.'archive'; 9403 $rrdfilename = basename($rrdfilename); 9404 if( defined $cachedays{$rrdfilename} ) { 9405 @days = @{$cachedays{$rrdfilename}}; 9406 $debugmessage .= "fromcache(dates:$rrdfilename)\n"; 9407 } else { 9408 foreach ( sort rev findarch( $archroot,$rrdfilename ) ) { 9409 if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { 9410 push @days, "$1$2-$3-$4"; } 9411 } 9412 $cachedays{$rrdfilename} = [ @days ]; # Cache for later 9413 $debugmessage .= "cached[dates:$rrdfilename]\n"; 9414 } 9415 print ( $#days + 1 ); 9416 print " from ".$days[$#days] if($#days > -1); 9417 } else { 9418 print "N/A"; 9419 } 9420 print "</TD><TD>"; 9421 if($rrdok and -r $interfaces{$curif}{rrd}) { 9422 $rrdinfo = RRDs::info($interfaces{$curif}{rrd},@rrdcached); 9423 $e = RRDs::error(); 9424 if(defined $rrdinfo and !$e) { 9425 print "RRD file format is legal."; 9426 print "<BR>Interval ".($rrdinfo->{step}/60) 9427 ." minute(s)" if($rrdinfo->{step} != 300); 9428 print "<BR><B>Not in MRTG format!</B>" 9429 if(!defined $rrdinfo->{"ds[ds0].type"}); 9430 print "<BR>Extended timeframe" 9431 if($rrdinfo->{"rra[0].rows"} > 799); 9432 } else { 9433 print $q->b("Error reading rrd:").$q->br.$e; 9434 } 9435 } else { print "N/A"; } 9436 print "</TD>\n"; 9437 } 9438 print "</TABLE>\n"; 9439 9440 print $q->hr.$q->a({name=>"icons"},$q->h2("Available Icons"))."\n"; 9441 print "The available icons should be located in the <b>rrdicons</b> directory, currently defined to be:".$q->br."\n"; 9442 print "URL: ".$q->code("http$s://$server".$config{'routers.cgi-smalliconurl'}).$q->br; 9443 print "If the menu page is installed, you can get to it " 9444 .$q->a({href=>$config{'routers.cgi-smalliconurl'}},"here").".".$q->br."\n"; 9445 if($iconpath and -d $iconpath ) { 9446 # show available icons in here 9447 my( $c ) = 0; my($f,$b); 9448 print $q->br."<TABLE border=1 align=center>\n<TR>"; 9449 foreach $f ( glob( $iconpath.$pathsep."*-sm.gif" ) ) { 9450 $b = basename $f; 9451 $c++; 9452 if($c eq 5) { $c = 1; print "</TR>\n<TR>"; } 9453 if( -r $f ) { 9454 print "<TD>".$q->img({src=>($iconurl.$b), width=>15, height=>15}); 9455 print " ".$b."</TD>"; 9456 } else { 9457 print "<TD bgcolor=#ff0000>Unable to read file $b</TD>"; 9458 } 9459 } 9460 print "</TR></TABLE>"; 9461 9462 # verify 9463 print $q->p("If the above images do not display, then you may need to correct the <b>iconurl</b> parameter in the <b>[routers.cgi]</b> section of your routers.conf file."); 9464 } else { 9465 print "Checked directory $iconpath<br>\n"; 9466 print $q->p("Unable to locate icon files in order to list them. This is not necessarily a problem! If the following image does not display, then you may need to correct the <b>iconurl</b> parameter in the <b>[routers.cgi]</b> section of your routers.conf file."); 9467 } 9468 print "This should show a target -->" 9469 .$q->img({src=>$iconurl."target-sm.gif",width=>15, height=>15}); 9470 print "<--. If it does not, correct your <b>iconurl</b> setting." 9471 .$q->br."\n"; 9472 9473 print $q->hr.$q->a({name=>"settings"}, 9474 $q->h2("Active Configuration Settings"))."\n"; 9475 print $q->p("These are the active settings, after taking into account any overrides due to application name ('$myname'), extra parameters ('$extra'), or authenticated user name ('$authuser').")."\n"; 9476 print "<UL>\n"; 9477 foreach ( sort keys %config ) { 9478 if( $_ eq 'web-auth-key' ) { 9479 print $q->li($q->b($_)." = \"<I>not displayed</I>\"")."\n"; 9480 } else { 9481 print $q->li($q->b($_)." = \"".$config{$_}."\"")."\n"; 9482 } 9483 } 9484 print "</UL>".$q->br; 9485 do_footer(); 9486} 9487 9488########################### 9489# If we get a bad page request 9490 9491sub do_bad($) 9492{ 9493 start_html_ss({-title=>"routers.cgi Error",-bgcolor=>"#ffd0d0", 9494 -class=>'error'}); 9495 print $q->h1(langmsg(8005,"Bad page request")); 9496 print $q->p("Error message was [".$_[0]."]")."\n"; 9497 print $q->p(langmsg(8007,"Check the format of the URL parameters for the page you are requesting."))."\n"; 9498 if(!$config{'web-paranoia'} 9499 or $config{'web-paranoia'}=~/[nN0]/) { 9500 eval { print $q->dump; }; 9501 } 9502 print $q->hr.$q->small("Error message generated by routers2.cgi")."\n"; 9503 print $q->end_html(); 9504} 9505 9506######################################################################## 9507# MAIN CODE STARTS HERE 9508######################################################################## 9509# Initialise parameters 9510 9511$bn = lc basename $q->url(-absolute=>1); 9512$myname = $bn if($bn); 9513 9514$opt_D = $opt_r = $opt_T = $opt_i = $opt_U = $opt_s = $opt_t = $opt_A = ""; 9515$opt_I = $opt_C = $opt_a = ""; 9516getopts('GAICD:T:r:i:s:t:a:U:'); 9517$opt_D = $opt_r if($opt_r); $opt_T = $opt_i if($opt_i); # override 9518 9519# Avoid IIS pathinfo bug 9520if( $^O !~ /Win/ or $q->server_software()!~/IIS|Microsoft/i ) { 9521 @pathinfo = split '/',$q->path_info() if($q->path_info()); 9522} 9523 9524$pagetype=""; 9525$pagetype=$q->param('page') if( defined $q->param('page') ); 9526$pagetype=$q->param('xpage')if( defined $q->param('xpage'));# stupid persistence 9527$pagetype='image' if(! defined $q->param('page') 9528 and $q->param('xgstyle') and ($q->param('xgstyle')=~/[AB]/)); 9529if($myname =~ /thumbnail\.(cgi|pl)/) { $pagetype = 'image'; $defgstyle = 'A'; } 9530$pagetype="graphCOMMAND" if($opt_A or $opt_D); # command line archive or generate 9531$pagetype="imageCOMMAND" if($opt_I or $opt_G); # command line image 9532$pagetype="csvCOMMAND" if($opt_C); # command line CSV extract 9533#$pagetype="graph" if(defined $q->param('searchhost')); 9534$pagetype="main" if(!$pagetype); 9535$archive = ""; 9536if( $q->param('archive') ){ 9537 $archive = $q->param('archive'); 9538} 9539# Deal with Authentication requests FIRST, before reading conf. 9540if( $pagetype eq 'login' ) { 9541 # generate login page 9542 login_page; 9543 print "<!--- login page requested --->\n"; 9544 exit 0; 9545} 9546if( $pagetype eq 'logout' ) { 9547 # generate logout page 9548 logout_page; 9549 exit 0; 9550} 9551if( $q->param('username') ) { 9552 # someone is trying to log in 9553 if( user_verify( $q->param('username'), $q->param('password') ) ) { 9554 # OK 9555 $authuser = $q->param('username'); 9556 } else { 9557 # bad login: force it again 9558 force_login(langmsg(1005,"Invalid username/password combination")); 9559 exit 0; 9560 } 9561} elsif($opt_U) { 9562 $authuser = $opt_U; # only via command line 9563} else { 9564 # get username from other sources 9565 $authuser = verify_id; 9566} 9567 9568# get these sections from the conf file. 9569$extra = lc $q->param('extra') if($q->param('extra')); 9570readconf( 'routers.cgi','web','routerdesc','targetnames','targettitles', 9571 'targeticons', 'servers', 'menu' ); 9572initlang(undef); # initialise the language module, if defined 9573 9574# Paranoia 9575$pagetype="main" if($pagetype eq "verify" and $config{'web-paranoia'} 9576 and $config{'web-paranoia'}=~/[yY1]/); 9577 9578if(defined $config{'routers.cgi-percent'} 9579 and $config{'routers.cgi-percent'}=~/(\d\d?\d?)/ ) { 9580 $PERCENT = $1; 9581} 9582 9583# Generate archived graphs 9584if($pagetype =~ /archive/) { 9585 $pagetype = "graph"; 9586 $archiveme = 1 if($config{'routers.cgi-archive'}=~/[y1]/i); 9587} 9588 9589# Allow override for broken web servers 9590$meurlfull = $config{'routers.cgi-myurl'} 9591 if( defined $config{'routers.cgi-myurl'} ); 9592 9593# Now, if we have forced security, and no authuser, then force the 9594# login page regardless. 9595if( defined $config{'web-auth-required'} 9596 and $config{'web-auth-required'} =~ /^[1y]/i and !$authuser ) { 9597 force_login(langmsg(1006,"Authorisation is required to view these pages")); 9598 exit 0; 9599} 9600# otherwise, if we have an authuser, set the cookie. 9601if($authuser) { 9602 push @cookies, generate_cookie; 9603 $headeropts{-cookie} = [@cookies]; 9604} 9605 9606# Find out our security level 9607$seclevel = $config{'routers.cgi-level'} 9608 if( defined $config{'routers.cgi-level'} ); 9609 9610# background colour (for the americans) 9611if ( defined $config{'routers.cgi-bgcolor'} 9612 and $config{'routers.cgi-bgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9613 $defbgcolour = $1; 9614} 9615if ( defined $config{'routers.cgi-fgcolor'} 9616 and $config{'routers.cgi-fgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9617 $deffgcolour = $1; 9618} 9619if ( defined $config{'routers.cgi-menufgcolor'} 9620 and $config{'routers.cgi-menufgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9621 $menufgcolour = $1; 9622} 9623if ( defined $config{'routers.cgi-menubgcolor'} 9624 and $config{'routers.cgi-menubgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9625 $menubgcolour = $1; 9626} 9627if ( defined $config{'routers.cgi-authfgcolor'} 9628 and $config{'routers.cgi-authfgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9629 $authfgcolour = $1; 9630} 9631if ( defined $config{'routers.cgi-authbgcolor'} 9632 and $config{'routers.cgi-authbgcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9633 $authbgcolour = $1; 9634} 9635if ( defined $config{'routers.cgi-linkcolor'} 9636 and $config{'routers.cgi-linkcolor'} =~ /(#[\da-fA-F]{6})/i ) { 9637 $linkcolour = $1; 9638} 9639# background colour (for the british) 9640if ( defined $config{'routers.cgi-bgcolour'} 9641 and $config{'routers.cgi-bgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9642 $defbgcolour = $1; 9643} 9644if ( defined $config{'routers.cgi-fgcolour'} 9645 and $config{'routers.cgi-fgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9646 $deffgcolour = $1; 9647} 9648if ( defined $config{'routers.cgi-menubgcolour'} 9649 and $config{'routers.cgi-menubgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9650 $menubgcolour = $1; 9651} 9652if ( defined $config{'routers.cgi-menufgcolour'} 9653 and $config{'routers.cgi-menufgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9654 $menufgcolour = $1; 9655} 9656if ( defined $config{'routers.cgi-authbgcolour'} 9657 and $config{'routers.cgi-authbgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9658 $authbgcolour = $1; 9659} 9660if ( defined $config{'routers.cgi-authfgcolour'} 9661 and $config{'routers.cgi-authfgcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9662 $authfgcolour = $1; 9663} 9664if ( defined $config{'routers.cgi-linkcolour'} 9665 and $config{'routers.cgi-linkcolour'} =~ /(#[\da-fA-F]{6})/i ) { 9666 $linkcolour = $1; 9667} 9668 9669if( defined $config{'web-png'} and $config{'web-png'}=~/[1y]/i ) { 9670 $graphsuffix = "png"; 9671} 9672if( defined $config{'routers.cgi-bytes'} 9673 and $config{'routers.cgi-bytes'}=~/y/i ) { 9674 $bits = "!bytes"; 9675 $factor = 1; 9676} 9677 9678# Anyone giving us a cookie? 9679$defgstyle = $q->cookie('gstyle') if($q->cookie('gstyle')); 9680if( ! $defgstyle ) { 9681 if( $config{'routers.cgi-graphstyle'} ) { 9682 my( $w ); # match against all the possibilities 9683 if( defined $gstyles{$config{'routers.cgi-graphstyle'}} ) { 9684 $defgstyle = $config{'routers.cgi-graphstyle'}; 9685 } else { 9686 foreach ( keys %gstyles ) { 9687 $gstyles{$_} =~ /^\s*(\w+)/; 9688 $w = lc $1; 9689 if( $w eq lc $config{'routers.cgi-graphstyle'} 9690 or $w eq $_ ) { 9691 $defgstyle = $_; 9692 last; 9693 } 9694 } 9695 } 9696 } 9697 $defgstyle = 'n' if(!$defgstyle); 9698} 9699$defbaropts = "Cami"; 9700if(defined $config{'routers.cgi-bars'}) { 9701 $defbaropts = $config{'routers.cgi-bars'}; 9702} 9703$defgopts = $q->cookie('gopts'); 9704$defgopts = "" if(!defined $defgopts); 9705$defgtype = $q->cookie('gtype'); 9706if( ! $defgtype ) { 9707 if( $config{'routers.cgi-graphtype'} ) { 9708 foreach ( @gorder ) { 9709 if( $_ eq $config{'routers.cgi-graphtype'} ) { 9710 $defgtype = $_; 9711 last; 9712 } 9713 } 9714 } 9715} 9716$defgtype = $gorder[0] if(! $defgtype); 9717 9718# identify menu type 9719$mtype = "routers"; 9720$mtype = $q->param('xmtype') if( defined $q->param('xmtype') ); 9721if( defined $config{'routers.cgi-allowexplore'} and $mtype ne "options" ) { 9722 $mtype = "options" 9723 if($config{'routers.cgi-allowexplore'} !~ /y/ ); 9724} 9725 9726# set the current device(router) and interface... 9727$router = ""; 9728$router = $defrouter = $q->cookie('router') if($q->cookie('router')); 9729$router = $pathinfo[1] if($pathinfo[1]); 9730$router = $opt_D if($opt_D); # command line 9731$router = $q->param('rtr') if( $q->param('rtr') ); 9732#$router = "" if(!defined $router or $router eq "none"); 9733$router = "" if(!defined $router); 9734# Only read in the routers table if (1) we need it, or (2) we are caching 9735if(($pagetype =~ /config/) 9736 or ($pagetype =~ /menu/ and ($mtype eq "routers" or !$router)) 9737 or(!$router and $pagetype and $pagetype !~ /help|main|head|bar/ ) 9738 or($pagetype =~ /graph/ 9739 and -r $config{'routers.cgi-confpath'}.$pathsep.$router ) 9740 or ($pagetype =~ /verify/) 9741 or ($q->param('searchhost')) 9742 or $CACHE ) { 9743 read_routers(); 9744 if ((! $router or !defined $routers{$router} ) and $router ne "none") { 9745 if($config{'routers.cgi-defaultrouter'} 9746 and ( defined $routers{$config{'routers.cgi-defaultrouter'}} 9747 or $config{'routers.cgi-defaultrouter'} eq 'none' )) { 9748 $router = $defrouter = $config{'routers.cgi-defaultrouter'}; 9749 } else { 9750 $router = $defrouter = (sort bydesc keys(%routers))[0] ; 9751 } 9752 } 9753} 9754 9755# Searching? 9756if( $q->param('searchhost') ) { 9757 my($sh) = $q->param('searchhost'); 9758 $router = 'none'; # If not found 9759 foreach ( keys %routers ) { 9760 if( $_ =~ /^(.*[\\\/])?$sh\.[^\.\\\/]+$/i ) { $router = $_; last; } 9761 } 9762 if($router eq 'none') { 9763 foreach ( keys %routers ) { 9764 if( $_ =~ /$sh/i ) { $router = $_; last; } 9765 if( $routers{$_}{shdesc} =~ /$sh/i ) { $router = $_; last; } 9766 } 9767 } 9768} 9769 9770# Do we need to redirect? 9771if( defined $routers{$router} and $routers{$router}{redirect} ) { 9772 if($pagetype =~ /graph/ or $q->param('searchhost')) { 9773 # coming from search box, or wanting graph page 9774 # Ugly stuff to avoid XSS problems - must reload entire frameset 9775 my($js)="function doredirect() { parent.location = \"" 9776 .$routers{$router}{redirect}.'?' 9777 .optionstring({page=>"main",rtr=>$router}) 9778 ."\"; } "; 9779 print $q->header(); 9780 print $q->start_html({-expires=>"+1s",-script=>$js,-onload=>"doredirect()"}); 9781 print "Please wait: handing over to other cluster member"; 9782 print $q->end_html; 9783 exit(0); 9784 } 9785 print $q->redirect($routers{$router}{redirect}.'?'. 9786 optionstring({page=>$pagetype,rtr=>$router}) ); 9787 exit(0); 9788} 9789 9790# Get interface information, if we need it 9791$defif = $q->cookie('if'); 9792$defif = $config{'routers.cgi-defaultinterface'} 9793 if(!$defif and defined $config{'routers.cgi-defaultinterface'}); 9794$defif = $pathinfo[2] if($pathinfo[2]); 9795$interface = ($q->param('if'))?$q->param('if'):$defif ; 9796$interface = $opt_T if($opt_T); # command line 9797$interface = '_summary_' if($interface eq '__summary'); # backwards compatible 9798$interface = 'none' if($router eq 'none'); 9799$interface = "" if(! defined $interface ); 9800if( ( ($pagetype =~ /menu/ and $mtype ne "routers" ) 9801 or $pagetype =~ /csv|graph|summary|info|compact|verify|image/ ) 9802 and $router ne "none" ) { 9803 if($router =~ /^#SERVER#/ ) { 9804 set_svr_ifs(); 9805 } else { 9806 read_cfg(); 9807 } 9808 $donecfg = 1; # set flag to show we have read in interfaces data 9809 if ( !$interface or $interface eq "__first" 9810 or $interface eq "__interface" or $interface eq "__memory" 9811 or $interface eq "__cpu" or $interface eq "__userdef" 9812 or ( $interface !~ /^__/ and !defined $interfaces{$interface} ) 9813 ) { 9814 if( $routers{$router}{defif} 9815 and defined $interfaces{$routers{$router}{defif}}) { 9816 $defif = $routers{$router}{defif}; 9817 } else { 9818 my( @ifs ); 9819 @ifs = sort byifdesc keys(%interfaces); 9820 $defif = 'none'; 9821 foreach ( @ifs ) { 9822 next if(!$interfaces{$_}{inmenu}); 9823 if( $interfaces{$_}{default} ) { $defif=$_; last; } 9824 $defif = $_ if($defif eq 'none'); 9825 if($interface eq "__interface" 9826 and $interfaces{$_}{mode} eq "interface") 9827 { $defif = $_; last; } 9828 if($interface eq "__memory" 9829 and $interfaces{$_}{mode} eq "memory") 9830 { $defif = $_; last; } 9831 if($interface eq "__cpu" 9832 and $interfaces{$_}{mode} eq "cpu") 9833 { $defif = $_; last; } 9834 if($interface eq "__userdef" and !$interfaces{$_}{issummary} 9835 and $interfaces{$_}{usergraph} ) 9836 { $defif = $_; last; } 9837 if($interface eq "__usersummary" and $interfaces{$_}{issummary} 9838 and $interfaces{$_}{usergraph} ) 9839 { $defif = $_; last; } 9840 } 9841 } # default specified 9842 $interface = $defif; 9843 } 9844} 9845 9846# Archive deletion 9847if( $q->param('delete') and $archive ) { 9848 # zap the requested archive 9849 my( $arch ); 9850 $arch = $router; $arch =~ s/[\?#\/\\]//g; 9851 $arch = $config{'routers.cgi-graphpath'}.$pathsep.$arch.$pathsep 9852 .$interface.$pathsep.$archive; 9853 unlink $arch; 9854 $archive = ""; 9855} 9856 9857$gtype = $defgtype; 9858$gstyle = $defgstyle; 9859$gopts = $defgopts; 9860$baropts = $defbaropts; 9861$gtype = $q->param('xgtype') if( defined $q->param('xgtype') ); 9862$gtype = $opt_t if($opt_t); 9863$gstyle = $q->param('xgstyle') if( defined $q->param('xgstyle')); 9864$gstyle = $opt_s if($opt_s); 9865$gopts = $q->param('xgopts') if( defined $q->param('xgopts') ); 9866$uopts = $q->param('uopts') if( defined $q->param('uopts') ); 9867$baropts= $q->param('bars') if( defined $q->param('bars') ); 9868$gtype = "d" if(!$gtype); 9869 9870# the graph time options 9871# Allow 6-hour if every RRD involved is able to do it also. 9872if( defined $config{'routers.cgi-6hour'} 9873 and $config{'routers.cgi-6hour'} =~ /y/i ) { 9874 # 6-hour mode is available. 9875 my($thisif); 9876 if($donecfg) { # have we read in the cfg files? 9877 if( $interface eq "__compact" ) { 9878 $usesixhour = 1; 9879 foreach $thisif ( keys %interfaces ) { 9880 next if(!$interfaces{$thisif}{incompact}); 9881 if($interfaces{$thisif}{interval} > 4) {$usesixhour = 0; last;} 9882 } 9883 } elsif ( $interface and defined $interfaces{$interface} 9884 and $interfaces{$interface}{usergraph} ) { 9885 # Userdefined - all member interfaces MUST be <5 9886 $usesixhour = 1; 9887 foreach $thisif ( @{$interfaces{$interface}{targets}} ) { 9888 if($interfaces{$thisif}{interval} > 4) {$usesixhour = 0; last;} 9889 } 9890 } elsif( $interface and defined $interfaces{$interface} 9891 and $interfaces{$interface}{interval} < 5 ) { 9892 $usesixhour = 1; 9893 } 9894 $usesixhour = 1 if($config{'routers.cgi-6hour'} =~ /a/i ); # for 'always' 9895 @gorder = ( "6", @gorder ) # add it to the beginning of the list 9896 if($usesixhour); 9897 } else { # donecfg 9898 @gorder = ( "6", @gorder ); # Assume it's OK, fix it later 9899 } 9900} 9901 9902# rrdcached support 9903# If we're using UNIX sockets, then we just need to force a flush of the 9904# relevant RRD files. If we're using TCP sockets, then all the commands need 9905# to use them. 9906$rrdcached = ""; 9907$rrdcached = $ENV{RRDCACHED_ADDRESS} if($ENV{RRDCACHED_ADDRESS}); 9908$rrdcached = $config{'web-rrdcached'} if($config{'web-rrdcached'}); 9909$rrdcached = $routers{$router}{rrdcached} 9910 if($router and defined $routers{$router} and $routers{$router}{rrdcached}); 9911if($rrdcached) { 9912 $debugmessage .= "RRDCached = $rrdcached, testing version...\n"; 9913 eval{ 9914 require RRDs; 9915 if( $RRDs::VERSION < 1.4 ) { 9916 $rrdcached = ""; # no support for rrdcached in this version 9917 } elsif( ($rrdcached !~ /^unix:/) and ($RRDs::VERSION<1.4999) ) { 9918 $rrdcached = ""; # no support for rrdcached/TCP in this version 9919 } 9920 }; 9921 $rrdcached = "" if($@); # if RRDs problem 9922 $debugmessage .= "RRDCached mode cancelled.\n" if(!$rrdcached); 9923} 9924# For tcp, 'fetch' and 'graph' will flush the cache; however 'last' doesnt 9925# Therefore we need to flush for all sockets. For unix domain, we go 9926# direct for graph, fetch and last so we MUST flush the cache. 9927#if( $rrdcached =~ /^unix:/ ) { 9928if( $rrdcached ) { # flush for TCP domain as well as unix domain 9929 # we know RRDs will be loaded by now 9930 if( $router and defined $routers{$router} and $interface 9931 and $interfaces{$interface} ) { 9932 my(@ifs) = (); 9933 my($pth) = $config{'routers.cgi-dbpath'}; 9934 $pth = $routers{$router}{workdir} if($routers{$router}{workdir}); 9935 $debugmessage .= "Flushing RRD files\n"; 9936 if( defined $interfaces{$interface}{targets} ) { 9937 foreach ( $interfaces{$interface}{targets} ) { 9938 push @ifs, $interfaces{$_}{rrd}; 9939 } 9940 } else { push @ifs, $interfaces{$interface}{rrd}; } 9941 eval { 9942 foreach ( @ifs ) { 9943 next if(!$_); 9944 RRDs::flushcached('--daemon',$rrdcached,$_); 9945 }; 9946 }; 9947 } 9948 # no longer needed as all will be done directly 9949 #$rrdcached = "" if( $rrdcached =~ /^unix:/ ); 9950} 9951@rrdcached = (); 9952@rrdcached = ( '--daemon',$rrdcached ) if($rrdcached); 9953 9954# Should we verify that the RRA has enough data? This would take a bit of 9955# extra time to do, but would prevent glitches. However we could say that 9956# anyone who switches this option on is taking the responsibility for making 9957# sure that the data is valid! 9958# Note that, if extendedtime = full, then we dont add these as we will instead 9959# test the RRD and add the appropriate dates into the calendar. 9960if( defined $config{'routers.cgi-extendedtime'} 9961 and $config{'routers.cgi-extendedtime'} =~ /y/i 9962) { 9963 push @gorder, "d-","w-","m-","y-"; 9964} elsif ( defined $config{'routers.cgi-extendedtime'} 9965 and $config{'routers.cgi-extendedtime'} =~ /t/i 9966 and $interface and defined $interfaces{$interface} 9967 and $interfaces{$interface}{rrd} 9968) { 9969 # see if we have more data available... 9970 eval { require RRDs; }; 9971 if( !$@ ) { 9972 my( $infop ) = RRDs::info($interfaces{$interface}{rrd},@rrdcached); 9973 push @gorder, "d-" if( ${$infop}{"rra[0].rows"} > 799 ); 9974 push @gorder, "w-" if( ${$infop}{"rra[1].rows"} > 799 ); 9975 push @gorder, "m-" if( ${$infop}{"rra[2].rows"} > 799 ); 9976 push @gorder, "y-" if( ${$infop}{"rra[3].rows"} > 799 ); 9977 } 9978} 9979 9980# sanity check 9981#if( $gtype eq "6" and $interface !~ /^__/ and ( !$usesixhour 9982# or ($interface and defined $interfaces{$interface} 9983# and $interfaces{$interface}{interval} >= 5 ))) { 9984# $gtype = $gorder[0]; 9985#} 9986if( $gtype eq "6" and $interface !~ /^_/ and !$usesixhour ) { 9987 $gtype = $gorder[0]; 9988} 9989if( defined $interfaces{$interface} 9990 and defined $interfaces{$interface}{suppress} ) { 9991 my($pat) = '['.$interfaces{$interface}{suppress}.']'; 9992 $gtype = 'dwmy' if($gtype =~ /$pat/); 9993} 9994if ( ! (defined $gtypes{$gtype}) or 9995 ( ($interface eq "__compact" 9996 or (defined $interfaces{$interface} and $interfaces{$interface}{issummary})) 9997 and (length ($gtype) > 2) )) { 9998 $gtype = $gorder[0]; 9999} 10000if( defined $config{'routers.cgi-uselastupdate'} 10001 and $config{'routers.cgi-uselastupdate'} =~ /y/i ) { 10002 $uselastupdate = 1; # set the flag for later. 10003} else { $uselastupdate = 0; } 10004# How big is a K ? Some people prefer 1024, some prefer 1000 10005if( $interfaces{$interface}{kilo} ) { 10006 $k = $interfaces{$interface}{kilo}; 10007 $M = $k * $k; 10008 $G = $M * $k; 10009 $T = $G * $k; 10010 if($k == 1000) { $ksym = 'k'; } else { $ksym = 'K'; } 10011} else { 10012 if( defined $config{'routers.cgi-usebigk'} ) { 10013 if( $config{'routers.cgi-usebigk'} =~ /y/i ) # yes 10014 { $k = 1024; $M = $k * 1024; $G = $M * 1024; $T=$G*1024; $ksym = "K"; } 10015 elsif( $config{'routers.cgi-usebigk'} =~ /n/i ) # no 10016 { $k = 1000; $M = 1000000; $G = $M * 1000; $T=$G*1000;$ksym = "k"; } 10017 elsif( $config{'routers.cgi-usebigk'} =~ /m/i ) # mixed 10018 { $k = 1024; $M = 1024000; $G = $M * 1000; $T=$G*1000;$ksym = "K"; } 10019 else 10020 { $k = 1024; $M = 1024000; $G=$M*1000;$T=$G*1000;$ksym="K"; } # default 10021 } else { 10022 $k = 1024; $M=1024000; $G=$M*1000;$T=$G*1000;$ksym="K"; # default (mixed) 10023 } 10024} 10025# Here, we should consider supporting Kmg to set ksym 10026# Define page title and so on. 10027$windowtitle = $config{'routers.cgi-windowtitle'} 10028 if ( defined $config{'routers.cgi-windowtitle'} ); 10029$toptitle = $config{'routers.cgi-pagetitle'} 10030 if ( defined $config{'routers.cgi-pagetitle'} ); 10031$toptitle = "<FONT size=+3>".$q->b($windowtitle)."</FONT>" if(!$toptitle); 10032 10033# Date format labels 10034$monthlylabel=$config{'web-weeknumber'} 10035 if( defined $config{'web-weeknumber'} 10036 and $config{'web-weeknumber'} =~ /%[UVW]/ ); 10037$dailylabel=$config{'web-hournumber'} 10038 if( defined $config{'web-hournumber'} 10039 and $config{'web-hournumber'} =~ /%[a-zA-Z]/ ); 10040 10041# Line widths 10042$linewidth = $config{'routers.cgi-linewidth'} 10043 if( defined $config{'routers.cgi-linewidth'} 10044 and ($config{'routers.cgi-linewidth'}>0) 10045 and ($config{'routers.cgi-linewidth'}<5)); 10046 10047# Menu format 10048if( (defined $config{'routers.cgi-twinmenu'} 10049 and $config{'routers.cgi-twinmenu'} =~ /y/i and $uopts !~ /T/ ) 10050 or $uopts =~ /t/ ) { 10051 $twinmenu = 1; 10052} 10053 10054# Archived data 10055# first, clean up cache if polluted 10056if(defined $interfaces{$interface} and $interfaces{$interface}{origrrd}) { 10057 $interfaces{$interface}{rrd} = $interfaces{$interface}{origrrd}; 10058} 10059$archdate = ''; 10060$archdate = $q->param('arch') if(defined $q->param('arch')); 10061$archdate = $opt_a if($opt_a); 10062$archdate = '' if($archdate eq POSIX::strftime('%Y-%m-%d',localtime())); 10063$basetime = 0; 10064if($config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'}=~/f/i and $archdate) { 10065 if($archdate=~/^(\d\d\d\d)-(\d\d)-(\d\d)/) { 10066 eval { 10067 $basetime = timelocal_nocheck(59,59,23,$3,$2-1,$1-1900); 10068 }; 10069 if($@) { 10070 $debugmessage .= "Error in time conversion: $@\n"; 10071 } 10072 } 10073 $basetime = time() if($basetime > time()); 10074 $debugmessage .= "Setting base time to $basetime ($archdate)\n"; 10075} elsif($archdate and $donecfg) { 10076 # archive date, and read in cfg file, and not extendedtime=full mode 10077 if($archdate=~/^(\d\d\d\d)-(\d\d)-(\d\d)/) { 10078 eval { 10079 $archivetime = timelocal_nocheck(59,59,23,$3,$2-1,$1-1900); 10080 }; 10081 } 10082 if( !$interface or !$interfaces{$interface}{rrd}){ 10083 $debugmessage .= "Invalid target $interface!\n"; 10084 $archdate = ''; # This interface is not valid 10085 } elsif( $config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'}=~/f/i ) { 10086 # using extendedtime with calendar. 10087 } elsif( ! -d 10088 (dirname($interfaces{$interface}{rrd}).$pathsep.'archive' 10089 .(($config{'routers.cgi-archive-mode'} and 10090 $config{'routers.cgi-archive-mode'}=~/hash/i )?"" 10091 :($pathsep.$archdate) 10092 ) 10093 ) 10094 ) { 10095 $debugmessage .= "Invalid date $archdate for target $interface!\n"; 10096 $archdate = ''; # this date archive is not avaiable 10097 } else { 10098 # CHANGE THE DEFINED RRD FILE(s) IF WE ARE NOT ON MENU 10099 if($pagetype=~/graph|csv|image|summary|compact/ ) { 10100 my($thisif,$dn,$bn); 10101 my(@candidates) = ( $interface ); 10102# push @candidates, @{$interfaces{$interface}{targets}} 10103# if($interfaces{$interface}{usergraph} 10104# or $interfaces{$interface}{issummary}); 10105 @candidates = (keys %interfaces) 10106 if($interface =~ /^__/ or $interfaces{$interface}{usergraph}); 10107 foreach $thisif ( @candidates ) { 10108 next if($thisif =~ /^_/); # skip userdefineds 10109 if(!$interfaces{$thisif}{origrrd}) { 10110 $interfaces{$thisif}{origrrd} = $interfaces{$thisif}{rrd}; 10111 } else { 10112 $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd}; 10113 } 10114 next if(!$interfaces{$thisif}{rrd}); 10115 $dn = dirname($interfaces{$thisif}{rrd}); 10116 $bn = basename($interfaces{$thisif}{rrd}); 10117 $interfaces{$thisif}{rrd} = $dn.$pathsep.'archive'.$pathsep 10118 .(($config{'routers.cgi-archive-mode'} and 10119 $config{'routers.cgi-archive-mode'}=~/hash/i )?( 10120 makehash($bn).$pathsep.$bn.".d" 10121 .$pathsep.$archdate.".rrd" 10122 ):( 10123 $archdate.$pathsep.$bn 10124 )); 10125 if( ! -f $interfaces{$thisif}{rrd} ) { 10126 # if the archive doesnt exist 10127 $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd}; 10128# $archdate = ''; 10129 $debugmessage .= "No archive for target $thisif on $archdate\n"; 10130# } else { 10131# # is this a good idea? Maybe should uselastupdate instead 10132# my($a) = (stat $interfaces{$thisif}{rrd})[9]; 10133# $archivetime = $a if(!$archivetime) or ($a > $archivetime)); 10134 } 10135 } 10136 } 10137 $uselastupdate = 2; # since we are now basing from old .rrd file 10138 } 10139# $debugmessage .= "Archivetime: $archivetime\nArchdate: $archdate\n"; 10140} elsif(defined $interfaces{$interface}) { 10141 if($pagetype =~ /graph|csv|summary|compact/ ) { 10142 my($thisif); 10143 my(@candidates) = ( $interface ); 10144 push @candidates, @{$interfaces{$interface}{targets}} 10145 if($interfaces{$interface}{usergraph}); 10146 @candidates = (keys %interfaces) if($interface =~ /^__/); 10147 foreach $thisif ( @candidates ) { 10148 $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd} 10149 if($interfaces{$thisif}{origrrd}); 10150 } 10151 } 10152} 10153 10154if( $opt_A ) { 10155 $pagetype = 'COMMAND'; $archiveme = 1; # override 10156 $|=1; 10157 print "Creating Graph...\n"; 10158 if($opt_T) { 10159 # target was set 10160 # Archive this graph 10161 if( !$interface or !defined $interfaces{$interface} 10162 or $interface=~/^__/ or $interfaces{$interface}{issummary} ) { 10163 print "This target is not appropriate to archive.\n"; 10164 print "Device/Target = [$router]/[$interface]\n"; 10165 print "Unknown Target\n" if(!defined $interfaces{$interface}); 10166 print "Illegal Target\n" if($interface=~/^__/); 10167 print "Summary Target\n" if($interfaces{$interface}{issummary}); 10168 print "Targets:\n".(join ",",(keys %interfaces))."\n"; 10169 print "Devices:\n".(join ",",(keys %routers))."\n"; 10170 exit(1); 10171 } 10172 do_graph(0); 10173 } else { 10174 # Do them all, for this device 10175 foreach $interface ( keys %interfaces ) { 10176 next if($interface=~/^__/ or $interfaces{$interface}{issummary} 10177 or !$interfaces{$interface}{inmenu} ); 10178 print "$interface... "; 10179 do_graph(0); 10180 } 10181 } 10182 exit(0); 10183} 10184 10185# Start the page off 10186if( $pagetype =~ /graph/ and !$archive and !$archdate ) { 10187 my($rtime) = 1800; 10188 $rtime =900 if($gtype =~ /w/); 10189 $rtime =300 if($gtype =~ /d/); 10190 $rtime = 60 if($gtype =~ /6/); 10191 $rtime = $config{'routers.cgi-minrefreshtime'} 10192 if( defined $config{'routers.cgi-minrefreshtime'} 10193 and $config{'routers.cgi-minrefreshtime'} > $rtime ); 10194 $headeropts{-expires} = "+5s"; 10195 $headeropts{-Refresh} = $rtime; 10196 $headeropts{-Refresh} .= "; URL=$meurlfull?".optionstring({}) if($archiveme); 10197 $headeropts{-head} = [] if(!$headeropts{-head}); 10198 push @{$headeropts{-head}}, $q->meta({-http_equiv=>'Refresh',-content=>$headeropts{-Refresh}}); 10199} 10200$headeropts{-target} = $pagetype if($pagetype =~ /head|menub?|graph/ ); 10201$headeropts{-target} = "graph" 10202 if( $pagetype =~ /compact|summary|help|info|config/ ); 10203$headeropts{-target} = "_top" if ( !$pagetype ); 10204 10205if ( $pagetype =~ /config/ and $q->param('xset')) { 10206 push @cookies, $q->cookie( -name=>'gstyle', -value=>$q->param('defgstyle'), 10207 -path=>$q->url(-absolute=>1), -expires=>"+10y" ) 10208 if( defined $q->param('defgstyle')); 10209 push @cookies, $q->cookie( -name=>'gtype', -value=>$q->param('defgtype'), 10210 -path=>$q->url(-absolute=>1), -expires=>"+10y" ) 10211 if( defined $q->param('defgtype') ); 10212 push @cookies, $q->cookie( -name=>'router', -value=>$q->param('defrouter'), 10213 -path=>$q->url(-absolute=>1), -expires=>"+10y" ) 10214 if( defined $q->param('defrouter') ); 10215 push @cookies, $q->cookie( -name=>'if', -value=>$q->param('defif'), 10216 -path=>$q->url(-absolute=>1), -expires=>"+10y" ) 10217 if( defined $q->param('defif') ); 10218 if( defined $q->param('deflang') ) { 10219 initlang($q->param('deflang')); 10220 if($q->param('deflang')) { 10221 push @cookies, $q->cookie( -name=>'lang', -value=>$language, 10222 -path=>$q->url(-absolute=>1), -expires=>"+10y" ) ; 10223 } else { 10224 push @cookies, $q->cookie( -name=>'lang', -value=>'', 10225 -path=>$q->url(-absolute=>1), -expires=>"now" ) ; 10226 } 10227 } 10228} 10229# Character sets 10230if(defined $config{'routers.cgi-charset'}) { 10231 $charset = $config{'routers.cgi-charset'}; 10232}elsif(defined $config{'web-charset'}) { 10233 $charset = $config{'web-charset'}; 10234} 10235if($charset) { 10236 $headeropts{-charset} = $charset; 10237 10238 $headeropts{-head} = [] if(!$headeropts{-head}); 10239 push @{$headeropts{-head}}, $q->meta({-http_equiv => 'Content-Type', 10240 -content => "text/html; charset=$charset"}); 10241} 10242# Are we exporting CSV? 10243if( $pagetype =~ /csv/ ) { 10244 my($fn) = "export.csv"; 10245 $csvmime=$config{'web-csvmimetype'} if(defined $config{'web-csvmimetype'}); 10246 $fn = $config{'web-csvmimefilename'} 10247 if(defined $config{'web-csvmimefilename'}) ; 10248 $csvmime .= "; filename=\"".$fn."\""; 10249 $headeropts{"-Content-Disposition"} = "filename=\"".$fn."\""; 10250 $headeropts{-type} = $csvmime ; 10251} 10252 10253# The bar and image functions have to do their own headers as they may need 10254# to redirect. 10255$headeropts{-cookie} = [@cookies] if(@cookies); 10256print $q->header({ %headeropts }) if($pagetype !~ /bar|image|COMMAND/); 10257 10258# 10259# Now, we check the passed parameters to find out what sort of page to 10260# serve up. If we can't work out which one to do, then we just serve the 10261# index page 10262if($pagetype) { 10263 for($pagetype) { 10264 /head/ and do { do_head(); last; }; 10265 /menu/ and do { do_menu(); last; }; # matches menu and menub 10266 /compactcsv/ and do { do_compact(1); last; }; 10267 /csv/ and do { 10268 if($interface eq "__compact") { do_compact(1); last; } 10269 last if( $interface =~ /^__/ ); # oops, this shouldnt happen 10270 do_export(); 10271 last; 10272 }; 10273 /image/ and do { 10274 if( $interface !~ /^__/ and defined $interfaces{$interface}) { 10275 if( $archive ) { 10276 do_archive(0); 10277 } else { 10278 do_graph(0); 10279 } 10280 } else { 10281 if($opt_I) { 10282 print "Interface: $interface\nError: Not defined\n"; 10283 } else { 10284 print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); 10285 } 10286 } 10287 last; 10288 }; 10289 /graph|archive/ and do { 10290 if ( $interface eq "__info" ) { 10291 do_info(); 10292 } elsif ( $interface eq "__compact" ) { 10293 do_compact(0); 10294 } elsif ( $interface eq "__none" ) { 10295 do_empty(); 10296 } elsif ( $interface =~ /^__/ ) { 10297 do_bad("Bad target: $interface"); 10298 } elsif ( $interfaces{$interface}{usergraph} 10299 and $interfaces{$interface}{issummary} ) { 10300 do_summary(); 10301 } else { 10302 if( $archive ) { 10303 do_archive(1); 10304 } else { 10305 do_graph(1); 10306 } 10307 } 10308 last; 10309 }; 10310 /help/ and do { do_help(); last; }; 10311 /main/ and do { do_main(); last; }; 10312 /info/ and do { do_info(); last; }; 10313 /summary/ and do { do_summary(); last; }; 10314 /compact/ and do { do_compact(0); last; }; 10315 /config/ and do { do_config(); last; }; 10316 /bar/ and do { do_bar(); last; }; 10317 /verify/ and do { 10318 if($config{'web-paranoia'} 10319 and $config{'web-paranoia'}=~/[yY1]/) { 10320 do_bad(langmsg(8006,"You do not have authority to view the configuration")); 10321 last; 10322 } 10323 if( !defined $config{'routers.cgi-allowexplore'} 10324 or $config{'routers.cgi-allowexplore'} =~ /[1y]/i ) { 10325 do_verify(); last; 10326 } 10327 do_bad(langmsg(8006,"You do not have authority to view the configuration")); 10328 last; 10329 }; 10330 do_bad("Bad pagetype: $pagetype"); 10331 } 10332} else { do_main() } 10333 10334# Clean up 10335if($CACHE and $archdate) { 10336 if(defined $interfaces{$interface} 10337 and defined $interfaces{$interface}{origrrd}) { 10338 $interfaces{$interface}{rrd} = $interfaces{$interface}{origrrd}; 10339 } 10340} 10341exit(0); 10342