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

\n"; } print "
"; # grouping $grouping = 1 if( defined $config{'routers.cgi-group'} and $config{'routers.cgi-group'} =~ /[Yy1]/ ); if($grouping) { $group=$lastgroup=""; $group=$routers{$router}{group} if(defined $routers{$router}); $gs = ':'; $gs = $config{'routers.cgi-groupsep'} if(defined $config{'routers.cgi-groupsep'}); } my($lastgroupdesc,$activegroupdesc); if($multilevel) { if( defined $config{"targetnames-$group"} ) { $activegroupdesc = $config{"targetnames-$group"}; } elsif( defined $config{("targetnames-".(lc $group))} ) { $activegroupdesc = $config{("targetnames-".(lc $group))}; } else { $activegroupdesc = basename( $group,'' ).$pathsep; } } foreach ( sort byshdesc keys(%routers) ) { next if(!$routers{$_}{inmenu}); if( $grouping ) { $thisgroup = $routers{$_}{group}; if( $thisgroup ne $lastgroup ) { my(@grps); if( defined $config{"targetnames-$thisgroup"} ) { $groupdesc = $config{"targetnames-$thisgroup"}; } elsif( defined $config{("targetnames-".(lc $thisgroup))} ) { $groupdesc = $config{("targetnames-".(lc $thisgroup))}; } else { $groupdesc = basename( $thisgroup,'' ).$pathsep; } if($multilevel) { @grps = getgroups($activegroupdesc,$groupdesc,$lastgroupdesc); } else { @grps = ( [ $groupdesc,1,(($thisgroup eq $group)?1:0) ] ); } foreach my $gg ( @grps ) { print ""; $menulevel = $gg->[1]; print "  " x $menulevel if($menulevel); if( $gg->[2] ) { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}g-sm.gif", width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu' })," "; print $q->b($gg->[0]); } else { $lurl = $meurlfull; $lurl = $routers{$_}{redirect} if(defined $routers{$_}{redirect}); if( $gstyle =~ /p/ or defined $routers{$_}{redirect}) { print $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}plus-sm.gif", width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu', border=>0 })," "; print $q->a({href=>"$lurl?" .optionstring({page=>"main",'if'=>"",rtr=>"$_"}), target=>"_top", class=>'sidemenu' },$q->b($gg->[0]) ); } else { print $q->a({ href=>"$lurl?" .optionstring({ rtr=>"$_", 'if'=>"" }), target=>"graph", class=>'sidemenu' }, $q->img({ src=>"${config{'routers.cgi-smalliconurl'}}plus-sm.gif", width=>15, height=>15, alt=>$gg->[0], class=>'sidemenu', border=>0 }))." "; print $q->a({ href=>"$lurl?" .optionstring({ rtr=>"$_", 'if'=>"" }), target=>"graph", class=>'sidemenu' },$q->b($gg->[0]) ); } } print "".$q->br."\n"; } # foreach $lastgroup = $thisgroup; $lastgroupdesc = $groupdesc; } # if in new group if( $multilevel ) { next if(( $thisgroup ne $group ) and ( $activegroupdesc !~ /^$groupdesc$gs/ )); # if(( $thisgroup ne $group ) # and ( $activegroupdesc !~ /^$groupdesc$gs/ )) { print "[$activegroupdesc][^$groupdesc$gs]"; } } else { next if( $thisgroup ne $group ); # only show active group } } # if grouping $rtrdesc = $routers{$_}{shdesc}; $rtrdesc = $_ if(! $rtrdesc ); $rtrdesc =~ s/ /\ \;/g; # stop breaking of line on spaces print ""; if($grouping) { print ( "  " x ($menulevel+1)); } if( $_ eq $router ) { print $q->a({name=>"top"},""); } print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$routers{$_}{icon}), width=>15, height=>15, class=>'sidemenu', alt=>( $routers{$_}{shdesc}?$routers{$_}{shdesc}:$_ ) })," "; if( $_ eq $router ) { print $q->b($rtrdesc); } else { $lurl = $meurlfull; $lurl = $routers{$_}{redirect} if(defined $routers{$_}{redirect}); if( $gstyle =~ /p/ or defined $routers{$_}{redirect}) { print $q->a({href=>"$lurl?".optionstring({page=>"main", 'if'=>"", rtr=>"$_"}), target=>"_top", class=>'sidemenu' },$rtrdesc ); } else { print $q->a({href=>"$lurl?".optionstring({ rtr=>"$_", 'if'=>"" }), target=>"graph", class=>'sidemenu' },$rtrdesc ); } } print "".$q->br."\n"; } # Now add any site links my($mkey,$marg,$mdesc,$micon,$murl,$targ,$level,$insec,$noop); # my($itemx) = 1; # while ( defined $config{"menu-item$itemx"} ) { # $marg = $config{"menu-item$itemx"}; # $mkey = "Item $itemx"; # $itemx += 1; ## This way is slower, but more user-friendly foreach ( sort keys %config ) { if( /^menu-(\S+)/i ) { $mkey = $1; $marg = $config{$_}; ( $mdesc, $murl, $micon, $targ, $level, $insec, $noop ) = parse_ext($marg); if($seclevel >= $level ) { # Are we high enough security level? if( !$micon and $mdesc =~ /\.gif$/ ) { $micon = $mdesc; $mdesc = $mkey; } $mdesc = $mkey if(!$mdesc); #default $micon = "cog-sm.gif" if(!$micon); #default if(!$noop and $murl !~ /\.html?$/ ) { if( $murl =~ /\?/ ) { $murl .= '&'; } else { $murl .= '?'; } $murl .= "fi=".$q->escape($router) ."&url=".$q->escape($q->url()) ."&t=".$q->escape($targ)."&L=".$seclevel; } print ""; print $q->img({ src=>($config{'routers.cgi-smalliconurl'}.$micon), width=>15, height=>15, alt=>"$mdesc", class=>'sidemenu' })," "; print $q->a({href=>$murl, target=>$targ, class=>'sidemenu' },$mdesc ); print "".$q->br."\n"; } # security level } # if } # foreach } # Finish off the page print "
\n" if( defined $config{'routers.cgi-menufontsize'} ); print "
\n\n"; print "\n"; print "\n" if($debugmessage); print $q->end_html(); } ############################ # Main frame set sub do_main() { my( $javascript, $framethree ); my( $urla, $urlb, $urlc, $urlh ); my( $menuwidth ) = 150; my( $frameopts ) = " marginwidth=2 marginheight=2 bgcolor=$menubgcolour "; my( $borderwidth ) = 1; $gtype = "" if(!defined $gtype); $mtype = "" if(!defined $mtype); $gstyle = "" if(!defined $gstyle); $gopts = "" if(!defined $gopts); $baropts = "cam" if(!defined $baropts); $borderwidth = $config{'routers.cgi-borderwidth'} if( defined $config{'routers.cgi-borderwidth'} ); $menuwidth = $config{'routers.cgi-menuwidth'} if( defined $config{'routers.cgi-menuwidth'} ); $menuwidth = 150 if ( $menuwidth < 100 or $menuwidth > 500 or $menuwidth !~ /^\d+$/ ); # Javasciript funtion to reload the page with a specified set of params. $javascript = " function makebookmark(rtr,rtrif,xgtype,xgstyle,xgopts,bars,extra,arch) { var newurl; newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif); if ( xgtype != '' ) { newurl = newurl + '&xgtype='+xgtype; } if ( xgstyle != '' ) { newurl = newurl + '&xgstyle='+xgstyle; } if ( xgopts != '' ) { newurl = newurl + '&xgopts='+xgopts ; } if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } if ( arch != '' ) { newurl = newurl + '&arch='+escape(arch) ; } if ( bars != '' && rtrif == '__compact' ) { newurl = newurl + '&bars='+bars ; } window.location = newurl; } function makearchmark(rtr,rtrif,extra,arch) { var newurl; newurl = '$meurlfull?rtr='+escape(rtr)+'&if='+escape(rtrif) +'&archive='+arch; if ( extra != '' ) { newurl = newurl + '&extra='+escape(extra) ; } window.location = newurl; } var lastaurl; var lastburl; function setlocationa(url) { if( lastaurl != url ) { self.menu.location = url; lastaurl = url; } } function setlocationb(url) { if( self.menub ) { if( lastburl != url ) { self.menub.location = url; lastburl = url; } } } "; $urlb = $meurlfull."?".optionstring({ page=>"graph", nomenu=>1 }); if( $twinmenu ) { $urla = $meurlfull."?".optionstring({ page=>"menu", xmtype=>"routers" }) ."#top"; $urlc = $meurlfull."?".optionstring({ page=>"menub", xmtype=>"options" }) ."#top"; $framethree = " \n"; } else { $urla = $meurlfull."?".optionstring({ page=>"menu", nomenu=>1 })."#top"; $framethree = " \n"; } $urlh = $meurlfull."?".optionstring({ page=>"head" }); if($q->cookie('auth')) { print "\n"; } print ""; print "\n" if($config{"routers.cgi-stylesheet"}); print "$windowtitle\n"; if(! $q->param('noheader') ) { print "\n"; print "\n"; } print "$framethree\n"; if(! $q->param('nohead') ) { print "\n"; } print < Sorry, routers.cgi does not support non-frames browsers. Upgrade to Netscape 4.x or later, or MSIE 4.x or later. EOT ; # now clean up the verify stuff if it's there # we cant do this in the do_verify subroutine because the file is required # by a future connection. unlink ($config{'routers.cgi-graphpath'}.$pathsep."redsquare.png") if( -f $config{'routers.cgi-graphpath'}.$pathsep."redsquare.png" ); } ######################## # Is this interface 'active'? # return 0 (inactive), 1 (active), error message sub isactive($) { my($curif) = $_[0]; my($start,$end,$interval,$rrd,$data,$names); my($e,$line,$val); my(@params)=('MAX'); my($dwmy,$lastupdate); # If thisis an archive, then uselastupdate=2 and rrd is already changed $rrd = $interfaces{$curif}{rrd}; $dwmy = $gtype; $end = 'now'; if($uselastupdate) { $lastupdate = RRDs::last($rrd); if($lastupdate) { $end = $lastupdate; } $end = $archivetime if($uselastupdate > 1 and $archivetime); } if( $dwmy =~ /-/ ) { if ( $dwmy =~ /6/ ) { push @params, "-e", "$end-6h"; } elsif ( $dwmy =~ /d/ ) { push @params, "-e", "$end-24h";} elsif ( $dwmy =~ /w/ ) { push @params, "-e", "$end-7d"; } elsif ( $dwmy =~ /m/ ) { push @params, "-e", "$end-30d";} elsif ( $dwmy =~ /y/ ) { push @params, "-e", "$end-365d";} } else { push @params, '-e', $end; } if ( $dwmy =~ /6/ ) { $interval = "60"; } elsif ( $dwmy =~ /d/ ) { $interval = "300"; } elsif ( $dwmy =~ /w/ ) { $interval = "1800"; } elsif ( $dwmy =~ /m/ ) { $interval = "7200"; } elsif ( $dwmy =~ /y/ ) { $interval = "86400"; } push @params,'-r',86400; # always use daily max RRA push @params,'-s',"end-".($interval*400);# just back to start of this graph ($start,$interval,$names,$data) = RRDs::fetch($rrd,@params); $e = RRDs::error(); return $e if($e); foreach $line ( @$data ) { foreach $val ( @$line ) { return 1 if($val); } } return 0; # not active: no values other than 0 were found } ########################## # Graph panel sub sinout($$) { my($interface); my($sin,$sout,$sext); my($ssin,$ssout,$ssext); my($l,$escunit); my($alt); ($interface,$alt) = @_; $escunit = $interfaces{$interface}{unit}; $escunit =~ s/%/%%/g; $escunit =~ s/:/\\:/g; $escunit =~ s/ / /g; $sin=langmsg(6403,"In: "); $sout=langmsg(6404,"Out:"); $sext = "Ext:"; $ssext = $ssin = $ssout = ""; $sin = $interfaces{$interface}{legendi} if( defined $interfaces{$interface}{legendi} ); $sout= $interfaces{$interface}{legendo} if( defined $interfaces{$interface}{legendo} ); $sext = $interfaces{$interface}{legendx} if( defined $interfaces{$interface}{legendx} ); if( $alt and $interfaces{$alt}{overridelegend} and $interfaces{$interface}{shdesc} and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} or $interfaces{$alt}{noo} or $interfaces{$alt}{noi} ) ) { $sin = $sout = $interfaces{$interface}{shdesc}.':'; } $l = length $sin; $l = length $sout if($l < length $sout); $sin = substr($sin.' ',0,$l); $sout= substr($sout.' ',0,$l); $sin =~ s/:/\\:/g; $sout =~ s/:/\\:/g; $sin =~ s/%/%%/g; $sout =~ s/%/%%/g; if( $interfaces{$interface}{integer} ) { $ssin = "%5.0lf"; $ssout = "%5.0lf"; $ssext = "%5.0lf"; } elsif( $interfaces{$interface}{fixunits} and !$interfaces{$interface}{exponent} ) { $ssin = "%7.2lf "; $ssout = "%7.2lf "; $ssext = "%7.2lf"; } else { $ssin = "%6.2lf %s"; $ssout = "%6.2lf %s"; $ssext = "%6.2lf %s"; } if( defined $config{'routers.cgi-legendunits'} and $config{'routers.cgi-legendunits'} =~ /y/i ) { $ssin .= $escunit; $ssout .= $escunit; } $sin .= $ssin; $sout .= $ssout; if( $interfaces{$interface}{mode} eq "SERVER" and $interface eq "CPU" ) { $sin = "usr\\:%6.2lf%%"; $sout = "sys\\:%6.2lf%%"; $sext = "wa\\: %6.2lf%%"; $ssin = $ssout = $ssext = "%6.2lf%%"; } return ( $sin,$sout,$sext, $ssin,$ssout,$ssext ); } sub usr_params(@) { my($ds0,$ds1,$mds0,$mds1); my($lin, $lout); my($dwmy,$interface) = @_; my($ssin, $ssout, $sin, $sout, $sext, $ssext); my($l,$defrrd, $curif); my($legendi,$legendo); my(@clr,$ifcnt, $c, $escunit); my($totindef,$totoutdef,$incnt, $outcnt); my($stacking) = 0; my($max1, $max2); my($greydef) = "0"; # extra RPN is added if necessary my($havepeaks) = 0; my($workday) = 0; # my($timezone) = 0; # use the global my(@wdparams) = (); my($maxlbl,$avglbl,$curlbl,$lastlbl) = ('Max','Avg','Cur','Last'); my($gmaxlbl,$gavglbl,$gcurlbl,$glastlbl); $maxlbl = langmsg(2200,$maxlbl); $avglbl = langmsg(2201,$avglbl); $curlbl = langmsg(2202,$curlbl); $lastlbl = langmsg(2203,$lastlbl); $gmaxlbl = langmsg(6200,$maxlbl); $gavglbl = langmsg(6201,$avglbl); $gcurlbl = langmsg(6202,$curlbl); $glastlbl = langmsg(6203,$lastlbl); if( defined $config{'routers.cgi-daystart'} and defined $config{'routers.cgi-dayend'} and $config{'routers.cgi-daystart'}<$config{'routers.cgi-dayend'} and $dwmy !~ /y/ ){ $workday = 1; } # stacking? if( defined $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle} =~ /stack/i ) { # |mirror $stacking = 1; # first is AREA, then STACK } # identify colours if( defined $interfaces{$interface}{colours} ) { @clr = @{$interfaces{$interface}{colours}}; } if(! @clr ) { if( $gstyle =~ /b/ ) { @clr = ( "#000000","#888888","#cccccc","#dddddd","#666666","#444444", "#222222", "#aaaaaa", "#eeeeee", "#bbbbbb", "#555555", "#333333" ); } else { @clr = ( "#0000ff","#00ff00","#ff0000","#00cccc","#cccc00","#cc00cc", "#8800ff", "#88ff00", "#ff8800", "#0088ff", "#ff0088", "#00ff88" ); } } $ifcnt = $#{$interfaces{$interface}{targets}}; # Now the workday highlights, if required if( $workday ) { # note we must have a DS in there even if it is not used push @wdparams, "CDEF:wdtest=in1,POP," ."TIME,3600,/,$timezone,+,DUP,24,/,7,%,DUP,4,LT,EXC,2,GE,+,2,LT," ."EXC,24,%,DUP," .trim($config{'routers.cgi-daystart'}).",GE,EXC," .trim($config{'routers.cgi-dayend'}).",LT,+,2,EQ,1," ."0,IF,0,IF"; # Set to 1 if in working day # mark the working day background, if not in b&w mode if( $gstyle !~ /b/ ) { push @wdparams, "CDEF:wd=wdtest,INF,0,IF", "AREA:wd#ffffcc"; if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { push @wdparams, "CDEF:mwd=wd,-1,*", "AREA:mwd#ffffcc"; } } } while( $#clr < $ifcnt ) { push @clr, @clr; } $totindef = "CDEF:totin=0"; $totoutdef = "CDEF:totout=0"; $ifcnt = 0; $incnt = $outcnt = 0; foreach $curif ( @{$interfaces{$interface}{targets}} ) { # loop through all interfaces $ifcnt++; if($interfaces{$interface}{active} and !$interfaces{$curif}{userdefined}) { next if(!isactive($curif)); } $defrrd = $interfaces{$curif}{rrd}; $defrrd =~ s/:/\\:/g; # $debugmessage .= "RRD: $defrrd\n"; ($sin,$sout,$sext ,$ssin,$ssout,$ssext) = sinout($curif,$interface); if ( $dwmy =~ /s/ ) { $lin=""; $lout=""; } else { $lin = langmsg(6405,"Inbound"); $lout = langmsg(6406,"Outbound"); $lin = $interfaces{$curif}{legend1} if( defined $interfaces{$curif}{legend1} ); $lout = $interfaces{$curif}{legend2} if( defined $interfaces{$curif}{legend2} ); if( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} ) { $lin = $interfaces{$curif}{desc}." ($lin)"; $lout= $interfaces{$curif}{desc}." ($lout)"; } $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; $lin = ':'.$lin; $lout = ':'.$lout; if($interfaces{$interface}{noo}) { $lin .= "\\l"; } else { $lout .= "\\l"; } } $lin = substr( $lin." ",0,30 ) if($lin and !$interfaces{$interface}{noo}); if( $interfaces{$interface}{nolegend} or $interfaces{$interface}{nodetails} ) { $lin = $lout = ""; } ($ds0, $ds1) = ("ds0", "ds1"); push @params, "DEF:in$ifcnt=".$defrrd.":$ds0:" .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE"), "DEF:out$ifcnt=".$defrrd.":$ds1:" .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE"); ($ds0, $ds1) = ("in$ifcnt", "out$ifcnt"); # Now for unknaszero if( $interfaces{$curif}{unknaszero} ) { push @params, "CDEF:unin$ifcnt=$ds0,UN,0,$ds0,IF", "CDEF:unout$ifcnt=$ds1,UN,0,$ds1,IF"; ($ds0, $ds1) = ("unin$ifcnt", "unout$ifcnt"); } # Now for unknasprev if( $interfaces{$curif}{unknasprev} ) { if($RRDs::VERSION >= 1.00039 ) { push @params, "CDEF:unpin$ifcnt=$ds0,UN,PREV,$ds0,IF", "CDEF:unpout$ifcnt=$ds1,UN,PREV,$ds1,IF"; ($ds0, $ds1) = ("unpin$ifcnt", "unpout$ifcnt"); } } # Needs to be here because ds1 must be defined push @params, @wdparams if($workday and ($ifcnt == 1)); ### do this if we are using BITS if( $interfaces{$curif}{mult} and ($interfaces{$curif}{mult} != 1) ) { push @params, "CDEF:fin$ifcnt=$ds0,".$interfaces{$curif}{mult}.",*", "CDEF:fout$ifcnt=$ds1,".$interfaces{$curif}{mult}.",*"; ($ds0, $ds1) = ("fin$ifcnt", "fout$ifcnt"); } if( defined $interfaces{$curif}{factor} ) { push @params, "CDEF:ffin$ifcnt=$ds0,".$interfaces{$curif}{factor}.",*", "CDEF:ffout$ifcnt=$ds1,".$interfaces{$curif}{factor}.",*"; ($ds0, $ds1) = ("ffin$ifcnt", "ffout$ifcnt"); } if( $interfaces{$curif}{c2fi} ) { push @params, "CDEF:c2fin$ifcnt=$ds0,1.8,*,32,+"; $ds0 = "c2fin$ifcnt"; } if( $interfaces{$curif}{c2fo} ) { push @params, "CDEF:c2fout$ifcnt=$ds1,1.8,*,32,+"; $ds1 = "c2fout$ifcnt"; } if(!$interfaces{$curif}{noi} ) { if($RRDs::VERSION < 1.00039 ) { $totindef .= ",in$ifcnt,UN,0,$ds0,IF,+"; } else { # $totindef .= ",in$ifcnt,UN,PREV($ds0),$ds0,IF,DUP,UN,EXC,0,EXC,IF,+"; $totindef .= ",$ds0,in$ifcnt,UN,EXC,PREV($ds0),DUP,UN,EXC,0,EXC,IF,EXC,IF,+"; } $incnt++; if( !$interfaces{$curif}{unknasprev} and !$interfaces{$curif}{unknaszero} ) { $greydef .= ",in$ifcnt,UN,+"; } } if(!$interfaces{$curif}{noo} ) { if($RRDs::VERSION < 1.00039 ) { $totoutdef .= ",out$ifcnt,UN,0,$ds1,IF,+"; } else { $totoutdef.= ",$ds1,out$ifcnt,UN,EXC,PREV($ds1),DUP,UN,EXC,0,EXC,IF,EXC,IF,+"; # $totoutdef .= ",out$ifcnt,UN,PREV($ds1),$ds1,IF,DUP,UN,EXC,0,EXC,IF,+"; } $outcnt++; if( !$interfaces{$curif}{unknasprev} and !$interfaces{$curif}{unknaszero} ) { $greydef .= ",out$ifcnt,UN,+"; } } # now for the peaks stuff ($mds0, $mds1) = ("ds0", "ds1"); push @params, "DEF:min$ifcnt=".$defrrd.":$mds0:MAX", "DEF:mout$ifcnt=".$defrrd.":$mds1:MAX"; ($mds0, $mds1) = ("min$ifcnt", "mout$ifcnt"); ### Do this if we are using BITS if( $interfaces{$curif}{mult} ne 1 ) { push @params, "CDEF:fmin$ifcnt=$mds0,".$interfaces{$curif}{mult}.",*", "CDEF:fmout$ifcnt=$mds1,".$interfaces{$curif}{mult}.",*"; ($mds0, $mds1) = ("fmin$ifcnt", "fmout$ifcnt"); } if( defined $interfaces{$curif}{factor} ) { push @params,"CDEF:ffmin$ifcnt=$mds0," .$interfaces{$curif}{factor}.",*", "CDEF:ffmout$ifcnt=$mds1,".$interfaces{$curif}{factor}.",*"; ($mds0, $mds1) = ("ffmin$ifcnt", "ffmout$ifcnt"); } ### # And the percentages $max1 = $max2 = $interfaces{$curif}{max}; $max1 = $interfaces{$curif}{max1} if(defined $interfaces{$curif}{max1}); $max2 = $interfaces{$curif}{max2} if(defined $interfaces{$curif}{max2}); if( $max1 && $dwmy !~ /s/ ) { push @params, "CDEF:pcin$ifcnt=$ds0,100,*,".$max1.",/", "CDEF:mpcin$ifcnt=$mds0,100,*,".$max1.",/"; } if( $max2 && $dwmy !~ /s/ ) { push @params, "CDEF:pcout$ifcnt=$ds1,100,*,".$max2.",/", "CDEF:mpcout$ifcnt=$mds1,100,*,".$max2.",/"; } if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i and $lin and $lout ) { $lout = ""; $lin = $interfaces{$curif}{desc}; $lin =~ s/:/\\:/g; $lin = ":$lin\\l"; } else { if( !$interfaces{$interface}{nolegend} and !$interfaces{$interface}{nodetails} and $dwmy !~ /s/ ) { push @params, "COMMENT:".decolon($interfaces{$curif}{desc}.":\\l") if(!$interfaces{$interface}{noi} and !$interfaces{$interface}{noo}); } } if(! $interfaces{$interface}{nolines} ) { $c=""; if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}) { $c = shift @clr; push @clr, $c; if( !$stacking ) { push @params, "LINE$linewidth:$ds0$c$lin" ; } elsif( $stacking > 1 ) { push @params, "STACK:$ds0$c$lin" ; } else { push @params, "AREA:$ds0$c$lin" ; $stacking = 2; } } if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}) { $c = "" if( $c and $interfaces{$interface}{graphstyle}!~/mirror/i ); if(!$c) { $c = shift @clr; push @clr, $c; } if( !$stacking ) { if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { push @params, "CDEF:mirror$ifcnt=$ds1,-1,*"; push @params, "LINE$linewidth:mirror$ifcnt$c$lout"; } else { push @params, "LINE$linewidth:$ds1$c$lout" ; } } elsif( $stacking > 1 ) { push @params, "STACK:$ds1".$c.$lout ; } else { push @params, "AREA:$ds1".$c.$lout ; $stacking = 2; } } } # nolines # now for the labels at the bottom if( !$interfaces{$interface}{nolegend} and !$interfaces{$interface}{nodetails} ) { if( $dwmy !~ /s/ ) { if( $max1 ) { if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}) { push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g" ; push @params ,"GPRINT:mpcin$ifcnt:MAX: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params,"GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g" ; push @params ,"GPRINT:pcin$ifcnt:AVERAGE: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params,"GPRINT:$ds0:LAST: $gcurlbl $sin\\g" ; push @params ,"GPRINT:pcin$ifcnt:LAST: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params, "COMMENT:\\l" ; } if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}) { push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g" ; push @params ,"GPRINT:mpcout$ifcnt:MAX: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params,"GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g" ; push @params ,"GPRINT:pcout$ifcnt:AVERAGE: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params,"GPRINT:$ds1:LAST: $gcurlbl $sout\\g" ; push @params ,"GPRINT:pcout$ifcnt:LAST: (%2.0lf%%)\\g" if($interfaces{$curif}{percent}); push @params, "COMMENT:\\l" ; } } else { push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g", "GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g", "GPRINT:$ds0:LAST: $gcurlbl $sin\\l" if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}); push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g", "GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g", "GPRINT:$ds1:LAST: $gcurlbl $sout\\l" if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}); } } else { ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); $legendi = $interfaces{$curif}{legendi} if(defined $interfaces{$curif}{legendi}); $legendo = $interfaces{$curif}{legendo} if(defined $interfaces{$curif}{legendo}); if( $interfaces{$interface}{overridelegend} and $interfaces{$curif}{shdesc} and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} or $interfaces{$curif}{noo} or $interfaces{$curif}{noi} ) ) { $legendi = $legendo = $interfaces{$curif}{shdesc}.':'; } $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; $legendi =~ s/%/%%/g; $legendo =~ s/%/%%/g; push @params, "PRINT:$mds0:MAX:".$q->b($legendi)." $maxlbl $ssin, ", "PRINT:$ds0:AVERAGE:$avglbl $ssin, ", "PRINT:$ds0:LAST:$lastlbl $ssin ".$q->br if(!$interfaces{$interface}{noi} and !$interfaces{$curif}{noi}); push @params, "PRINT:$mds1:MAX:".$q->b($legendo)." $maxlbl $ssout, ", "PRINT:$ds1:AVERAGE:$avglbl $ssout, ", "PRINT:$ds1:LAST:$lastlbl $ssout ".$q->br if(!$interfaces{$interface}{noo} and !$interfaces{$curif}{noo}); } # s mode } # not nolegend mode } # end of loop through interfaces # add total line if necessary if($interfaces{$interface}{withtotal} or $interfaces{$interface}{withaverage} ) { push @params, $totindef if(!$interfaces{$interface}{noi} and $incnt); push @params, $totoutdef if(!$interfaces{$interface}{noo} and $outcnt); ($sin,$sout,$sext ,$ssin,$ssout,$ssext) = sinout($interface,0); $lin = langmsg(6100,"Total")." ".$interfaces{$interface}{legend1}; $lin = $interfaces{$interface}{legendti} if($interfaces{$interface}{legendti}); $lin = substr($lin.' ',0,30); if($interfaces{$interface}{noo} or !$outcnt) { $lin .= "\\l"; } $lout = langmsg(6100,"Total")." ".$interfaces{$interface}{legend2}."\\l"; $lout = $interfaces{$interface}{legendto}."\\l" if($interfaces{$interface}{legendto}); $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; $lin = ':'.$lin if($lin); $lout = ':'.$lout if($lout); if($interfaces{$interface}{withtotal} ) { if($interfaces{$interface}{nolegend} or $dwmy =~ /s/ ) { $lin = $lout = ""; } elsif( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { $lout = ""; $lin = langmsg(6101,"Total values"); $lin =~ s/:/\\:/g; $lin = ":$lin\\l"; } else { push @params, "COMMENT:" .decolon(langmsg(6101,"Total values").":\\l") if(!$interfaces{$interface}{noi} and !$interfaces{$interface}{noo} and !$interfaces{$interface}{nodetails}); } $c = ""; if(!$interfaces{$interface}{noi} and $incnt ) { $c = shift @clr; push @clr, $c; push @params, "LINE$linewidth:totin$c$lin"; } if(!$interfaces{$interface}{noo} and $outcnt ) { $c = "" if( $c and $interfaces{$interface}{graphstyle}!~/mirror/i ); if(!$c) { $c = shift @clr; push @clr, $c;} if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { push @params, "CDEF:mtotout=totout,-1,*"; push @params, "LINE$linewidth:mtotout$c$lout"; } else { push @params, "LINE$linewidth:totout$c$lout"; } } if( $dwmy !~ /s/ ) { if(!$interfaces{$interface}{nolegend} ) { push @params, "GPRINT:totin:MAX:$gmaxlbl $sin\\g", "GPRINT:totin:AVERAGE: $gavglbl $sin\\g", "GPRINT:totin:LAST: $gcurlbl $sin\\l" if(!$interfaces{$interface}{noi} and $incnt); push @params, "GPRINT:totout:MAX:$gmaxlbl $sout\\g", "GPRINT:totout:AVERAGE: $gavglbl $sout\\g", "GPRINT:totout:LAST: $gcurlbl $sout\\l" if(!$interfaces{$interface}{noo} and $outcnt); } } else { ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); $legendi = $interfaces{$interface}{legendi} if(defined $interfaces{$interface}{legendi}); $legendo = $interfaces{$interface}{legendo} if(defined $interfaces{$interface}{legendo}); $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; push @params, "PRINT:totin:MAX:".$q->b(langmsg(2100,"Total")."\\:")." $maxlbl $ssin, ", "PRINT:totin:AVERAGE:$avglbl $ssin, ", "PRINT:totin:LAST:$lastlbl $ssin ".$q->br if(!$interfaces{$interface}{noi} and $incnt); push @params, "PRINT:totout:MAX:".$q->b(langmsg(2100,"Total")."\\:")." $maxlbl $ssout, ", "PRINT:totout:AVERAGE:$avglbl $ssout, ", "PRINT:totout:LAST:$lastlbl $ssout ".$q->br if(!$interfaces{$interface}{noo} and $outcnt); } } } # add average line if necessary if($interfaces{$interface}{withaverage} ) { push @params,"CDEF:avgin=totin,$incnt,/" if(!$interfaces{$interface}{noi} and $incnt); push @params,"CDEF:avgout=totout,$outcnt,/" if(!$interfaces{$interface}{noo} and $outcnt); $lin = "Average ".$interfaces{$interface}{legend1}; $lin = $interfaces{$interface}{legendai} if($interfaces{$interface}{legendai}); $lin = substr($lin.' ',0,30); $lout= "Average ".$interfaces{$interface}{legend2}."\\l"; if($interfaces{$interface}{noo} or !$outcnt){ $lin .= "\\l"; } $lout = $interfaces{$interface}{legendao}."\\l" if($interfaces{$interface}{legendao}); $lin =~ s/:/\\:/g; $lout=~ s/:/\\:/g; $lin = ':'.$lin if($lin); $lout = ':'.$lout if($lout); if($interfaces{$interface}{nolegend} or $dwmy=~ /s/ ) { $lin = $lout = ""; } elsif( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { $lout = ""; $lin = langmsg(6901,"Average values"); $lin =~ s/:/\\:/g; $lin = ":$lin\\l"; } else { push @params, "COMMENT:" .decolon(langmsg(6901,"Average values").":\\l") if(!$interfaces{$interface}{noi} and !$interfaces{$interface}{noo} and !$interfaces{$interface}{nodetails}); } $c = ""; if(!$interfaces{$interface}{noi} and $incnt) { $c = shift @clr; push @clr, $c; push @params, "LINE$linewidth:avgin$c$lin"; } if(!$interfaces{$interface}{noo} and $outcnt) { $c = "" if( $c and $interfaces{$interface}{graphstyle}!~/mirror/i ); if(!$c) { $c = shift @clr; push @clr, $c;} if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i ) { push @params, "CDEF:mavgout=avgout,-1,*"; push @params, "LINE$linewidth:mavgout$c$lout"; } else { push @params, "LINE$linewidth:avgout$c$lout"; } } if( $dwmy !~ /s/ ) { if(!$interfaces{$interface}{nolegend} ) { push @params, "GPRINT:avgin:MAX:$gmaxlbl $sin\\g", "GPRINT:avgin:AVERAGE: $gavglbl $sin\\g", "GPRINT:avgin:LAST: $gcurlbl $sin\\l" if(!$interfaces{$interface}{noi} and $incnt); push @params, "GPRINT:avgout:MAX:$gmaxlbl $sout\\g", "GPRINT:avgout:AVERAGE: $gavglbl $sout\\g", "GPRINT:avgout:LAST: $gcurlbl $sout\\l" if(!$interfaces{$interface}{noo} and $outcnt); } } else { ($legendi,$legendo)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:")); $legendi = $interfaces{$interface}{legendi} if(defined $interfaces{$interface}{legendi}); $legendo = $interfaces{$interface}{legendo} if(defined $interfaces{$interface}{legendo}); $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; push @params, "PRINT:avgin:MAX:".$q->b("$avglbl\\:")." $maxlbl $ssin, ", "PRINT:avgin:AVERAGE:$avglbl $ssin, ", "PRINT:avgin:LAST:$lastlbl $ssin ".$q->br if(!$interfaces{$interface}{noi} and $incnt); push @params, "PRINT:avgout:MAX:".$q->b("$avglbl\\:")." $maxlbl $ssout, ", "PRINT:avgout:AVERAGE:$avglbl $ssout, ", "PRINT:avgout:LAST:$lastlbl $ssout ".$q->br if(!$interfaces{$interface}{noo} and $outcnt); } # small graph } # with average line # Greyout if no data at all. if($greydef) { $greydef = "CDEF:greyout=$greydef,$incnt,$outcnt,+,EQ,INF,0,IF"; push @params, $greydef, "AREA:greyout#d0d0d0"; if( $interfaces{$interface}{graphstyle} and $interfaces{$interface}{graphstyle}=~/mirror/i and !$interfaces{$interface}{unknasprev}) { $greydef = "CDEF:mgreyout=greyout,-1,*"; push @params, $greydef, "AREA:mgreyout#d0d0d0"; push @params, "HRULE:0#ff0000"; } } } # usr_params sub rtr_params(@) { my($ds0,$ds1,$ds2,$mds0,$mds1, $mds2)=("","","","","",""); my($lin, $lout, $mlin, $mlout, $lextra); my($dwmy,$interface) = @_; my($ssin, $ssout, $sin, $sout, $ssext, $sext); my($l,$defrrd); my($workday) = 0; my($legendi,$legendo, $legendx); my(@clr, $escunit); my($max1, $max2); my($havepeaks) = 0; my($graphstyle) = ""; my($maxlbl,$avglbl,$curlbl,$lastlbl) = ('Max','Avg','Cur','Last'); my($gmaxlbl,$gavglbl,$gcurlbl,$glastlbl); $maxlbl = langmsg(2200,$maxlbl); $avglbl = langmsg(2201,$avglbl); $curlbl = langmsg(2202,$curlbl); $lastlbl = langmsg(2203,$lastlbl); $gmaxlbl = langmsg(6200,$maxlbl); $gavglbl = langmsg(6201,$avglbl); $gcurlbl = langmsg(6202,$curlbl); $glastlbl = langmsg(6203,$lastlbl); $graphstyle = lc $interfaces{$interface}{graphstyle} if( $interfaces{$interface}{graphstyle} ); # are we peak lines on this graph? if($graphstyle !~ /stack/ ) { if(!defined $config{'routers.cgi-withpeak'} or $config{'routers.cgi-withpeak'} =~ /y/i ) { if( $dwmy =~ /[wmy]/ or ( $dwmy =~ /d/ and $usesixhour )) { my($pat) = ''; if( defined $interfaces{$interface}{withpeak} ) { $pat = '[a'.$interfaces{$interface}{withpeak}.']'; $havepeaks = 1 if( $dwmy =~ /$pat/i ); } else { $havepeaks = 1; } } } } # are we going to work out the 'working day' averages as well? if( defined $config{'routers.cgi-daystart'} and defined $config{'routers.cgi-dayend'} and $config{'routers.cgi-daystart'}<$config{'routers.cgi-dayend'} and $dwmy !~ /y/ ){ $workday = 1; } # identify colours if( defined $interfaces{$interface}{colours} ) { @clr = @{$interfaces{$interface}{colours}}; } if(! @clr ) { if( $gstyle =~ /b/ ) { @clr = ("#888888", "#000000", "#cccccc","#444444", "#222222"); } else { @clr = ("#00cc00", "#0000ff","#006600", "#ff00ff", "#ff0000" ); } } $defrrd = $interfaces{$interface}{rrd}; $defrrd =~ s/:/\\:/g; $debugmessage .= "RRD: $defrrd\n"; $escunit = $interfaces{$interface}{unit}; $escunit =~ s/%/%%/g; $escunit =~ s/:/\\:/g; $escunit =~ s/ / /g; ($sin,$sout,$sext,$ssin,$ssout,$ssext) = sinout($interface,0); if ( $dwmy =~ /s/ ) { $lin=""; $lout=""; $lextra=""; $mlin=""; $mlout=""; } else { $lin = langmsg(6405,"Inbound"); $lout = langmsg(6406,"Outbound"); $mlin = langmsg(6407,"Peak Inbound"); $mlout = langmsg(6408,"Peak Outbound"); $lin = $interfaces{$interface}{legend1} if( defined $interfaces{$interface}{legend1} ); $lout = $interfaces{$interface}{legend2} if( defined $interfaces{$interface}{legend2} ); $mlin = $interfaces{$interface}{legend3} if( defined $interfaces{$interface}{legend3} ); $mlout = $interfaces{$interface}{legend4} if( defined $interfaces{$interface}{legend4} ); if($interfaces{$interface}{noo} or $havepeaks or ( $graphstyle =~ /range/i )) { $lin .= "\\l"; } $lextra = "Other\\l"; $lextra = $interfaces{$interface}{legend5}."\\l" if( defined $interfaces{$interface}{legend5} ); $lin =~ s/:/\\:/g; $mlin =~ s/:/\\:/g; $lout =~ s/:/\\:/g; $mlout =~ s/:/\\:/g; $lin = ':'.$lin; $lout = ':'.$lout; $mlin = ':'.$mlin; $mlout = ':'.$mlout; $lextra = ':'.$lextra; } $lout .= "\\l" if($lout); $lin = substr( $lin." ",0,30 ) if($lin and !$interfaces{$interface}{noo} and $lin !~ /\\l$/ ); $mlout = substr( $mlout." ",0,30 ) if ($mlout); $mlin = substr( $mlin." ",0,30 ) if ($mlin); if( $interfaces{$interface}{nolegend} ) { $lin = $lout = ""; } ($ds0, $ds1) = ("ds0", "ds1"); if( $interfaces{$interface}{mode} eq "SERVER" ) { ($ds0, $ds1, $ds2) = ("user", "system", "wait") if($interface eq "CPU"); ($ds0, $ds1) = ("page", "page") if($interface eq "Page"); ($ds0, $ds1) = ("usercount", "usercount") if($interface eq "Users"); } # ($ds0, $ds1) = ( $ds1, $ds0 ) if($interfaces{$interface}{reverse}); push @params, "DEF:in=".$defrrd.":$ds0:" # .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE"), ."AVERAGE", "DEF:out=".$defrrd.":$ds1:" # .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE"); ."AVERAGE"; push @params, "DEF:extra=".$defrrd.":$ds2:" # .($interfaces{$interface}{cf}?$interfaces{$interface}{cf}:"AVERAGE") ."AVERAGE" if($ds2); ($ds0, $ds1) = ("in", "out"); $ds2 = "extra" if($ds2); # Try to get around the race condition... This also hides the first UNK point # if($RRDs::VERSION >= 1.00039 ) { # push @params, # "CDEF:racein=$ds0,UN,PREV($ds0),$ds0,IF", # "CDEF:raceout=$ds1,UN,PREV($ds1),$ds1,IF"; # ($ds0, $ds1) = ("racein", "raceout"); # } # Now for unknaszero if( $interfaces{$interface}{unknaszero} ) { push @params, "CDEF:unin=$ds0,UN,0,$ds0,IF", "CDEF:unout=$ds1,UN,0,$ds1,IF"; ($ds0, $ds1) = ("unin", "unout"); } # Now for unknasprev if( $interfaces{$interface}{unknasprev} ) { if($RRDs::VERSION >= 1.00039 ) { push @params, "CDEF:unpin=$ds0,UN,PREV,$ds0,IF", "CDEF:unpout=$ds1,UN,PREV,$ds1,IF"; ($ds0, $ds1) = ("unpin", "unpout"); } } ### do this if we are using BITS if( $interfaces{$interface}{mult} and ($interfaces{$interface}{mult}!=1) ) { push @params, "CDEF:fin=$ds0,".$interfaces{$interface}{mult}.",*", "CDEF:fout=$ds1,".$interfaces{$interface}{mult}.",*"; ($ds0, $ds1) = ("fin", "fout"); } ### if( defined $interfaces{$interface}{factor} ) { push @params, "CDEF:ffin=$ds0,".$interfaces{$interface}{factor}.",*", "CDEF:ffout=$ds1,".$interfaces{$interface}{factor}.",*"; ($ds0, $ds1) = ("ffin", "ffout"); } # now for the peaks stuff ($mds0, $mds1) = ("ds0", "ds1"); if( $interfaces{$interface}{mode} eq "SERVER" ) { ($mds0,$mds1,$mds2) = ("user","system","wait") if($interface eq "CPU"); ($mds0,$mds1) = ("page", "page") if($interface eq "Page"); ($mds0,$mds1) = ("usercount", "usercount") if($interface eq "Users"); } # ($mds0, $mds1) = ("ds1", "ds0") if($interfaces{$interface}{reverse}); push @params, "DEF:min=".$defrrd.":$mds0:MAX", "DEF:mout=".$defrrd.":$mds1:MAX"; ($mds0, $mds1) = ("min", "mout"); if( $interfaces{$interface}{mode} eq "SERVER" and $mds2 ) { push @params, "DEF:mx=".$defrrd.":$mds2:MAX"; $mds2 = "mx"; } ### Do this if we are using BITS if( $interfaces{$interface}{mult} and ($interfaces{$interface}{mult}!=1)) { push @params, "CDEF:fmin=$mds0,".$interfaces{$interface}{mult}.",*", "CDEF:fmout=$mds1,".$interfaces{$interface}{mult}.",*"; ($mds0, $mds1) = ("fmin", "fmout"); } ### if( defined $interfaces{$interface}{factor} ) { push @params, "CDEF:ffmin=$mds0,".$interfaces{$interface}{factor}.",*", "CDEF:ffmout=$mds1,".$interfaces{$interface}{factor}.",*"; ($mds0, $mds1) = ("ffmin", "ffmout"); } # Do the maxima $max1 = $max2 = $interfaces{$interface}{max}; $max1 = $interfaces{$interface}{max1} if(defined $interfaces{$interface}{max1}); $max2 = $interfaces{$interface}{max2} if(defined $interfaces{$interface}{max2}); # Reverse calculations if($interfaces{$interface}{'reverse'}) { push @params, "CDEF:rin=$max1,$ds0,-", "CDEF:mrin=$max1,$mds0,-", "CDEF:rout=$max2,$ds1,-", "CDEF:mrout=$max2,$mds1,-"; ($ds0, $ds1) = ("rin", "rout"); ($mds0, $mds1) = ("mrin", "mrout"); } # And the percentages if($interfaces{$interface}{aspercent}) { push @params, "CDEF:pcin=$ds0,100,*,".$max1.",/", "CDEF:mpcin=$mds0,100,*,".$max1.",/", "CDEF:pcout=$ds1,100,*,".$max2.",/", "CDEF:mpcout=$mds1,100,*,".$max2.",/"; ($mds0, $mds1) = ("mpcin", "mpcout"); ($ds0, $ds1) = ("pcin", "pcout"); } elsif($interfaces{$interface}{dorelpercent}) { # what if ds1=0? No way to avoid potential /0 push @params, "CDEF:pcin=$ds0,100,*,".$ds1.",/", "CDEF:mpcin=$mds0,100,*,".$mds1.",/"; $mds0 = "mpcin"; # note we don't care about OUT as this implies NOO $ds0 = "pcin"; } else { if( $max1 && $dwmy !~ /s/ ) { push @params, "CDEF:pcin=$ds0,100,*,".$max1.",/", "CDEF:mpcin=$mds0,100,*,".$max1.",/"; } if( $max2 && $dwmy !~ /s/ ) { push @params, "CDEF:pcout=$ds1,100,*,".$max2.",/", "CDEF:mpcout=$mds1,100,*,".$max2.",/"; } } # Now the workday averages, if required if( $workday ) { # note we must have a DS in there even if it is not used push @params, "CDEF:wdtest=$ds0,POP," ."TIME,3600,/,$timezone,+,DUP,24,/,7,%,DUP,4,LT,EXC,2,GE,+,2,LT," ."EXC,24,%,DUP," .trim($config{'routers.cgi-daystart'}).",GE,EXC," .trim($config{'routers.cgi-dayend'}).",LT,+,2,EQ,1," ."0,IF,0,IF"; # Set to 1 if in working day push @params, "CDEF:wdin=wdtest,$ds0,UNKN,IF", "CDEF:wdout=wdtest,$ds1,UNKN,IF"; push @params, "CDEF:wdx=wdtest,$ds2,UNKN,IF" if($ds2); # mark the working day background, if not in b&w mode if( $gstyle !~ /b/ ) { push @params, "CDEF:wd=wdtest,INF,0,IF", "AREA:wd#ffffcc"; if($graphstyle=~/mirror/) { push @params, "CDEF:mwd=wd,-1,*", "AREA:mwd#ffffcc"; } } } if( $interfaces{$interface}{available} ) { # availability percentage push @params, "CDEF:apc=in,UN,out,UN,+,2,EQ,0,100,IF"; # Now, the average of apc is the percentage availability! } if( $interfaces{$interface}{mode} eq "SERVER" and $ds2 ) { push @params, "AREA:$ds0".$clr[0].$lin, "STACK:$ds1".$clr[1].$lout, "STACK:$ds2".$clr[4].$lextra; } else { # now for the actual lines : put the peaklines for d only if we have a 6 hr # dont forget to use more friendly colours if this is black and white mode push @params, "LINE$linewidth:$mds0".$clr[2].$mlin if($havepeaks and !$interfaces{$interface}{noi}); # outbound is done later... push @params, "AREA:$ds0".$clr[0].$lin if(!$interfaces{$interface}{noi}); if(!$interfaces{$interface}{noo}) { if( $graphstyle =~ /stack/i ) { push @params, "STACK:$ds1".$clr[1].$lout; } elsif( $graphstyle =~ /range/i ) { push @params, "AREA:$ds1#ffffff"; # erase lower part # if workingday active, put HIGHLIGHTED lower in if( $workday and $gstyle !~ /b/) { push @params, "CDEF:lwday=wdin,UN,0,$ds1,IF", "AREA:lwday#ffffcc"; } push @params, "LINE$linewidth:$ds1".$clr[0]; # replace last pixel } elsif( $graphstyle =~ /mirror/i ) { if($havepeaks) { push @params, "CDEF:mmirror=$mds1,-1,*"; push @params, "LINE$linewidth:mmirror".$clr[3].$mlout; } push @params, "CDEF:mirror=$ds1,-1,*"; push @params, "AREA:mirror".$clr[1].$lout; } else { # we do it here so it isnt overwritten by the incoming area if($havepeaks) { push @params, "LINE$linewidth:$mds1".$clr[3].$mlout; } # with peaks push @params, "LINE$linewidth:$ds1".$clr[1].$lout; } } } # server mode # data unavailable if(!$interfaces{$interface}{unknaszero} and !$interfaces{$interface}{unknasprev}) { push @params, "CDEF:down=in,UN,out,UN,+,2,EQ,INF,0,IF","AREA:down#d0d0d0"; if($graphstyle=~/mirror/i) { push @params, "CDEF:mdown=down,-1,*","AREA:mdown#d0d0d0"; push @params, "HRULE:0#ff0000"; } } # thresholds if( $dwmy !~ /s/ ) { my($tdone) = 0; my( $tlab ) = ""; my($tlabbit); foreach ( qw/i o/ ) { $tlabbit = ""; if(defined $interfaces{$interface}{"threshmin$_"}) { $tlabbit = doformat($interfaces{$interface}{"threshmin$_"}, $interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit}; } if(defined $interfaces{$interface}{"threshmax$_"}) { $tlabbit .= ", " if($tlabbit); $tlabbit .= doformat($interfaces{$interface}{"threshmax$_"}, $interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit}; } if($tlabbit) { $tlab .= " (".$interfaces{$interface}{"legend$_"}." ".$tlabbit.")"; } } $tlab =~ s/:/\\:/g; foreach ( qw/maxi maxo mini mino/ ) { if(defined $interfaces{$interface}{"thresh$_"} ) { if($tdone) { push @params, "HRULE:" .$interfaces{$interface}{"thresh$_"} ."#ffa0a0"; } else { push @params, "HRULE:" .$interfaces{$interface}{"thresh$_"} ."#ffa0a0:".langmsg(6105,"Thresholds")."$tlab\\l"; $tdone = 1; } } } } # the max line if($interfaces{$interface}{aspercent} or $interfaces{$interface}{dorelpercent}) { $interfaces{$interface}{max} = 100; $interfaces{$interface}{max1} = 100; $interfaces{$interface}{max2} = 100; } if( $interfaces{$interface}{max} and ! ( defined $config{'routers.cgi-maxima'} and $config{'routers.cgi-maxima'} =~ /n/i ) and !$interfaces{$interface}{nomax} ) { my( $lmax ) = ""; my( $lamax ) = ""; my( $lcol ) = "#ff0000"; $lcol = "#cccccc" if( $gstyle =~ /b/ ); if( $dwmy !~ /s/ ) { if( defined $interfaces{$interface}{mblegend} ) { $lmax = $interfaces{$interface}{mblegend}; $lmax =~ s/:/\\:/g; $lmax = ':'.$lmax; } elsif( $interfaces{$interface}{isif} ) { $lmax =":100% ".langmsg(6103,"Bandwidth"); } else { $lmax =":".langmsg(6102,"Maximum"); } if( $max1 and $max2 and ($max1 != $max2) ) { $lmax .= " (".doformat($max1,$interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit}."," .doformat($max2,$interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit}.")\\l"; } else { $lmax .= " (".doformat($interfaces{$interface}{max}, $interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit}.")\\l"; } if( defined $interfaces{$interface}{absmax} ) { if( defined $interfaces{$interface}{amlegend} ) { $lamax = ":".$interfaces{$interface}{amlegend}; } else { $lamax =":".langmsg(6104,"Hard Maximum"); } $lamax .= " (".doformat($interfaces{$interface}{absmax}, $interfaces{$interface}{fixunits},1) .$interfaces{$interface}{unit}.")\\l"; } if($interfaces{$interface}{aspercent} or $interfaces{$interface}{aspercent}) { $lmax=""; } } if( $graphstyle =~ /mirror/ ) { $max1 = $interfaces{$interface}{max} if(!$max1); $max2 = -$interfaces{$interface}{max} if(!$max2); } if( $max1 and $max2 and ($max1 != $max2)) { push @params, "HRULE:".$max1.$lcol.$lmax; push @params, "HRULE:".$max2.$lcol; } else { push @params, "HRULE:".$interfaces{$interface}{max}.$lcol.$lmax; } if( defined $interfaces{$interface}{absmax} and !$interfaces{$interface}{noabsmax} ) { if( $gstyle =~ /b/ ) { push @params, "HRULE:".$interfaces{$interface}{absmax} ."#aaaaaa$lamax"; } else { push @params, "HRULE:".$interfaces{$interface}{absmax} ."#ff0080$lamax"; } } } # now for the labels at the bottom if( $dwmy !~ /s/ ) { if( $max1 ) { if(!$interfaces{$interface}{noi}) { push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g" ; push @params ,"GPRINT:mpcin:MAX: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params,"GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g" ; push @params ,"GPRINT:pcin:AVERAGE: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params,"GPRINT:$ds0:LAST: $gcurlbl $sin\\g" ; push @params ,"GPRINT:pcin:LAST: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params, "COMMENT:\\l" ; } if(!$interfaces{$interface}{noo}) { push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g" ; push @params ,"GPRINT:mpcout:MAX: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params,"GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g" ; push @params ,"GPRINT:pcout:AVERAGE: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params,"GPRINT:$ds1:LAST: $gcurlbl $sout\\g" ; push @params ,"GPRINT:pcout:LAST: (%2.0lf%%)\\g" if($interfaces{$interface}{percent}); push @params, "COMMENT:\\l" ; } if($ds2) { push @params, "GPRINT:$mds2:MAX:$gmaxlbl $sext\\g" ; push @params,"GPRINT:$ds2:AVERAGE: $gavglbl $sext\\g" ; push @params,"GPRINT:$ds2:LAST: $gcurlbl $sext\\g" ; push @params, "COMMENT:\\l" ; } if($workday) { push @params, "COMMENT:".decolon(langmsg(6106,"Working day averages")."\\g"); push @params,"GPRINT:wdin:AVERAGE: $sin\\g" if(!$interfaces{$interface}{noi}); push @params,"GPRINT:wdout:AVERAGE: $sout\\g" if(!$interfaces{$interface}{noo}); push @params,"GPRINT:wdx:AVERAGE: $sext\\g" if($ds2); push @params, "COMMENT:\\l"; } if( defined $config{'routers.cgi-maxima'} and $config{'routers.cgi-maxima'} =~ /n/i and !$interfaces{$interface}{nomax} ) { my( $comment ); if(defined $interfaces{$interface}{mblegend}) { $comment = $interfaces{$interface}{mblegend}; $comment = "COMMENT:".decolon($comment); } elsif($interfaces{$interface}{isif}) { $comment = "COMMENT:100% ".decolon(langmsg(6103,"Bandwidth")); } else { $comment = "COMMENT:".decolon(langmsg(6102,"Maximum value")); } $comment .= decolon(" ".doformat($interfaces{$interface}{max}, $interfaces{$interface}{fixunits},0) .$escunit."\\l"); push @params, $comment; } } else { push @params, "GPRINT:$mds0:MAX:$gmaxlbl $sin\\g", "GPRINT:$ds0:AVERAGE: $gavglbl $sin\\g", "GPRINT:$ds0:LAST: $gcurlbl $sin\\l" if(!$interfaces{$interface}{noi}); push @params, "GPRINT:$mds1:MAX:$gmaxlbl $sout\\g", "GPRINT:$ds1:AVERAGE: $gavglbl $sout\\g", "GPRINT:$ds1:LAST: $gcurlbl $sout\\l" if(!$interfaces{$interface}{noo}); push @params, "GPRINT:$mds2:MAX:$gmaxlbl $sext\\g", "GPRINT:$ds2:AVERAGE: $gavglbl $sext\\g", "GPRINT:$ds2:LAST: $gcurlbl $sext\\l" if($ds2); if($workday) { push @params, "COMMENT:".decolon(langmsg(6106,"Working day averages")."\\g"); push @params,"GPRINT:wdin:AVERAGE: $sin\\g" if(!$interfaces{$interface}{noi}); push @params,"GPRINT:wdout:AVERAGE: $sout\\g" if(!$interfaces{$interface}{noo}); push @params,"GPRINT:wdx:AVERAGE: $sext\\g" if($ds2); push @params, "COMMENT:\\l"; } } if( $interfaces{$interface}{available} ) { push @params, "GPRINT:apc:AVERAGE:".langmsg(6107,"Data availability")."\\: %.2lf%%\\l"; } } else { ($legendi,$legendo,$legendx) = (langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); $legendi = $interfaces{$interface}{legendi} if(defined $interfaces{$interface}{legendi}); $legendo = $interfaces{$interface}{legendo} if(defined $interfaces{$interface}{legendo}); $legendx = $interfaces{$interface}{legendx} if(defined $interfaces{$interface}{legendx}); $legendi =~ s/:/\\:/g; $legendo =~ s/:/\\:/g; $legendx=~s/:/\\:/g; $legendi =~ s/%/%%/g; $legendo =~ s/%/%%/g; $legendx=~s/%/%%/g; push @params, "PRINT:$mds0:MAX:".$q->b($legendi)." $maxlbl $ssin, ", "PRINT:$ds0:AVERAGE:$avglbl $ssin, ", "PRINT:$ds0:LAST:$lastlbl $ssin ".$q->br if(!$interfaces{$interface}{noi}); push @params, "PRINT:$mds1:MAX:".$q->b($legendo)." $maxlbl $ssout, ", "PRINT:$ds1:AVERAGE:$avglbl $ssout, ", "PRINT:$ds1:LAST:$lastlbl $ssout ".$q->br if(!$interfaces{$interface}{noo}); push @params, "PRINT:$mds2:MAX:".$q->b($legendx)." $maxlbl $ssext, ", "PRINT:$ds2:AVERAGE:$avglbl $ssext, ", "PRINT:$ds2:LAST:$lastlbl $ssext ".$q->br if($legendx and $ds2); if($workday) { my($pfx) = "".langmsg(3201,"Working day average")."\\:"; my($sfx) = ""; if(!$interfaces{$interface}{noi}) { $sfx = "" if($interfaces{$interface}{noo}); push @params, "PRINT:wdin:AVERAGE:$pfx$ssin" ."$sfx"; $pfx = ""; } push @params, "PRINT:wdout:AVERAGE:$pfx$ssout" ."$sfx" if(!$interfaces{$interface}{noo}); push @params, "PRINT:wdx:AVERAGE:$pfx$ssext" ."$sfx" if($ds2); } } } ######################################################################## # Actually create the necessary graph, and output the IMG tag. sub make_graph(@) { my ($e, $thisgraph, $thisurl, $s, $autoscale); my ($tstr, $gheight, $width, $gwidth, $gtitle, $col); my( $maxwidth ) = 30; my( $endtime, @tparams, $interval, $end ); my($inhtml,$dwmy,$interface) = @_; my($optsuffix) = ""; my(@ctgt) = (); $debugmessage .= "Graph: $interface\n"; # Verify that the rrd file exists if( $interfaces{$interface}{usergraph} ) { # several to check @ctgt = @{$interfaces{$interface}{targets}}; } else { @ctgt = ( $interface ); } foreach (@ctgt) { if(!-r $interfaces{$_}{rrd}) { if ( $pagetype eq "image" ) { if($opt_I) { print "Interface: $interface($_)\nDevice: $router\nError: RRD does not exist\nRRD: ".$interfaces{$_}{rrd}."\n"; } else { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); } } else { print $q->h1(langmsg(3003,"RRD database file not found"))."\n"; print "The file ".$interfaces{$_}{rrd} ." does not exist, or is unreadable. This file is created by MRTG when it first runs successfully on the " .$routers{$router}{file}." file.\n".$q->br ."Please check that you have collected data via MRTG and stored it into the RRD database without errors.".$q->br."\n"; } return; } } # Shall we scale it, etc $autoscale = 1; $s = $dwmy; $s =~ s/s//; if( $interfaces{$interface}{unscaled} ) { $autoscale = 0 if ($interfaces{$interface}{unscaled} =~ /$s/i); } $tstr = "6-hour" if( $dwmy =~ /6/ ) ; $tstr = "Daily" if( $dwmy =~ /d/ ) ; $tstr = "Weekly" if( $dwmy =~ /w/ ) ; $tstr = "Monthly" if( $dwmy =~ /m/ ) ; $tstr = "Yearly" if( $dwmy =~ /y/ ) ; $gtitle = $interfaces{$interface}{desc}; if( ($dwmy.$gstyle)=~/s/ ) { if($gstyle=~/x/) { $maxwidth = 50; } elsif($gstyle=~/l/) { $maxwidth = 40; } else { $maxwidth = 30; } } if(!$gtitle or ((length($gtitle)>$maxwidth)and(($dwmy.$gstyle) =~ /s/))) { $gtitle = ""; $gtitle .= $routers{$router}{shdesc}.": " if( defined $routers{$router}{shdesc}); $gtitle .= $interfaces{$interface}{shdesc}; } $gtitle = $q->unescape($gtitle); $gtitle =~ s/ / /g; $gtitle =~ s/&/&/g; @params = (); $optsuffix = "r1" if($uopts =~ /r/ ); $optsuffix = "r2" if($uopts =~ /R/ ); $optsuffix = "-$optsuffix" if($optsuffix); $thisgraph = "${router}-${interface}-${dwmy}-${gstyle}${optsuffix}.${graphsuffix}"; $thisgraph = "${archdate}-${thisgraph}" if($archdate); $thisgraph = "$language-$thisgraph" if($language); $thisgraph =~ s/[\?#\/\\]//g; $thisurl = $config{'routers.cgi-graphurl'}."/".$q->escape($thisgraph); $thisgraph = $config{'routers.cgi-graphpath'}.$pathsep.$thisgraph; # width is the data unit width (400 max). gwidth is the pixel width of # the actual graph. Thus, if gwidth > width, it is stretched. # Short: for PDAs, unstretched, shorter data window # Stretch: normal graph size, short data window (for easier viewing) # Long: normal data width, slightly bigger graph (for 800/600 screens) # Xlong: normal data width, double graph size (for 1024/768 screens) # gheight is the height of the graphic. This is doubled for # Tall (n2), big (l2) and huge (x2). # The 1st char is the width indicator, then optional 2 (double height) and # b (black & white) if ( $gstyle =~ /^s/ ) { $width = 200; $gwidth = 200; } #short elsif ( $gstyle =~ /^t/ ) { $width = 200; $gwidth = 400; } #stretch elsif ( $gstyle =~ /^l/ ) { $width = 400; $gwidth = 530; } #long elsif ( $gstyle =~ /^x/ ) { $width = 400; $gwidth = 800; } #xlong else { $width = 400; $gwidth = 400; } # default (normal) if ( $gstyle =~ /2/ ) { $gheight = 200; } elsif ( $gstyle =~ /3/ ) { $gheight = 300; } else { $gheight = 100; } # now, if $dwmy contains an s, this is a summary graph, and should be # half of the expected data width and half the expected screen width. # We also force the graph to be normal height. # The magic 60 in the graph width is the width of the axis, as gwidth is # the width of the AXIS, not the width of the graphic. if ( $dwmy =~ /s/ ) { $width /= 2; $gwidth = $gwidth/2 - 60; $gheight = 100; } push @params, $thisgraph; if( $graphsuffix eq "png" ) { push @params, '--imgformat',uc $graphsuffix; } push @params,"--base", $k; push @params,"--lazy" if($dwmy !~ /s/); # only if we dont need PRINT push @params, "--interlaced"; # -l 0 removed if($interfaces{$interface}{fixunits} and $RRDs::VERSION >= 1.00030 ) { if($interfaces{$interface}{exponent}) { push @params,"--units-exponent",$interfaces{$interface}{exponent}; } else { push @params,"--units-exponent",0; } } push @params,"--force-rules-legend" if($RRDs::VERSION >= 1.00047); push @params,"--slope-mode" if(($RRDs::VERSION >= 1.2 ) and defined $config{'routers.cgi-slope'} and ($config{'routers.cgi-slope'}=~/[y1]/i) ); # time window: save these, we may need them again @tparams = (); $end = 'now'; $endtime = time; if($uselastupdate > 1 and $archivetime) { $end = $endtime = $archivetime; } elsif($lastupdate and $uselastupdate) { $end = $endtime = $lastupdate; } else { $end = $endtime = 300*int($endtime/300); # 5min boundary } if( $dwmy =~ /-/ ) { if ( $dwmy =~ /6/ ) { push @tparams, "-e", "$end-6h"; $endtime -= (6*3600); } if ( $dwmy =~ /d/ ) { push @tparams, "-e", "$end-24h"; $endtime -= (24*3600); } if ( $dwmy =~ /w/ ) { push @tparams, "-e", "$end-7d"; $endtime -= (7*24*3600); } if ( $dwmy =~ /m/ ) { push @tparams, "-e", "$end-30d"; $endtime -= (30*24*3600); } if ( $dwmy =~ /y/ ) { push @tparams, "-e", "$end-365d"; $endtime -= (365*24*3600); } } else { push @tparams, "-e", $end; } if ( $dwmy =~ /6/ ) { push @tparams, "-s", "end".(-1 * $width)."m" ; $interval = "60"; } if ( $dwmy =~ /d/ ) { push @tparams, "-s", "end".(-5 * $width)."m" ; $interval = "300"; } if ( $dwmy =~ /w/ ) { push @tparams, "-s", "end".(-25 * $width)."m" ; $interval = "1800"; } if ( $dwmy =~ /m/ ) { push @tparams, "-s", "end".(-2 * $width)."h" ; $interval = "7200"; } if ( $dwmy =~ /y/ ) { push @tparams, "-s", "end".(-1 * $width)."d" ; $interval = "86400"; } push @params, @tparams; # only force the minimum upper-bound of graph if we have a max, # and we dont have maxima=n, and we dont have unscaled=n if( $uopts =~ /r/i ) { # force upper limit to be 2xMax(avgs) if r, and Max(avgs) if R my($ulim) = 0; my($ai,$ao, $e, $start, $names, $data); my(@t) = ($interface); my($thistarg, $thislim,$lookback); # multiple targets? @t = @{$interfaces{$interface}{targets}} if($interfaces{$interface}{usergraph}); # find out average value $e = int($lastupdate/$interval)*$interval; $lookback = 10; $lookback = 200 if($uopts =~ /r/); # look back further # this _should_ return only one line of values... foreach $thistarg ( @t ) { ($start,$interval,$names,$data) = RRDs::fetch($interfaces{$thistarg}{rrd}, "AVERAGE", "-r", $interval, "-s", "end-".($lookback*$interval), "-e", $e); ($ai,$ao) = get_avg($data); if($ao > $ai) { $thislim = $ao; } else { $thislim = $ai; } $thislim = $ao if($interfaces{$thistarg}{noi}); $thislim = $ai if($interfaces{$thistarg}{noo}); if( $interfaces{$interface}{withtotal} and $interfaces{$interface}{usergraph} ) { $ulim += $thislim; } else { $ulim = $thislim if($thislim > $ulim); } } $ulim *= 1.1; # just give a little more space # now we need to multiply, if appropriate $ulim *= $interfaces{$interface}{mult} if($interfaces{$interface}{mult}); $ulim *= $interfaces{$interface}{factor} if(defined $interfaces{$interface}{factor}); $ulim = int(2.0 * $ulim + 0.5) if($uopts =~ /r/); push @params, '-r', '-u', $ulim if($ulim > 0); } else { if($interfaces{$interface}{upperlimit}) { push @params, '-u', $interfaces{$interface}{upperlimit}; } elsif( ! $autoscale ) { if( $interfaces{$interface}{max} and ( !defined $config{'routers.cgi-maxima'} or $config{'routers.cgi-maxima'} !~ /n/i ) ) { push @params, '-u', $interfaces{$interface}{max} ; } else { push @params, '-u', 0.1; # For sanity } } else { push @params, '-u', 0.1; # For sanity } # could have added a "-r" there to enforce the upper limit rigidly push @params, '--rigid' if($interfaces{$interface}{rigid}); } if($interfaces{$interface}{lowerlimit}) { push @params, '--lower-limit', $interfaces{$interface}{lowerlimit}; push @params, '-r' if($interfaces{$interface}{rigid}); } push @params, "-w", $gwidth, "-h", $gheight; push @params,"--x-grid","MINUTE:15:HOUR:1:HOUR:1:0:$dailylabel" if ( $dwmy =~ /6/ ); push @params,"--x-grid","HOUR:1:HOUR:24:HOUR:2:0:$dailylabel" if ( $dwmy =~ /d/ ); push @params,"--x-grid","HOUR:6:DAY:1:DAY:1:86400:%a" if ( $dwmy =~ /w/ ); push @params,"--x-grid","DAY:1:WEEK:1:WEEK:1:604800:Week" .(($NT and $RRDs::VERSION < 1.00039)?"_":" ").$monthlylabel if ( $dwmy =~ /m/ and $RRDs::VERSION >= 1.00029 ); push @params,"--title", $gtitle; if ( defined $interfaces{$interface}{ylegend} ) { push @params, "--vertical-label", $interfaces{$interface}{ylegend}; # push @params, "-U", $interfaces{$interface}{unit} # if($interfaces{$interface}{unit}); } else { push @params, "--vertical-label", $interfaces{$interface}{unit}; } # Horizontal rules if( defined $interfaces{$interface}{hrule} and $dwmy!~/s/ ) { $col = 4; foreach ( @{$interfaces{$interface}{hrule}} ) { push @params, "HRULE:".$_->{value}."#" .((sprintf "%x",$col) x 6) .":".$_->{desc}." ( " .doformat($_->{value},$interfaces{$interface}{fixunits},0) .$interfaces{$interface}{unit} .")\\l"; $col += 1; } } if( $interfaces{$interface}{usergraph} ) { usr_params($dwmy,$interface); } else { rtr_params($dwmy,$interface); } if ( defined $config{'routers.cgi-withdate'} and $config{'routers.cgi-withdate'}=~/y/ ) { push @params, "COMMENT:".decolon(shortdate($endtime))."\\r"; } ( $rrdoutput, $rrdxsize, $rrdysize ) = RRDs::graph(@params); $e = RRDs::error(); if ( $pagetype eq "image" ) { if($e) { if($opt_I) { print "Device: $router\nTarget: $interface\n"; print "Error: $e\n"; } else { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); } } else { # output the graphic directly from disk open GRAPH, "<$thisgraph"; binmode GRAPH; binmode STDOUT; print $q->header({ -type=>"image/$graphsuffix", -expires=>"now", -Content-Disposition=>"filename=\"image.$graphsuffix\"" }) if(!$opt_I); while( ) { print; } close GRAPH; } return; } if ( $e ) { if( $inhtml ) { print $q->p("RRD Error: $e"),"\n"; print $q->p("You can visit the configuration verification page " .$q->a({href=>("$meurlfull?page=verify&rtr=" .$q->escape($router)),target=>"_new"},"here.")); print $q->p("RRD: ".$interfaces{$interface}{rrd}.$q->br. "Device: [$router] ".$routers{$router}{desc}.$q->br. "Interface: $interface".$q->br. "Interfaces: ".(join ",",keys(%interfaces)) ); print "Params: ".(join " ",@params).$q->br; } else { print "Error generating graph:\n$e\n"; } } elsif( ! -f $thisgraph ) { if( $inhtml ) { print $q->h2("Graph was not created!"); print $q->p("Probably, no data is available for the requested time period."); print $q->p("RRD: ".$interfaces{$interface}{rrd}.$q->br. "Device: [$router] ".$routers{$router}{desc}.$q->br. "Interface: $interface" ); } else { print "Error generating graph: Probably no data available for that time period.\n"; } } else { print "\n" ."\n" ."\n" if( $config{'web-debug'} ); if($inhtml) { my($element) = "igraph$dwmy"; my($tzoffset) = ($timezone*3600); # default to server's timezone if($interfaces{$interface}{timezone}) { my($savetz) = $ENV{TZ}; $ENV{TZ}=$interfaces{$interface}{timezone}; POSIX::tzset(); $tzoffset = (localtime(86400))[2]; # -0 $tzoffset -= 24 if( (localtime(86400))[3] != 2 ); $tzoffset *= 3600; $ENV{TZ}=$savetz; print "\n"; } print $q->img({src=>$thisurl,alt => $gtitle,border => 0, width => $rrdxsize, height => $rrdysize, name => $element, onMouseOver => "timepopup(this,'$element',$gwidth,$gheight,$interval,$endtime,$width,$tzoffset)", onMouseMove => "mousemove(event)", onMouseOut => "clearpopup()" }); } if( $archiveme ) { # copy this graph into the archive dir, # graphdir/file/target/ymdhm-siz.ext my( $arch ) = ""; my( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); $year += 2000 if($year < 100); $year += 1900 if($year < 1000); $arch = $router; $arch =~ s/[\?#\/\\]//g; $arch = $config{'routers.cgi-graphpath'}.$pathsep.$arch; mkdir $arch,0755 if(! -d $arch); $arch .= $pathsep.$interface; mkdir $arch,0755 if(! -d $arch); $min = '0'.$min if($min < 10); $mday = '0'.$mday if($mday < 10); $mon += 1; $mon = '0'.$mon if($mon < 10); $arch .= $pathsep.$year.'-'.$mon.'-' .$mday.'-'.$hour.'-'.$min.'-'.$dwmy.'.'.$graphsuffix; print "\n" if( $config{'web-debug'} ); if( open ARCH, '>'.$arch ) { binmode ARCH; if( open GRAPH, '<'.$thisgraph ) { binmode GRAPH; while ( ) { print ARCH; } if($inhtml) { print $q->br.$q->b(langmsg(9001,"Archived OK")).$q->br."\n"; } else { print langmsg(9001,"Graph archive OK.")."\n"; } close GRAPH; } else { if($inhtml) { print $q->br.$q->b(langmsg(8001,"Archiving FAILED")." (cannot read?!)"); } else { print "Graph archive FAILED (cannot read?!).\n"; } } close ARCH; } else { if($inhtml) { print $q->br.$q->b(langmsg(8001,"Archiving FAILED")." (cannot write)"); } else { print "Graph archive FAILED (cannot write).\n"; } } } } if( $config{'web-debug'} ) { print "\n\n\n\n"; } } ############### # Calculations of average and max from fetched data sub get_max($) { my($rows) = $_[0]; my($maxin, $maxout) = (0,0); foreach ( @$rows ) { $maxin = $$_[0] if($$_[0]>$maxin); $maxout = $$_[1] if($$_[1]>$maxout); } return ($maxin, $maxout); } sub get_avg($) { my($rows) = $_[0]; my($avgin, $avgout) = (0,0); my($numrows) = $#$rows; return (0,0) if($numrows < 1); foreach ( @$rows ) { $avgin += $$_[0]; $avgout += $$_[1]; } $avgin /= ($numrows+1); $avgout /= ($numrows+1); return ($avgin,$avgout); } ####################################################### # For the compact summary. This will call the bar function a lot! # bar images are: $meurl?page=bar&IN=xx&OUT=yy for percentages xx yy # images are 400x15 pixels sub do_compact($) { my ($csvmode) = $_[0]; my ($javascript); my ($curif); my ($e, $interval, $resolution, $rrd, $seconds); my ($curin, $curout, $avgin, $avgout, $maxin, $maxout ); my ($curinpc, $curoutpc, $avginpc, $avgoutpc, $maxinpc, $maxoutpc ); my ($perinpc, $peroutpc, $perin, $perout); my ($start, $from, $step, $names, $values); my ($c,$a,$m,$p,$io, $heading); my ($d, $inarr, $outarr,$barlen); my (@iforder); my ($legendi,$legendo,$fix,$intf); my ($unit) = ""; my ($max1, $max2); if(!$csvmode) { $javascript = make_javascript({}); start_html_ss({ -expires => "+5s", -script => $javascript, -onload => "LoadMenu()", -class=>'compact' }); print "
"; print expandvars($config{'routers.cgi-pagetop'}),"\n" if( defined $config{'routers.cgi-pagetop'} ); print "
"; } else { $comma = substr( $config{'web-comma'},0,1 ) if(defined $config{'web-comma'}); $comma = ',' if(!$comma); print "Target".$comma."Description".$comma."Type".$comma ."Metric 1".$comma."Metric 2\n"; } # # Now for the RRD stuff eval { require 'RRDs.pm'; }; if( $@ ) { if($csvmode) { print "".langmsg(8999,"Error").$comma ."Cannot find RRDs.pm: $@\n"; return; } print $q->h1(langmsg(8999,"Error"))."Cannot find RRDs.pm in ".(join " ",@INC )."\n"; print $q->p("You can visit the configuration verification page " .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), target=>"_new"},"here.")); do_footer(); return; } # First, the header to select which are visible: ($c,$a,$m,$p,$io) = ("","","","","i"); $c = $1 if( $baropts =~ /(c)/i ); # this preserves the case $a = $1 if( $baropts =~ /(a)/i ); $m = $1 if( $baropts =~ /(m)/i ); $p = $1 if( $baropts =~ /(p)/i ); if( $baropts =~ /o/i ) { $io = "o"; } else { $io = "i"; } if(!$csvmode) { print "
"; print "\n"; print "\n"; print "\n"; print "\n"; if( defined $config{'routers.cgi-percentile'} and $config{'routers.cgi-percentile'} =~ /y/i ) { print "\n"; } print "
".langmsg(2302,"Last:")." " .$q->a({href=>"$meurlfull?".optionstring({bars=>"Ci".(lc "$a$m$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by current incoming"}) ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Co".(lc "$a$m$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by current outgoing"}) ); if( $c ) { print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$m$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", border=>0,height=>10,width=>10,alt=>"Remove current bar"}) ); } else { print $q->a({href=>"$meurlfull?".optionstring({bars=>"c$a$m$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", border=>0,height=>10,width=>10,alt=>"Add Current bar"}) ); } print "".langmsg(2303,"Average:")." " .$q->a({href=>"$meurlfull?".optionstring({bars=>"Ai".(lc "$c$m$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by average incoming"}) ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Ao".(lc "$c$m$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by average outgoing"}) ); if( $a ) { print $q->a({href=>"$meurlfull?".optionstring({bars=>"$c$m$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", border=>0,height=>10,width=>10,alt=>"Remove Average bar"}) ); } else { print $q->a({href=>"$meurlfull?".optionstring({bars=>"a$c$m$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", border=>0,height=>10,width=>10,alt=>"Add Average bar"})); } print "".langmsg(2304,"Maximum:")." " .$q->a({href=>"$meurlfull?".optionstring({bars=>"Mi".(lc "$c$a$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by Maximum incoming"}) ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Mo".(lc "$c$a$p")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by Maximum outgoing"}) ); if( $m ) { print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$c$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", border=>0,height=>10,width=>10,alt=>"Remove Maximum bar"})); } else { print $q->a({href=>"$meurlfull?".optionstring({bars=>"m$a$c$p$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", border=>0,height=>10,width=>10,alt=>"Add Maximum bar"})); } print "".langmsg(2305,"95th Percentile:")." " .$q->a({href=>"$meurlfull?".optionstring({bars=>"Pi".(lc "$c$a$m")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-g-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by Incoming 95th percentile"}) ).$q->a({href=>"$meurlfull?".optionstring({bars=>"Po".(lc "$c$a$m")})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}sort-b-vsm.gif", border=>0,height=>10,width=>10,alt=>"Sort by Outgoing 95th percentile"}) ); if( $p ) { print $q->a({href=>"$meurlfull?".optionstring({bars=>"$a$m$c$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}tick-vsm.gif", border=>0,height=>10,width=>10,alt=>"Remove 95th percentile bar"})); } else { print $q->a({href=>"$meurlfull?".optionstring({bars=>"p$a$m$c$io"})}, $q->img({src=>"${config{'routers.cgi-smalliconurl'}}cross-vsm.gif", border=>0,height=>10,width=>10,alt=>"Add 95th percentile bar"})); } print "
\n"; } # end if csvmode # Now, we set up the necessary resolution variables to use in the fetch: $resolution = 60; $interval = "6h"; $seconds = 6*3600; $heading = langmsg(2310,"Six hourly calculations"); if ( $gtype =~ /d/ ) { $resolution=300; $interval="24h"; $seconds=86400; $heading = langmsg(2311,"Daily calculations"); } elsif ($gtype =~ /w/){ $resolution=1800; $interval="7d"; $seconds=7*86400; $heading = langmsg(2312,"Weekly calculations"); } elsif ($gtype =~ /m/){ $resolution=7200; $interval="1month"; $seconds=30*86400; $heading = langmsg(2313,"Monthly calculations"); } elsif ($gtype =~ /y/){ $resolution=86400; $interval="1y"; $seconds=365*86400; $heading = langmsg(2314,"Yearly calculations"); } if(!$csvmode) { print $q->center($q->h2({class=>'compact'},$routers{$router}{desc}))."\n" if($routers{$router}{desc}); print $q->h3({class=>'compact'},$heading); } # we now process each interface with incompact=>1 in turn. foreach $curif ( keys(%interfaces) ) { next if(!$curif); # avoid rogue records next if(!$interfaces{$curif}{incompact}); $interfaces{$curif}{errors} = ""; # now we fetch the necessary information from the RRD $curin = $maxin = $avgin = -1; # error $from = "now"; $e = 0; $rrd = $interfaces{$curif}{rrd}; if( $gtype =~ /-/ ) { $from = "now-$interval"; } elsif($uselastupdate > 1 and $archivetime) { $from = $archivetime; } elsif($uselastupdate) { $from = RRDs::last($rrd); $e = RRDs::error(); if($e) { $from = "now"; $interfaces{$curif}{errors}.= $q->br.$q->small(langmsg(8999,"Error").": $e")."\n"; } } $max1 = $max2 = $interfaces{$curif}{max}; $max1 = $interfaces{$curif}{max1} if(defined $interfaces{$curif}{max1}); $max2 = $interfaces{$curif}{max2} if(defined $interfaces{$curif}{max2}); $lastupdate = $from; if( $c ) { ( $start, $step, $names, $values ) = RRDs::fetch($rrd,"AVERAGE","-s","$from-$resolution", "-e",$from,"-r",$resolution); $e = RRDs::error(); if($e) { $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); } else { ( $curin, $curout ) = @{$values->[0]}; $curin *= $interfaces{$curif}{mult}; $curout *= $interfaces{$curif}{mult}; $curin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $curout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $curin = 0 if($interfaces{$curif}{noi}); $curout= 0 if($interfaces{$curif}{noo}); } if(defined $curin) { $curinpc = $curin*100.0/$max1; } else { $curin = -1; $curinpc = 0; } if(defined $curout) { $curoutpc = $curout*100.0/$max2; } else { $curout = -1; $curoutpc = 0; } $interfaces{$curif}{barcurin} = $curin; $interfaces{$curif}{barcurinpc} = $curinpc; $interfaces{$curif}{barcurout} = $curout; $interfaces{$curif}{barcuroutpc} = $curoutpc; } # c if( $a ) { ( $start, $step, $names, $values ) = RRDs::fetch($rrd,"AVERAGE","-s","$from-$interval", "-e",$from,"-r",$seconds); $e = RRDs::error(); if($e) { $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); } else { ($avgin, $avgout) = get_avg($values); $avgin *= $interfaces{$curif}{mult}; $avgout *= $interfaces{$curif}{mult}; $avgin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $avgout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $avgin = 0 if($interfaces{$curif}{noi}); $avgout= 0 if($interfaces{$curif}{noo}); } if(defined $avgin) { $avginpc = $avgin*100.0/$max1; } else { $avgin = -1; $avginpc = 0; } if(defined $avgout) { $avgoutpc = $avgout*100.0/$max2; } else { $avgout = -1; $avgoutpc = 0; } $interfaces{$curif}{baravgin} = $avgin; $interfaces{$curif}{baravgout} = $avgout; $interfaces{$curif}{baravginpc} = $avginpc; $interfaces{$curif}{baravgoutpc} = $avgoutpc; } # a if( $m ) { ( $start, $step, $names, $values ) = RRDs::fetch($rrd,"MAX","-s","$from-$interval", "-e",$from,"-r",$seconds); $e = RRDs::error(); if($e) { $interfaces{$curif}{errors} .= $q->br.$q->small(langmsg(8999,"Error").": $e"); } else { ($maxin, $maxout) = get_max($values); $maxin *= $interfaces{$curif}{mult}; $maxout *= $interfaces{$curif}{mult}; $maxin *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $maxout *= $interfaces{$curif}{factor} if($interfaces{$curif}{factor}); $maxin = 0 if($interfaces{$curif}{noi}); $maxout= 0 if($interfaces{$curif}{noo}); } if(defined $maxin) { $maxinpc = $maxin*100.0/$max1; } else { $maxin = -1; $maxinpc = 0; } if(defined $maxout) { $maxoutpc = $maxout*100.0/$max2; } else { $maxout = -1; $maxoutpc = 0; } $interfaces{$curif}{barmaxin} = $maxin; $interfaces{$curif}{barmaxout} = $maxout; $interfaces{$curif}{barmaxinpc} = $maxinpc; $interfaces{$curif}{barmaxoutpc} = $maxoutpc; } # m if( $p ) { ($d,$inarr,$outarr) = calc_percentile($curif,$gtype,95); $perin = ${$inarr}[0]; $perout= ${$outarr}[0]; $perin = 0 if($interfaces{$curif}{noi}); $perout= 0 if($interfaces{$curif}{noo}); if(defined $perin) { $perinpc = $perin*100.0/$max1; } else { $perin = -1; $perinpc = -1; } if(defined $perout) { $peroutpc = $perout*100.0/$max2; } else { $perout = -1; $peroutpc = -1; } $interfaces{$curif}{barperin} = $perin; $interfaces{$curif}{barperout} = $perout; $interfaces{$curif}{barperinpc} = $perinpc; $interfaces{$curif}{barperoutpc} = $peroutpc; if(!$d) { $interfaces{$curif}{errors} .= $q->br.$q->small($$inarr[2]) .$q->br.$q->small($$outarr[2]); } } # p # Now correct for any interfaces which are dorelpercent if( $interfaces{$curif}{dorelpercent} ) { foreach $traffic ( qw/cur avg max per/ ) { next if(!defined $interfaces{$curif}{"bar".$traffic."in"}); next if($interfaces{$curif}{'bar'.$traffic.'in'}<0); if($interfaces{$curif}{'bar'.$traffic.'out'}<=0) { $interfaces{$curif}{'bar'.$traffic.'inpc'} = 0; next; } $interfaces{$curif}{'bar'.$traffic.'inpc'} = ($interfaces{$curif}{'bar'.$traffic.'in'}*100/ $interfaces{$curif}{'bar'.$traffic.'out'}); $interfaces{$curif}{'bar'.$traffic.'inpc'} = 100 if($interfaces{$curif}{'bar'.$traffic.'inpc'}>100); $interfaces{$curif}{'bar'.$traffic.'outpc'} = 0; $interfaces{$curif}{'bar'.$traffic.'in'} = $interfaces{$curif}{'bar'.$traffic.'inpc'} ; $interfaces{$curif}{legendo} = ''; } } } # end of data collection # Work out the order of the interfaces $traffic = ""; if ( $c eq "C" ) { $traffic = "cur"; } elsif( $a eq "A" ) { $traffic = "avg"; } elsif( $m eq "M" ) { $traffic = "max"; } elsif( $p eq "P" and defined $config{'routers.cgi-percentile'} and $config{'routers.cgi-percentile'} =~ /y/i ) { $traffic = "per"; } if($traffic) { $traffic .= 'in' if( $io eq "i" ); $traffic .= 'out' if( $io eq "o" ); $traffic = 'bar'.$traffic.'pc'; @iforder = sort bytraffic keys(%interfaces); } else { @iforder = sort byifdesc keys(%interfaces); } # we now print the bars. $barlen = 400; # 800x600 $barlen = 600 if ( $gstyle =~ /x/i ); # 1024x768 $barlen = 280 if ( $gstyle =~ /[nts]/i ); # 640x480 and pda print "\n" if(!$csvmode); foreach $curif ( @iforder ) { next if(!$curif); # avoid rogue records next if(!$interfaces{$curif}{incompact}); # the unit string, if any $unit = ""; $unit = $interfaces{$curif}{unit} if(!defined $config{'routers.cgi-legendunits'} or $config{'routers.cgi-legendunits'} =~ /y/i ); $fix = $interfaces{$curif}{fixunits}; $fix = 0 if(!defined $fix); $intf = $interfaces{$curif}{integer}; $intf = 0 if(!defined $intf); # the legends ($legendi,$legendo)=(langmsg(2204,"IN"),langmsg(2205,"OUT")); $legendi = $interfaces{$curif}{legendi} if(defined $interfaces{$curif}{legendi}); $legendo = $interfaces{$curif}{legendo} if(defined $interfaces{$curif}{legendo}); $legendi = "" if($interfaces{$curif}{noi}); $legendo = "" if($interfaces{$curif}{noo}); if(!$csvmode) { print "\n"; } # csvmode # now print the bar graphs up if( $c ) { $curin = $interfaces{$curif}{barcurin}; $curout= $interfaces{$curif}{barcurout}; $curinpc = $interfaces{$curif}{barcurinpc}; $curoutpc= $interfaces{$curif}{barcuroutpc}; if($csvmode) { print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma .'"'.langmsg(2203,"Last").'"'.$comma .($legendi?doformat($curin,$fix,$intf):"").$comma .($legendo?doformat($curout,$fix,$intf):"").$comma ."\n"; } else { print "\n"; } # csvmode } # c if( $a ) { $avgin = $interfaces{$curif}{baravgin}; $avgout= $interfaces{$curif}{baravgout}; $avginpc = $interfaces{$curif}{baravginpc}; $avgoutpc= $interfaces{$curif}{baravgoutpc}; if($csvmode) { print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma .'"'.langmsg(2201,"Avg").'"'.$comma .($legendi?doformat($avgin,$fix,$intf):"").$comma .($legendo?doformat($avgout,$fix,$intf):"").$comma ."\n"; } else { print "\n"; } # csvmode } # a if( $m ) { $maxin = $interfaces{$curif}{barmaxin}; $maxout= $interfaces{$curif}{barmaxout}; $maxinpc = $interfaces{$curif}{barmaxinpc}; $maxoutpc= $interfaces{$curif}{barmaxoutpc}; if($csvmode) { print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma .'"'.langmsg(2200,"Max").'"'.$comma .($legendi?doformat($maxin,$fix,$intf):"").$comma .($legendo?doformat($maxout,$fix,$intf):"").$comma ."\n"; } else { print "\n"; } # csvmode } # m if( $p ) { $perin = $interfaces{$curif}{barperin}; $perout= $interfaces{$curif}{barperout}; $perinpc = $interfaces{$curif}{barperinpc}; $peroutpc= $interfaces{$curif}{barperoutpc}; if($csvmode) { print $curif.$comma.'"'.$interfaces{$curif}{desc}.'"'.$comma .'"'.langmsg(2206,"95th").'"'.$comma .($legendi?doformat($perin,$fix,$intf):"").$comma .($legendo?doformat($perout,$fix,$intf):"").$comma ."\n"; } else { print "\n"; } # csvmode } # p } # foreach interface print "
\n"; print $q->a({href=>"$meurlfull?".optionstring({if=>$curif})}, $q->small($interfaces{$curif}{desc} .(($interfaces{$curif}{desc} ne $interfaces{$curif}{shdesc})? (" (".$interfaces{$curif}{shdesc}.")"):"") ))."\n"; print $interfaces{$curif}{errors}; print "$legendi$legendo
".langmsg(2203,"Last") .""; print $q->img({border=>0,height=>10,width=>$barlen,src=>"$meurlfull?page=bar&L=$barlen&IN=".dp($curinpc,1)."&OUT=".dp($curoutpc,1)}); print ""; print $q->small("  ".doformat($curin,$fix,$intf) ."$unit") if($curin>=0 and $legendi); print $q->small(" (".doformat($curinpc,1,0)."%)") if($curinpc>=0 and $legendi and $interfaces{$curif}{percent}); print ""; print $q->small("  ".doformat($curout,$fix,$intf) ."$unit") if($curout>=0 and $legendo); print $q->small(" (".doformat($curoutpc,1,0)."%)") if($curoutpc>=0 and $legendo and $interfaces{$curif}{percent}); print "
".langmsg(2201,"Avg") .""; print $q->img({border=>0,height=>10,width=>$barlen,src=>"$meurlfull?page=bar&L=$barlen&IN=".dp($avginpc,1)."&OUT=".dp($avgoutpc,1)}); print ""; print $q->small("  ".doformat($avgin,$fix,$intf)."$unit") if($avgin>=0 and $legendi); print $q->small(" (".doformat($avginpc,1,0)."%)") if($avginpc>=0 and $legendi and $interfaces{$curif}{percent}); print ""; print $q->small("  ".doformat($avgout,$fix,$intf)."$unit") if($avgout>=0 and $legendo); print $q->small(" (".doformat($avgoutpc,1,0)."%)") if($avgoutpc>=0 and $legendo and $interfaces{$curif}{percent}); print "
" .langmsg(2200,"Max").""; print $q->img({border=>0,height=>10,width=>$barlen,src=>"$meurlfull?page=bar&L=$barlen&IN=".dp($maxinpc,1)."&OUT=".dp($maxoutpc,1)}); print ""; print $q->small("  ".doformat($maxin,$fix,$intf)."$unit") if($maxin>=0 and $legendi); print $q->small(" (".doformat($maxinpc,1,0)."%)") if($maxinpc>=0 and $legendi and $interfaces{$curif}{percent}); print ""; print $q->small("  ".doformat($maxout,$fix,$intf)."$unit") if($maxout>=0 and $legendo); print $q->small(" (".doformat($maxoutpc,1,0)."%)") if($maxoutpc>=0 and $legendo and $interfaces{$curif}{percent}); print "
".langmsg(2206,"95th") .""; print $q->img({border=>0,height=>10,width=>$barlen,src=>"$meurlfull?page=bar&L=$barlen&IN=".dp($perinpc,1)."&OUT=".dp($peroutpc,1)}); print ""; print $q->small("  ".doformat($perin,$fix,$intf)."$unit") if($perin>=0 and $legendi); print $q->small(" (".doformat($perinpc,1,0)."%)") if($perinpc>=0 and $legendi and $interfaces{$curif}{percent}); print ""; print $q->small("  ".doformat($perout,$fix,$intf)."$unit") if($perout>=0 and $legendo); print $q->small(" (".doformat($peroutpc,1,0)."%)") if($peroutpc>=0 and $legendo and $interfaces{$curif}{percent}); print "
\n" if(!$csvmode); # Page foot if(!$csvmode) { print "
"; print expandvars($config{'routers.cgi-pagefoot'}),"\n" if( defined $config{'routers.cgi-pagefoot'} ); print "
"; if( $gstyle !~ /p/ ) { my( $ngti, $ngto ) = ("",""); print "
".$q->hr; print "\n",$q->a({href=>"javascript:location.reload(true)"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh.gif", alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20}))," \n" if(!$archdate); # print $q->a({href=>"javascript:parent.makebookmark('" # .$q->escape($router)."','__compact','$gtype','$gstyle','$gopts','$baropts','".$q->escape($extra)."')"}, # $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", # alt=>"Bookmark",border=>"0",width=>100,height=>20}))," \n"; print $q->a({href=>"$meurlfull?".optionstring({page=>"", xmtype=>"", if=>"__compact", xgstyle=>""}), target=>"_top" }, $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20}))," \n"; print $q->a({href=>"$meurlfull?".optionstring({page=>"compactcsv"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}csv.gif", alt=>langmsg(5019,"CSV Download"),border=>"0",width=>100,height=>20})),"\n"; if( $gtype eq "6" ) { $ngto = "d"; } elsif( $gtype eq "d" ) { $ngto = "w"; $ngti = "6" if($usesixhour); } elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } elsif( $gtype eq "y" ) { $ngti = "m"; } if( $ngti ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20}))," \n"; } if( $ngto ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20}))," \n"; } print "
"; print $q->br,"\n"; } # csvmode } if(!$csvmode){ print "\n"; do_footer(); } # csvmode } ####################################################### # This is for the summary of interfaces view sub do_summary() { # Start off. We use onload() and Javascript to force reload the # lefthand (menu) panel. my ($javascript, $e); my ($rrd, $curif); my ($m, $a, $l ); my ($start,$step, $names, $data); my ($savetz) = ""; my ($legendi, $legendo, $legendx); my ($donehead) = 0; my ($withdetails) = 1; my ($doneone) = 0; my ($inhtml) = 1; calctimezone(); $javascript = make_javascript({}).graphpopupscript(); $withdetails = 0 if($interfaces{$interface}{nodetails}); start_html_ss({ -expires => "+5s", -script => $javascript, -onload => "LoadMenu()", -class=>'summary' }, $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); print $q->center($q->h2($routers{$router}{desc}))."\n" if($routers{$router}{desc}); print "
"; print expandvars($config{'routers.cgi-pagetop'}),"\n" if( defined $config{'routers.cgi-pagetop'} ); if( defined $config{'routers.cgi-mrtgpagetop'} and $config{'routers.cgi-mrtgpagetop'} =~ /y/i and $interfaces{$interface}{pagetop}) { print expandvars($interfaces{$interface}{pagetop}),"\n"; } print "
"; # # Now for the RRD stuff eval { require 'RRDs.pm'; }; if( $@ ) { print $q->h1(langmsg(8999,"Error"))."Cannot find RRDs.pm in ".(join " ",@INC )."\n"; print $q->p("You can visit the configuration verification page " .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), target=>"_new"},"here.")); do_footer(); return; } print "\n"; $savetz = $ENV{TZ}; $doneone = 0; foreach $curif ( sort byifdesc @{$interfaces{$interface}{targets}} ) { next if(!$curif); # avoid rogue records if($interfaces{$interface}{active} and !$interfaces{$curif}{userdefined}) { next if(!isactive($curif)); } ($legendi,$legendo,$legendx)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); $legendi = $interfaces{$curif}{legendi} if(defined $interfaces{$curif}{legendi}); $legendo = $interfaces{$curif}{legendo} if(defined $interfaces{$curif}{legendo}); $legendx = $interfaces{$curif}{legendx} if(defined $interfaces{$curif}{legendx}); if($interfaces{$interface}{overridelegend} and $interfaces{$curif}{shdesc} and ( $interfaces{$interface}{noo} or $interfaces{$interface}{noi} or $interfaces{$curif}{noo} or $interfaces{$curif}{noi} ) ){ $legendi = $legendo = $interfaces{$curif}{shdesc}.':'; } # timezone information if($interfaces{$curif}{timezone}) { $ENV{TZ} = $interfaces{$curif}{timezone} ; POSIX::tzset(); } print "" if($withdetails or !$doneone); print ""; if($doneone) { print "\n" ; $doneone = 0; } else { $doneone = 1; } } else { print "\n"; } next; } if(!$withdetails) { if($interfaces{$interface}{withtop}) { print $q->br."\n".$interfaces{$curif}{pagetop}.$q->br if($interfaces{$curif}{pagetop}); } } print ""$curif"}, target=>"graph").">"; make_graph($inhtml,$gtype."s",$curif); print ""; if($interfaces{$curif}{usergraph}) { print $q->br.$q->small("User Graph: ".$q->i($curif)); } else { print $q->br.$q->small("Target: ".$q->i($interfaces{$curif}{target})) if($interfaces{$curif}{target}); } if(!$withdetails) { if($interfaces{$interface}{withfoot}) { print $q->br."\n".$interfaces{$curif}{pagefoot} if($interfaces{$curif}{pagefoot}); } print "\n"; if($doneone) { print "\n" ; $doneone = 0; } else { $doneone = 1; } next; } print "/i and !$donehead ) { $donehead = 1; next; } print if(!$donehead); } } } else { if ( $interfaces{$curif}{max} and !$interfaces{$curif}{nomax} ) { if ( defined $interfaces{$curif}{mblegend} ) { print $interfaces{$curif}{mblegend}; } elsif ( $interfaces{$curif}{isif} ) { print langmsg(2103,"Bandwidth"); } else { print langmsg(2102,"Maximum"); } if(defined $interfaces{$curif}{max1} and defined $interfaces{$curif}{max2}) { print ": ".doformat( $interfaces{$curif}{max1}, $interfaces{$curif}{fixunits},0) .$interfaces{$curif}{unit}."/" .doformat( $interfaces{$curif}{max2}, $interfaces{$curif}{fixunits},0) .$interfaces{$curif}{unit}.$q->br,"\n"; } else { print ": ".doformat( $interfaces{$curif}{max}, $interfaces{$curif}{fixunits},0); print $interfaces{$curif}{unit}.$q->br,"\n"; } if( defined $interfaces{$curif}{absmax} and !$interfaces{$curif}{noabsmax} ) { if ( defined $interfaces{$curif}{amlegend} ) { print $interfaces{$curif}{amlegend}; } else { print langmsg(2104,"Hard Maximum"); } print ": ".doformat ($interfaces{$curif}{absmax}, $interfaces{$curif}{fixunits},0) .$interfaces{$curif}{unit}.$q->br,"\n"; } } print "Address: ".$interfaces{$curif}{address},$q->br,"\n" if ( $interfaces{$curif}{address} ); print "Interface IP: ".$interfaces{$curif}{ipaddress},$q->br,"\n" if ( $interfaces{$curif}{ipaddress} ); print "Interface # ".$interfaces{$curif}{ifno},$q->br,"\n" if(defined $interfaces{$curif}{ifno}); print "Interface name: ".$interfaces{$curif}{ifdesc},$q->br,"\n" if($interfaces{$curif}{ifdesc}); # insert here the last/current/max values. # print @$rrdoutput if($rrdoutput); $donehead = 0; if($rrdoutput) { foreach ( @$rrdoutput ) { if( /^/i and !$donehead ) { $donehead = 1; print "
"; if( $interfaces{$curif}{userdefined} ) { $rrd = $interfaces{$interfaces{$interface}{targets}->[0]}{rrd}; $lastupdate = RRDs::last($rrd); $e = RRDs::error(); } elsif( defined $interfaces{$curif}{rrd} ) { $rrd = $interfaces{$curif}{rrd}; # Last update stuff. $lastupdate = RRDs::last($rrd); $e = RRDs::error(); } else { $rrd = ""; $e = langmsg(8002,"No RRD file defined for interface")." '$curif'"; } if( $e ) { print $q->p($q->b(langmsg(8003,"Error reading RRD database")." $rrd"),$q->br,$e,"Check that MRTG has run successfully on this device, and has created the RRD file."),"\n"; if(!$withdetails) { print "
\n"; print $q->h3($interfaces{$curif}{shdesc}),"\n"; print $q->p($interfaces{$curif}{desc}),$q->br; # print $q->dump; print "
\n"; print $q->a({href=>"$meurlfull?".optionstring({if=>"$curif"}), target=>"graph"}, $q->b($interfaces{$curif}{desc})); if($interfaces{$interface}{withtop} and $interfaces{$curif}{pagetop}) { print $q->br.$interfaces{$curif}{pagetop}."\n"; } print $q->br,langmsg(3203,"Last update").": ".scalar(localtime($lastupdate)), $q->br,"\n"; print langmsg(3204,"Timezone").": ".$interfaces{$curif}{timezone}.$q->br."\n" if($interfaces{$curif}{timezone}); if($interfaces{$curif}{usergraph}) { if($rrdoutput) { $donehead = 0; foreach ( @$rrdoutput ) { if( /^
"; print $q->td($q->b($legendi)) if(!$interfaces{$curif}{noi}); print $q->td($q->b($legendo)) if(!$interfaces{$curif}{noo}); print $q->td($q->b($legendx)) if($legendx); print "\n"; } print; } } # now the 95th percentile, if required if( defined $config{'routers.cgi-percentile'} and $config{'routers.cgi-percentile'} =~ /y/i ) { my( $pcdesc, $inarr, $outarr ); if(!$donehead) { print "
"; print $q->td($q->b($legendi)) if(!$interfaces{$curif}{noi}); print $q->td($q->b($legendo)) if(!$interfaces{$curif}{noo}); print $q->td($q->b($legendx)) if($legendx); print "\n"; $donehead = 1; } ( $pcdesc, $inarr, $outarr ) = calc_percentile($curif,$gtype,95); if($pcdesc) { if($interfaces{$curif}{total}) { print "".$q->td(langmsg(2301,"Total over")." $pcdesc:"); print $q->td({ align=>"right"},doformat($$inarr[1], $interfaces{$curif}{fixunits},$interfaces{$curif}{integer}) .$interfaces{$curif}{totunit}) if(!$interfaces{$curif}{noi}); print $q->td({ align=>"right"},doformat($$outarr[1], $interfaces{$curif}{fixunits},$interfaces{$curif}{integer}) .$interfaces{$curif}{totunit}) if(!$interfaces{$curif}{noo}); print "\n"; } if($interfaces{$curif}{percentile}) { print "".$q->td(langmsg(2300,"95th Percentile for")." $pcdesc:"); print $q->td({ align=>"right"},doformat($$inarr[0], $interfaces{$curif}{fixunits},0) .$interfaces{$curif}{unit}) if(!$interfaces{$curif}{noi}); print $q->td({ align=>"right"},doformat($$outarr[0], $interfaces{$curif}{fixunits},0) .$interfaces{$curif}{unit}) if(!$interfaces{$curif}{noo}); } } else { print "".$q->td(langmsg(8004,"Error in 95th percentile calcs").":") .$q->td($$inarr[2]).$q->td($$outarr[2])."\n"; } } print "
".$q->br."\n" if($donehead); } # not usergraph if($interfaces{$interface}{withfoot} and $interfaces{$curif}{pagefoot}) { print $interfaces{$curif}{pagefoot}."\n"; } print "\n"; if($savetz){ $ENV{TZ}=$savetz; POSIX::tzset(); } } # foreach print "" if(!$withdetails and $doneone); print "\n"; # Page foot print "
"; if( defined $config{'routers.cgi-mrtgpagefoot'} and $config{'routers.cgi-mrtgpagefoot'} =~ /y/i and $interfaces{$interface}{pagefoot}) { print expandvars($interfaces{$interface}{pagefoot}),"\n"; } print expandvars($config{'routers.cgi-pagefoot'}),"\n" if( defined $config{'routers.cgi-pagefoot'} ); print "
"; if( $gstyle !~ /p/ ) { my( $u, $ngti, $ngto ) = ("","",""); print $q->hr; print "\n",$q->a({href=>"javascript:location.reload(true)"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh.gif", alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20}))," \n" if(!$archdate); print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", xmtype=>"", xgstyle=>""}), target=>"_top" }, $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20}))," \n"; if( $gtype eq "6" ) { $ngto = "d"; } elsif( $gtype eq "d" ) { $ngto = "w"; $ngti = '6' if($usesixhour); } elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } elsif( $gtype eq "y" ) { $ngti = "m"; } if( $ngti ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20}))," \n"; } if( $ngto ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20}))," \n"; } print $q->br,"\n"; } print "
"; do_footer(); } sub do_empty() { my ($javascript); $javascript = make_javascript({}); start_html_ss({ -expires => "+5s", -script => $javascript, -onload => "LoadMenu()", -bgcolor => "#ffffff", -class=>'empty' }); if( $router eq "none" ) { print $q->h3(langmsg(9002,"Please select a device")); } else { print $q->h3(langmsg(9003,"Please select a target")); } do_footer(); } sub do_graph($) { # Start off. We use onload() and Javascript to force reload the # lefthand (menu) panel. my ($javascript, $e); my ($rrd, $curif); my ($iconsuffix) = ""; my ($bgcolor,$legendi,$legendo,$legendx); my ($inhtml) = $_[0]; # true if we want HTML page calctimezone(); $iconsuffix = "-bw" if( $gstyle =~ /b/ ); $javascript = make_javascript({}).graphpopupscript(); $bgcolor = $defbgcolour; $bgcolor = $interfaces{$interface}{background} if($interface and defined $interfaces{$interface} and defined $interfaces{$interface}{background}); if($inhtml) { my($class) = $interfaces{$interface}{mode}?$interfaces{$interface}{mode}:'generic'; $class =~ s/^\177_//; start_html_ss({ -expires => "+5s", -script => $javascript, -onload => "LoadMenu()", -bgcolor => $bgcolor, -class => $class }, $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); } # Catch for if there are NO cfg files. if( ! $interface or ! $router or $interface eq "none" or $interface =~ /^__/ or $router eq "none" ) { if(!$inhtml) { if($opt_I) { print "Device: $router\nTarget: $interface\n"; } else { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); } return; } print $q->h3(langmsg(9004,"No valid target is selected")); if( $#cfgfiles eq -1 and $config{'routers.cgi-cfgfiles'} ne 'none' ) { print $q->p("You have no valid MRTG configuration files. You should check your configuration in $conffile.".$q->br."[" .$config{'routers.cgi-confpath'}.$pathsep .$config{'routers.cgi-cfgfiles'}."]"),"\n"; print $q->p("NT users should check that this includes the correct drive letter.")."\n" if($config{'web-NT'}); print $q->p("confpath = ".$config{'routers.cgi-confpath'}); print $q->p("cfgfiles = ".$config{'routers.cgi-cfgfiles'}); } do_footer(); return; } # Now for the RRD stuff eval { require 'RRDs.pm'; }; if( $@ ) { if(!$inhtml) { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); return; } print $q->h1(langmsg(8999,"Error")),"cannot find RRDs.pm in ".(join " ",@INC)."\n"; print $q->p("You can visit the configuration verification page " .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), target=>"_new"},"here.")); do_footer(); return 0; } # Now, we have to do this differently depending on which gtype we have # We do a switch for the different graphs. # We have to call RRD to create them, and the IMG tag is created ready to # stuff into the page! $rrd = ""; if ( $interface =~ /^__/ ) { # compact and summary $curif = (keys(%interfaces))[0]; $rrd = $interfaces{$curif}{rrd}; } elsif ( $interfaces{$interface}{usergraph} ) { # user defined $rrd = $interfaces{$interfaces{$interface}{targets}->[0]}{rrd}; } else { $rrd = $interfaces{$interface}{rrd} if( defined $interfaces{$interface}{rrd} ); } # Timezone if($interfaces{$interface}{timezone}) { $ENV{TZ} = $interfaces{$interface}{timezone} ; POSIX::tzset(); } # Last update stuff. if( $rrd ) { $lastupdate = RRDs::last($rrd); $e = RRDs::error(); } else { $e = langmsg(8002,"No RRD file defined for interface")." '$interface'"; } if( $e ) { if(!$inhtml) { if($opt_I) { print "Error: $e\n"; } else { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); } return; } print $q->h3("$interfaces{$interface}{shdesc}"),"\n"; print $q->p("$interfaces{$interface}{desc}"),"\n"; print $q->p($q->b(langmsg(8003,"Error reading RRD database")." $rrd"),$q->br,$e,"Check that MRTG has run successfully on this device, and has created the RRD file."),"\n"; # We may need to give a more helpful error message here if the # user is asking for a nonexistant archive date print $q->p("You can visit the configuration verification page " .$q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($router)), target=>"_new"},"here.")); # print $q->dump; } else { # any defined pagetop stuff if($inhtml) { print "
"; print expandvars($config{'routers.cgi-pagetop'}),"\n" if( defined $config{'routers.cgi-pagetop'} ); if( defined $config{'routers.cgi-mrtgpagetop'} and $config{'routers.cgi-mrtgpagetop'} =~ /y/i and $interfaces{$interface}{pagetop} and !$interfaces{$interface}{usergraph} ) { print expandvars($interfaces{$interface}{pagetop}),"\n"; } print "
"; } my $suffix = ( $gtype =~ /s/ ) ? "s" : ""; $suffix .= "-" if( $gtype =~ /-/ ); if( defined $interfaces{$interface}{suppress} ) { my $pat = "[".$interfaces{$interface}{suppress}."]"; $gtype =~ s/$pat//g; } make_graph($inhtml,"6$suffix",$interface) if ( $gtype =~ /6/ ); make_graph($inhtml,"d$suffix",$interface) if ( $gtype =~ /d/ ); print $q->br,"\n" if ( $inhtml and $uopts=~/s/ ); make_graph($inhtml,"w$suffix",$interface) if ( $gtype =~ /w/ ); print $q->br,"\n" if ( $inhtml and (length($gtype) > 2 or $uopts=~/s/) ); make_graph($inhtml,"m$suffix",$interface) if ( $gtype =~ /m/ ); print $q->br,"\n" if ( $inhtml and $uopts=~/s/ ); make_graph($inhtml,"y$suffix",$interface) if ( $gtype =~ /y/ ); print $q->br,"\n" if ( $inhtml and (length($gtype) > 2 or $uopts=~/s/) ); return if(!$inhtml); # we can leave now print $q->br.$q->br; print ""; print "\n" if($archdate); print "\n"; print "\n" if($interfaces{$interface}{timezone}); print "
".langmsg(3205,"Data archived").":$archdate
".langmsg(3203,"Last update").": ".scalar(localtime($lastupdate)) ."
".langmsg(3204,"Timezone").":".$interfaces{$interface}{timezone} ."
\n"; if( defined $config{'routers.cgi-percentile'} and $config{'routers.cgi-percentile'} =~ /y/i # and !$interfaces{$interface}{usergraph} ) { my( $i, $pcdesc, $inarr, $outarr, $sfx ); print "\n"; # Loop through interfaces, if on userdefined graph foreach $curif ( $interfaces{$interface}{usergraph}? (@{$interfaces{$interface}{targets}}):($interface) ) { # Skip this if it is not an active graph if($interfaces{$interface}{active}) { next if(!isactive($curif)); } print "\n" if($interfaces{$interface}{usergraph}); $sfx = ""; ($legendi,$legendo,$legendx)=(langmsg(2204,"IN:"),langmsg(2205,"OUT:"),""); $legendi=$interfaces{$curif }{legendi} if(defined $interfaces{$curif }{legendi}); $legendo=$interfaces{$curif }{legendo} if(defined $interfaces{$curif }{legendo}); $legendx=$interfaces{$curif }{legendx} if(defined $interfaces{$curif }{legendx}); $legendi =~ s/ / /g; $legendo =~ s/ / /g; $sfx = "-" if( $gtype =~ /-/ ); # Loop through time periods, if on multiple graphs foreach $i ( qw/d w m y/ ) { next if((index $gtype, $i) < 0); ( $pcdesc, $inarr, $outarr ) = calc_percentile($curif,$i.$sfx,95); if($pcdesc) { # print "".$q->td("").$q->td($q->b($legendi)) # .$q->td($q->b($legendo)); if($interfaces{$interface}{total}) { print "".$q->td($q->b(langmsg(2301,"Total over")." $pcdesc:")); print $q->td($legendi).$q->td({align=>"right"},doformat($$inarr[1], $interfaces{$curif }{fixunits},$interfaces{$curif }{integer}) .$interfaces{$curif }{totunit}) .$q->td("") if(!$interfaces{$interface}{noi}); print $q->td($legendo).$q->td({align=>"right"},doformat($$outarr[1], $interfaces{$curif }{fixunits},$interfaces{$curif }{integer}) .$interfaces{$curif }{totunit}) .$q->td("") if(!$interfaces{$interface}{noo}); print "\n"; } if($interfaces{$interface}{percentile}) { my($pclabel); print "".$q->td($q->b(langmsg(2300,"95th Percentile for")." $pcdesc:")); if(!$interfaces{$interface}{noi}) { $pclabel = ""; $pclabel = " (" .doformat(($$inarr[0]/$interfaces{$curif }{max}*100.0),1,0) ."%)" if($interfaces{$curif }{percent} and $interfaces{$curif}{max}); print $q->td($legendi).$q->td({align=>"right"}, doformat($$inarr[0], $interfaces{$curif }{fixunits},0) .$interfaces{$curif }{unit}) ; print $q->td($pclabel); } if(!$interfaces{$interface}{noo}) { $pclabel = ""; $pclabel = " (" .doformat(($$outarr[0]/$interfaces{$curif }{max}*100.0),1,0) ."%)" if($interfaces{$curif }{percent} and $interfaces{$curif}{max}); print $q->td($legendo).$q->td({align=>"right"}, doformat($$outarr[0], $interfaces{$curif }{fixunits},0) .$interfaces{$curif }{unit}) ; print $q->td($pclabel); } print "\n"; } } else { print "" if($$inarr[2] or $$outarr[2]); } # pcdesc } # foreach timeperiod } # foreach interface print "
" .$q->a({href=>("$meurlfull?".optionstring({ 'if'=>$curif, 'page'=>'graph' } ))}, $q->i($interfaces{$curif}{desc})) ."
".langmsg(8004,"Error in 95th percentile") .":" ."[".$$inarr[2]."]".$q->br ."[".$$outarr[2]."]
\n"; } print $q->br."
"; if( defined $config{'routers.cgi-mrtgpagefoot'} and $config{'routers.cgi-mrtgpagefoot'} =~ /y/ and $interfaces{$interface}{pagefoot} and !$interfaces{$interface}{usergraph} ) { print expandvars($interfaces{$interface}{pagefoot}),"\n"; } print expandvars($config{'routers.cgi-pagefoot'}),"\n" if( defined $config{'routers.cgi-pagefoot'} ); print "
"; # any extensions defined for this target? if( defined $interfaces{$interface}{extensions} and $uopts !~/s/ ) { my($ext, $u, $targ); print $q->hr,"\n"; foreach $ext ( @{$interfaces{$interface}{extensions}} ) { if($seclevel<$ext->{level}) { # print $ext->{desc}." (".$ext->{level}.")".$q->br."\n"; next; } $targ = "graph"; $targ = $ext->{target} if( defined $ext->{target} ); $u=$ext->{url}; if(!$ext->{noopts}) { $u .= "?x=2" if( $u !~ /\?/ ); $u .= "&fi=".$q->escape($router)."&ta=" .$q->escape($interface)."&url=".$q->escape($q->url()); $u .= "&t=".$q->escape($targ); $u .= "&L=".$seclevel; $u .= "&uopts=".$uopts if($uopts); $u .= "&h=".$q->escape($interfaces{$interface}{hostname}) if(defined $interfaces{$interface}{hostname}); $u .= "&c=".$q->escape($interfaces{$interface}{community}) if(defined $interfaces{$interface}{community} and $ext->{insecure}); $u .= "&ifno=".$interfaces{$interface}{ifno} if(defined $interfaces{$interface}{ifno}); $u .= "&b=".$q->escape("javascript:history.back();history.back()") ."&conf=".$q->escape($conffile); $u .= "&ad=$archdate" if($archdate); } elsif( $ext->{noopts} == 2 ) { $u .= "&L=$seclevel&xgtype=$gtype&xgstyle=$gstyle"; $u .= "&arch=$archdate" if($archdate); } print $q->img( { height=>15, width=>15, src=>($config{'routers.cgi-smalliconurl'}.$ext->{icon}) }) ." "; # print $q->img( { height=>15, width=>15, # src=>($config{'routers.cgi-iconurl'}."alert-sm.gif") }) # ." " if($ext->{insecure}); print $q->a( { href=>$u, target=>$targ }, $ext->{desc}).$q->br."\n"; } } print "
"; # routers.cgi page footer if( $gstyle !~ /p/ ) { my( $u, $ngti, $ngto ) = ("","",""); print $q->hr; print "\n",$q->a({href=>"javascript:location.reload(true)"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}refresh$iconsuffix.gif",alt=>langmsg(5003,"Refresh"),border=>"0",width=>100,height=>20})),"\n" if(!$archdate); # print $q->a({href=>"javascript:parent.makebookmark('" # .$q->escape($router)."','".$q->escape($interface) # ."','$gtype','$gstyle','$gopts','$baropts','".$q->escape($extra)."')"}, print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", xmtype=>"", xgstyle=>""}), target=>"_top" }, $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark$iconsuffix.gif",alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20})), "\n"; if( $gtype eq "6" ) { $ngto = "d"; } elsif( $gtype eq "d" ) { $ngto = "w"; $ngti='6' if($usesixhour); } elsif( $gtype eq "w" ) { $ngti = "d"; $ngto = "m"; } elsif( $gtype eq "m" ) { $ngti = "w"; $ngto = "y"; } elsif( $gtype eq "y" ) { $ngti = "m"; } if( $ngti ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngti"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomin.gif", alt=>langmsg(5017,"Zoom In"),border=>"0",width=>100,height=>20})),"\n"; } if( $ngto ) { print $q->a({href=>"$meurlfull?".optionstring({xgtype=>"$ngto"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}zoomout.gif", alt=>langmsg(5018,"Zoom Out"),border=>"0",width=>100,height=>20})),"\n"; } # if(!$interfaces{$interface}{usergraph}) { print $q->a({href=>"$meurlfull?".optionstring({page=>"csv"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}csv.gif", alt=>langmsg(5019,"CSV Download"),border=>"0",width=>100,height=>20})),"\n"; # } if( defined $config{'routers.cgi-archive'} and $config{'routers.cgi-archive'} =~ /[y1]/i ) { print $q->a({href=>"$meurlfull?".optionstring({page=>"archive"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}archive.gif", alt=>langmsg(5020,"Add to archive"),border=>"0",width=>100,height=>20})),"\n"; } my($nuopts) = $uopts; # 3-way toggle if($nuopts =~ /r/) { $nuopts =~ s/r/R/g; } elsif($nuopts =~ /R/) { $nuopts =~ s/[rR]//g; } else { $nuopts .= 'r'; } print $q->a({href=>"$meurlfull?".optionstring({uopts=>"$nuopts"}), target=>"graph"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}rescale.gif", alt=>langmsg(5021,"Rescale"),border=>"0",width=>100,height=>20})),"\n"; print $q->br,"\n"; } # gstyle not p print "
"; } # Finish off the page (this does the ending body and html tags) do_footer(); } # Information on this router sub do_info() { # Start off. We use onload() and Javascript to force reload the # lefthand (menu) panel. my ($javascript, $ifkey,$x, $icon); my ($acount,$archivepat,@archive,$archives); $javascript = make_javascript({}); start_html_ss({ -expires => "+5s", -script => $javascript, -onload => "LoadMenu()", -class=>'info' }); # Here we build up a page of info, with lotsalinks. print $q->center($q->h2($routers{$router}{desc}))."\n"; print $q->h3(langmsg(3004,"Device Information")),"\n"; print $q->a({href=>"$meurlfull?".optionstring({page=>"graph",if=>"_summary_"}), target=>"graph"}, $q->b("$router: ".$routers{$router}{shdesc}.": " .$routers{$router}{desc})),$q->br,"\n"; print $q->br.$q->b(langmsg(3005,"MRTG config file").": ").$routers{$router}{file}."\n"; print "
    "; $ifkey = ""; # we want this later foreach (sort byifdesc keys (%interfaces)) { next if(!$_); # avoid rogue records next if(/^__/); next if($interfaces{$_}{mode} =~ /^\177_AUTO/); # system created # count archived copies $archivepat = $router; $archivepat =~ s/[\?#\\\/]//g; $archivepat = $config{'routers.cgi-graphpath'}.$pathsep .$archivepat.$pathsep.$_.$pathsep."*.*"; @archive = glob($archivepat); $acount = $#archive + 1; # now the data line $icon = $q->img({src=>($config{'routers.cgi-smalliconurl'}.$interfaces{$_}{icon}) ,width=>15,height=>15})." "; $ifkey = $_ if(!$ifkey and $interfaces{$_}{community} and $interfaces{$_}{hostname}); if( $acount == 1 ) { $archives = $q->br.langmsg(3300,"This target has one archived graph."); } elsif( $acount > 1 ) { $archives = $q->br.langmsg(3301,"This target has") ." $acount ".langmsg(3302,"archived graphs."); } else { $archives = ""; } if( $interfaces{$_}{usergraph} ) { print $q->li( $icon.$q->a( {href=>"$meurlfull?".optionstring({if=>"$_"}), target=>"graph"}, $interfaces{$_}{desc})." [$_] " .($interfaces{$_}{graphstyle}?("<".$interfaces{$_}{graphstyle}.">"):"") .($interfaces{$_}{default}?"[DEFAULT]":"") ." \n$archives"); } elsif( defined $interfaces{$_}{ifno} ) { # interface number print $q->li( $icon.$q->a( {href=>"$meurlfull?".optionstring({if=>"$_"}), target=>"graph"}, "#".$interfaces{$_}{ifno}.": ".$interfaces{$_}{desc} )." [".$interfaces{$_}{target}."] ".langmsg(6200,"Max")." " .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) .$interfaces{$_}{unit} ." {".$interfaces{$_}{mode}."} " .($interfaces{$_}{default}?"[DEFAULT]":"") ."\n$archives"),"\n"; } elsif( defined $interfaces{$_}{ifdesc} ) { # interface description print $q->li( $icon.$q->a( {href=>"$meurlfull?".optionstring({if=>"$_"}), target=>"graph"}, $interfaces{$_}{shdesc}.": ".$interfaces{$_}{desc} )." [".$interfaces{$_}{target}."] ".langmsg(6200,"Max")." " .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) .$interfaces{$_}{unit} ." {".$interfaces{$_}{mode}."} " .($interfaces{$_}{default}?"[DEFAULT]":"") ."\n$archives"),"\n"; } elsif( defined $interfaces{$_}{ipaddress} ) { # IP address print $q->li( $icon.$q->a( {href=>"$meurlfull?".optionstring({if=>"$_"}), target=>"graph"}, $interfaces{$_}{ipaddress}.": ".$interfaces{$_}{desc} )." [".$interfaces{$_}{target}."] " .langmsg(6200,"Max")." " .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) .$interfaces{$_}{unit} ." {".$interfaces{$_}{mode}."} " .($interfaces{$_}{default}?"[DEFAULT]":"") ."\n$archives"),"\n"; } else { # userdefined and unknown print $q->li( $icon.$q->a( {href=>"$meurlfull?".optionstring({if=>"$_"}), target=>"graph"}, $interfaces{$_}{desc})." [".$interfaces{$_}{target}."] " .langmsg(6200,"Max")." " .doformat($interfaces{$_}{max},$interfaces{$_}{fixunits},1) .$interfaces{$_}{unit} # ."(f=".$interfaces{$_}{factor}.",m=".$interfaces{$_}{mult}.")" ." {".$interfaces{$_}{mode}."}" .($interfaces{$_}{graphstyle}?("<".$interfaces{$_}{graphstyle}.">"):"") .($interfaces{$_}{default}?"[DEFAULT]":"") ."\n$archives" ),"\n"; } } print "
\n"; # Can we call out to the routingtable.cgi program? if( defined $config{'routers.cgi-routingtableurl'} and ( !defined $routers{$router}{routingtable} or $routers{$router}{routingtable} eq "y" )) { if($ifkey) { print $q->a({target=>"_self", href=>($config{'routers.cgi-routingtableurl'} ."?r=".$q->escape($interfaces{$ifkey}{hostname}) ."&h=".$q->escape($interfaces{$ifkey}{hostname}) ."&c=".$q->escape($interfaces{$ifkey}{community}) ."&url=".$q->escape($q->url()) ."&t=graph&b=javascript:".$q->escape("history.back();history.back()") ."&conf=".$q->escape($conffile))}, langmsg(3303,"Show routing table for this device"))." (may take some time)", $q->br,$q->br,"\n"; } else { print langmsg(3304,"Routing table information not available."),$q->br, $q->br,"\n"; } } # Finish off the page (this does the ending body and html tags) do_footer(); } ############################################################################ # Export of data to CSV format -- single RRD sub do_export() { my( $start, $step, $names, $data, $line); my( $mstart, $mstep, $mnames, $maxdata, $mline ); my( $rrd, @opts, $e, $d, $t, $i, $r, @dat ); my( $thisif, $startpoint, $endpoint, $resolution ); my( @allifs ); $comma = substr( $config{'web-comma'},0,1 ) if(defined $config{'web-comma'}); $comma = ',' if(!$comma); eval { require 'RRDs.pm'; }; if( $@ ) { print "ERROR".$comma."Cannot find RRDs.pm!".$comma.$@; return; } if( !$interface ) { print langmsg(9004,"No interface selected!"); return; } # If this is a normal one, then just one interface. If it is a # userdefined, then we wil have a list of targets to process. @allifs = ( $interface ); @allifs = @{$interfaces{$interface}{targets}} if( $interfaces{$interface}{targets} ); foreach $thisif ( @allifs ) { # Header line print "\"Hostname\"$comma\"Target\"$comma\"Sample Date YMD\"$comma\"Sample Time HHMM\"$comma\"Count in seconds\""; if( $interfaces{$thisif}{aspercent} ) { print "$comma\"Raw data 1\"" if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); print "$comma\"Raw data 2\"" if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); } print "$comma\"".$interfaces{$thisif}{legend1}.($interfaces{$thisif}{unit}? (' in '.$interfaces{$thisif}{unit}):'').'"' if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); print "$comma\"".$interfaces{$thisif}{legend2}.($interfaces{$thisif}{unit}? (' in '.$interfaces{$thisif}{unit}):'').'"' if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); if( $gtype !~ /6/ ) { if( $interfaces{$thisif}{aspercent} ) { print "$comma\"Raw max data 1\"" if($interfaces{$thisif}{legend1} and !$interfaces{$thisif}{noi}); print "$comma\"Raw max data 2\"" if($interfaces{$thisif}{legend2} and !$interfaces{$thisif}{noo}); } print "$comma\"".$interfaces{$thisif}{legend3}.($interfaces{$thisif}{unit}? (' in '.$interfaces{$thisif}{unit}):'').'"' if($interfaces{$thisif}{legend3} and !$interfaces{$thisif}{noi}); print "$comma\"".$interfaces{$thisif}{legend4}.($interfaces{$thisif}{unit}? (' in '.$interfaces{$thisif}{unit}):'').'"' if($interfaces{$thisif}{legend4} and !$interfaces{$thisif}{noo}); } print "\r\n"; $i = $interfaces{$thisif}{shdesc}; $r = $routers{$router}{desc}; $r = $interfaces{$thisif}{hostname} if(!$r); $r = $router if(!$r); $r = "Unknown" if(!$r); $rrd = $interfaces{$thisif}{rrd}; foreach ( $gtype ) { /y/ and do { $resolution = 3600; $startpoint = "-1y"; last; }; /m/ and do { $resolution = 1800; $startpoint = "-1month"; last; }; /w/ and do { $resolution = 300; $startpoint = "-7d"; last; }; /6/ and do { $resolution = 60*$interfaces{$thisif}{interval}; $startpoint = "-6h"; last; }; $resolution = 60*$interfaces{$thisif}{interval}; # interval $startpoint = "-24h"; # 1 day } $resolution = 300 if(!$resolution); if( $gtype =~ /-/ ) { @opts = ( $rrd, "AVERAGE", "-e", "now".$startpoint, "-s", "end".$startpoint ); } elsif( $uselastupdate ) { $lastupdate = RRDs::last($rrd); $e = RRDs::error(); if(!$lastupdate) { print "Error reading rrd:\n$e\n"; return; } if($archivetime and $uselastupdate > 1 ) { @opts = ( $rrd, "AVERAGE", "-e", $archivetime, "-s", "end".$startpoint ); } else { @opts = ( $rrd, "AVERAGE", "-e", $lastupdate, "-s", "end".$startpoint ); } } else { @opts = ( $rrd, "AVERAGE", "-s", $startpoint ); } # Fetch data ( $start, $step, $names, $data ) = RRDs::fetch( @opts ); if( !$start or !$data ) { $e = RRDs::error(); print "Error retrieving data - do you have enough stored?\n"; print "Check that you have enough real data gathered to be able to export.\n"; print "$e\n"; return; } if( $gtype !~ /6/ ) { $opts[1] = 'MAX'; ( $mstart, $mstep, $mnames, $maxdata ) = RRDs::fetch( @opts ); # maxdata may now be null, if we dont have a MAX RRA available. } else { $maxdata = 0; # 6-hour graphs never have MAX available. } # Print data foreach $line ( @$data ) { @dat = localtime $start; $d = sprintf "%04d/%02d/%02d",($dat[5]+1900),($dat[4]+1),$dat[3]; $t = sprintf "%02d:%02d",$dat[2],$dat[1]; # hh:mm print "\"$r\"$comma\"$i\"$comma$d$comma$t$comma$start"; printf "$comma%12.1f", ($$line[0]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", ($$line[1]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noo}); if($interfaces{$thisif}{aspercent}) { printf "$comma%12.1f", 100.0*($$line[0]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", 100.0*($$line[1]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noo}); } if($gtype !~ /6/) { if($maxdata) { $mline = shift @$maxdata; $mline = [ 0,0 ] if(!$mline); # in case data runs out printf "$comma%12.1f", ($$mline[0]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", ($$mline[1]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noo}); if($interfaces{$thisif}{aspercent}) { printf "$comma%12.1f", 100.0*($$mline[0]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", 100.0*($$mline[1]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noo}); } } else { printf "$comma%12.1f", ($$line[0]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", ($$line[1]*$interfaces{$thisif}{mult}) if(!$interfaces{$thisif}{noo}); if($interfaces{$thisif}{aspercent}) { printf "$comma%12.1f", 100.0*($$line[0]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noi}); printf "$comma%12.1f", 100.0*($$line[1]/$interfaces{$thisif}{max}) if(!$interfaces{$thisif}{noo}); } } } printf "\r\n"; $start += $step; } # foreachline } # next interface in list } ############################################################################ # Help page sub do_help() { my($vurl,$iurl); my($javascript); $javascript = make_javascript({if=>"__none",rtr=>"none"}); start_html_ss({-script => $javascript, -onload => "LoadMenu()", -class=>'help' }); $vurl = "$meurlfull?page=verify&rtr=".$q->escape($router); $iurl = $config{'routers.cgi-smalliconurl'}; print $q->h1(langmsg(3006,"Information and Help")); print <Updates and support Updates to the routers.cgi script may be obtained from $APPURL. During development phases there may be daily updates, so check every so often. Support is available via the support forum, mailing list and directly - check this link for more details.

Online help

  • Diagnose configuration problems here (opens new window)
  • Show available link icons here (opens new window)

Credits

Thanks to the following people for supporting the development of this software by sending me a gift on my Wishlist! All listed in no particular order, in case you were wondering.
  • Pall Wiberg Joensen, Faroese Telecom, Faroe Islands
  • Ben Higgins, Dovetail Internet, USA
  • Mike Bernhardt, Arsin, USA
  • EDS Europe
  • Ruedi Kehl, Manor AG, Switzerland (twice!)
  • Allied Domecq, UK
  • Rob
  • Peter Cohen, Telia, USA
  • Jay Christopherson
  • David Hares, Network One
  • Reuben Farrelly, Netfilter, Australia
  • Network Operations, Roche Diagnostics GmbH, Germany
  • Keith Johnson, UK
  • J Herrera, Brown Publishing
  • Kristin Gorman, New York, USA
  • Inigo T Storm, ASV AG, Hamburg, Germany
  • M Williams, London, UK
  • Joseph Truong, USA
  • Babul Mukherjee, The Montopolis Group, San Antonio, USA
  • Matevz Turk, Slovenia
  • Barry Basselgia; the most generous contributor so far
  • Gary Higgs
  • Scott Monk, USA
  • Robert Gibson, Texas, USA
  • Andrew McClure, Santa Barbara, USA
  • Innokentiy Georgeievskiy, Moscow, Russia (Twice!)
  • Kirsten Johnson
  • Matti Wiersmuller, Switzerland
  • University of Auckland, New Zealand
  • Steven Hay, Alberta, Canada.
  • Dan Lowry, Scituate, USA
  • Alan Dean, Prospect, USA
  • Thomas Thong, Alameda, USA
  • Steve McDonald, Indiana, USA
  • Harry Edmondson, USA
  • Saul Herbert/Hugh David, ADV Films, UK and Australia
  • Francesco Duranti, Kuwait Petroleum Italia
  • Herman Poon, Ontario, Canada
  • Various generous but anonymous people
V2.0 Beta testers:
  • Garry Cook, MacTec Inc.
  • Ed Stalnaker, Rollins Corp, USA
  • Francesco Duranti, Kuwait Petroleum Italia
  • Neil Pike, Protech Computing
  • Brian Wilson, North Carolina State University
  • Martijn Koopsen, Energis NL
Contributors:
  • Ed Stalnaker (modified cfgmaker script)
  • Brian Wilson, Garry Cook, Aid Arslanagic, Andy Jezierski, Leo Artnts, James Keane, Todd Wiese, Jim Harbin (alternative icon sets)
  • Many other people for suggestions and bug reports.
Additional thanks to all the other people who have assisted by sending in bug reports and suggestions for improvement. Also, major thanks to Tobi Oetiker, the author of MRTG and RRDTool, without whom this interface would never have been created.

Legal Jargon

This software is available under the GNU GPL. More information is available in the text files accompanying this software, or on the web site. Please note that this software is provided without any warranty, or guarantee, and you use it at your own risk. In no event shall myself, my employers, or the owner of any web site distributing this software, be held liable for any loss or damage caused as a result of the use or misuse of this software or the instructions that accompany it.

EOT ; do_footer(); } # set cookies etc. for defaults. # the way we do this is by refreshing ourself with extra parameters. # The existence of the extra parameters causes the cookie to be set. sub do_config() { my ( $javascript, %routerdesc, $k ); my (%langs,$langfile,$langdir,$cc); my ($explore); $javascript = make_javascript({if=>"__none",rtr=>"none"}); start_html_ss({-script => $javascript, -onload => "LoadMenu()", -class=>'config' }); print $q->h2(langmsg(3007,"Personal Preferences")),"\n"; $explore = 'y'; $explore = $config{'routers.cgi-allowexplore'} if( defined $config{'routers.cgi-allowexplore'} ); if( $q->param('xset') ) { print $q->p($q->b(langmsg(9005,"Options have been saved."))),"\n"; } # Load language definitions %langs = (); $langs{''} = langmsg(3008,"No Preference"); if(defined $config{'web-langdir'}) { $langdir = $config{'web-langdir'} ; } else { $langdir = dirname($conffile); } foreach $langfile ( glob( $langdir.$pathsep."lang_*.conf" ) ) { if( -r $langfile and $langfile =~ /lang_(.+)\.conf/ ) { $cc = $1; open LANG,"<$langfile"; while ( ) { chomp; if( /^\s*description\s*=\s*(.*)/ ) { $langs{$cc} = $1; last; } } close LANG; } } # Load routers definitions foreach ( keys %routers ) { $routerdesc{$_} = $routers{$_}{desc}; } $routerdesc{''} = langmsg(3008,"No preference"); if($config{'routers.cgi-6hour'} =~ /y/i ) { @gorder = ( '6', @gorder ) if($gorder[0] ne "6"); } 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.")); print $q->hr; print "

\n"; # now a couple of hidden fields to preserve mtype and page print $q->hidden({ name=>"page", value=>"config", -override=>1 }),"\n", $q->hidden({ name=>"xmtype", value=>$mtype, -override=>1 }) ,"\n", $q->hidden({ name=>"xset", value=>"yes" }) ,"\n"; # Now the main fields, defrouter and defgtype. Dropdown lists. In a table. $defgstyle = $q->cookie('gstyle'); $defgstyle = 'n' if(!$defgstyle); print $q->table( { -border=>0 }, (( $explore =~ /[1y]/i )? $q->Tr( { -border=>"0", align=>"left" } , $q->td(langmsg(3100,"Default device:") )."\n", $q->td( $q->popup_menu( {name=>"defrouter", values=>["",sort bydesc keys(%routers)], labels=>{%routerdesc}, default=>$q->cookie('router')}) )."\n" ):""), (( $explore =~ /[1yi]/i )? $q->Tr( { -border=>"0", align=>"left" } , $q->td(langmsg(3101,"Default target/interface:") )."\n", $q->td( $q->popup_menu({ name=>"defif", values=>["", "__first", "__interface","__cpu","__memory","__summary", "__compact", "__incoming","__outgoing","__info", "__userdef" ], labels=>{__first=>langmsg(3012,"First target"), __summary=>langmsg(3013,"Summary page"), __info=>langmsg(3021,"Info Page"), __cpu=>langmsg(3016,"CPU performance"), __memory=>langmsg(3017,"Memory Usage"), __userdef=>langmsg(3018,"First user graph"), __interface=>langmsg(3019,"First Interface target"), __incoming=>langmsg(3014,"Incoming Graph"), __outgoing=>langmsg(3015,"Outgoing graph"), __compact=>langmsg(3020,"Compact Summary"), ""=>langmsg(3008,"No preference") }, default=>$q->cookie('if') }) )."\n" ):""), $q->Tr( { -border=>"0", align=>"left" } , $q->td(langmsg(3102,"Default graph type:") )."\n", $q->td( $q->popup_menu({ name=>"defgtype", values=>[@gorder], labels=>{%gtypes}, default=>$q->cookie('gtype') }) )."\n" ), $q->Tr( { -border=>"0", align=>"left" } , $q->td(langmsg(3103,"Default graph style:") )."\n", $q->td( $q->popup_menu({ name=>"defgstyle", values=>[@sorder], labels=>{%gstyles}, default=>"$defgstyle" }) )."\n" ), $q->Tr( { -border=>"0", align=>"left" } , $q->td(langmsg(3106,"Default language:") )."\n", $q->td( $q->popup_menu({ name=>"deflang", values=>[sort keys %langs], labels=>{%langs}, default=>"$language" }) )."\n" ), $q->Tr( { align=>"left" }, $q->td(""),$q->td( $q->submit({ name=>"Submit", value=>langmsg(3104,"Set Defaults") }) )."\n" ) ),"\n"; print "
"; print $q->br({clear=>"BOTH"}),"\n"; print $q->center($q->b($q->a({target=>"_top",href=>$meurlfull}, langmsg(3105,"Go to the current default page")))).$q->br,"\n"; do_footer(); } ########################### # Show an archive graph. sub do_archive($) { my( $javascript, $thisgraph, $thisgraphurl ); my( $inhtml ) = $_[0]; $javascript = make_javascript({archive=>$archive}); if($inhtml) { start_html_ss({ -script => $javascript, -onload => "LoadMenu()" , # -class=>($interfaces{$interface}{mode}?$interfaces{$interface}{mode}:'archive') -class=>'archive' }, $interfaces{$interface}{xbackground}?$interfaces{$interface}{xbackground}:""); } $thisgraphurl = $router; $thisgraphurl =~ s/[\?#\\\/]//g; $thisgraph = $thisgraphurl; $thisgraph = $config{'routers.cgi-graphpath'}.$pathsep.$thisgraph .$pathsep.$interface.$pathsep.$archive; $thisgraphurl = $config{'routers.cgi-graphurl'}.'/'.$thisgraphurl .'/'.$interface.'/'.$archive; if($inhtml) { print $q->h2({class=>'archive'},langmsg(3009,"Archive graph")); # any defined pagetop stuff print "
"; print expandvars($config{'routers.cgi-pagetop'}),"\n" if( defined $config{'routers.cgi-pagetop'} ); if( defined $config{'routers.cgi-mrtgpagetop'} and $config{'routers.cgi-mrtgpagetop'} =~ /y/i and $interfaces{$interface}{pagetop} and !$interfaces{$interface}{usergraph} ) { print expandvars($interfaces{$interface}{pagetop}),"\n"; } print "
"; } if( -f $thisgraph ) { if($inhtml) { print $q->img({ src=>$thisgraphurl, alt=>$archive }).$q->br."\n"; } else { #output the graph in binmode XXX } } else { if($inhtml) { print $q->p($q->b(langmsg(3010,"This graph has been deleted.")))."\n"; } else { # redirect to error print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); return; } } if( $inhtml and $archive =~ /(\d+)-(\d+)-(\d+)-(\d+)-(\d+)-([dwmys6]+)\./ ) { # try to get local formatting my( $dformat ) = "%c"; $dformat = $config{'web-shortdateformat'} if(defined $config{'web-shortdateformat'}); $dformat = $config{'web-longdateformat'} if(defined $config{'web-longdateformat'}); eval { require POSIX; }; if($@ or !$dformat) { print $q->br, $q->p(langmsg(3200,"Archive time").": $4:$5 $3/$2/$1 (" .$gtypes{$6}.")"); } else { print $q->br, $q->p(langmsg(3200,"Archive time").": " .POSIX::strftime($dformat,0,$5,$4,$3,($2-1),($1-1900)) ." (".$gtypes{$6}.")"); } } if($inhtml) { print $q->br."
"; if( defined $config{'routers.cgi-mrtgpagefoot'} and $config{'routers.cgi-mrtgpagefoot'} =~ /y/ and $interfaces{$interface}{pagefoot} and !$interfaces{$interface}{usergraph} ) { print expandvars($interfaces{$interface}{pagefoot}),"\n"; } print expandvars($config{'routers.cgi-pagefoot'}),"\n" if( defined $config{'routers.cgi-pagefoot'} ); print "
"; print "
"; print $q->hr."\n"; # print $q->a({href=>"javascript:parent.makearchmark('" # .$q->escape($router)."','".$q->escape($interface) # ."','".$q->escape($extra)."','$archive')"}, print $q->a({href=>"$meurlfull?".optionstring({page=>"", bars=>"", xmtype=>"", archive=>"$archive", xgtype=>"", xgstyle=>""}), target=>"_top"}, $q->img({src=>"${config{'routers.cgi-iconurl'}}bookmark.gif", alt=>langmsg(5016,"Bookmark"),border=>"0",width=>100,height=>20})),"\n"; # only for Yes, not for Read if( $config{'routers.cgi-archive'} =~ /y/i ) { print $q->a( { href=>$meurlfull.'?'.optionstring({archive=>$archive, page=>'graph',delete=>1}) }, $q->img({ border=>0, alt=>langmsg(5022,"Delete this graph"), width=>100, height=>20, src=>$config{'routers.cgi-iconurl'}."delete.gif" })).$q->br; } print "
"; do_footer(); } # inhtml } ########################### # Verification of everything. # This is more a debug utility, really. We display all the routers and # interfaces, also the available icons and check the sanity of the # routers.conf, and the graph directory. sub yesno($) { if(!$_[0]) { print $q->td({bgcolor=>"#ff0000",align=>"center",class=>"no"},"No"); } else { print $q->td({bgcolor=>"#00ff00",align=>"center",class=>"yes"},"Yes"); } } sub do_verify() { my($server,$iconpath, $ipath, $confpath, $iconurl,$graphpath, $graphurl); my($curif, $key, $rtr); my($testfile, $okfile); my($username) = ""; my($e,$rrdok, $rrdinfo); my($archroot,@days,$rrdfilename); my($s)=""; $server = "localhost"; $server = $2 if($meurl =~ /http(s?):\/\/([\w\.\-]+)\//); $s = "s" if($1); $confpath = $config{'routers.cgi-confpath'}; $graphpath = $config{'routers.cgi-graphpath'}; $graphurl = $config{'routers.cgi-graphurl'}; $iconurl = $config{'routers.cgi-smalliconurl'}; $ipath = $iconurl; $ipath =~ s#/#\\#g if($NT); $iconpath = $graphpath.$pathsep."..".$ipath; $iconpath = $graphpath.$pathsep."..".$pathsep."..".$ipath if(!-d $iconpath); $iconpath = "" if(!-d $iconpath); $username = $q->remote_user if($q->remote_user); start_html_ss({-title=>langmsg(3011,"Configuration Verification"), -class=>'verify'}); print $q->h1(langmsg(3011,"Configuration Verification")); print $q->ul( $q->li($q->a({href=>"#conf"},"Check routers.conf")), $q->li($q->a({href=>"#files"},"Check MRTG files")), $q->li($q->a({href=>"#targets"},"Check MRTG targets")), $q->li($q->a({href=>"#icons"},"Check available icons")), $q->li($q->a({href=>"#settings"},"Configuration settings")) ).$q->hr."\n"; print $q->a({name=>"conf"},$q->h2("routers.conf check"))."\n"; 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"; print "\n"; print "\n"; print "\n"; if( -r $conffile ) { print "\n"; } else { print "\n"; } print "\n" if($username); print "\n"; if( -d $graphpath ) { $testfile = $graphpath.$pathsep ."verylongfilename-------------testfile.png"; if( open TEST, ">$testfile" ) { print "\n"; close TEST; unlink $testfile; } else { print "\n"; } } else { print "\n"; } print "\n"; $testfile = $graphpath.$pathsep."redsquare.png"; unlink $testfile if( -f $testfile ); if( open GRAPH, ">$testfile" ) { binmode GRAPH; # this generates a PNG of a red square. print GRAPH "\211PNG\r\n\032\n\0\0\0\rIHDR\0\0\0\017\0\0\0\017\001\003\0\0\0\001\030" ."\a\t\0\0\0\003PLTE\377\0\0\031\342\t7\0\0\0\fIDATx\234c` \001\0\0\0-\0" ."\001\305\327\300\206\0\0\0\0IEND\256B`\202"; close GRAPH; print "\n"; } else { print "\n"; } print "\n"; print "\n"; if( @cfgfiles ) { print "\n"; print "
Script name$myname (Version $VERSION)
Configuration file
$conffile
Exists and is readble
Unable to read file
Authenticated username$username
Graphs path
$graphpath
Directory exists and is writeable
Unable to create files in directory!
Directory does not exist!
Graph URL
$graphurl
This should show a red square -->" .$q->img({src=>$graphurl."/redsquare.png",alt=>"Red Square", width=>15,height=>15}) ."<--
\n"; print "If it doesn't, then your graphurl does not match your graphpath.
Unable to create test file!
Check your graphpath setting above.
Icon URL
$iconurl
\n"; print "This should show a target -->" .$q->img({src=>$iconurl."target-sm.gif",width=>15, height=>15}) ."<--
\n" ."If it doesn't, then there is a problem.
MRTG files
Path: ".$confpath .$q->br."Files: ".$config{'routers.cgi-cfgfiles'}."
".($#cfgfiles + 1)." files detected OK."; } else { if(!-d $confpath) { print "Directory does not exist or is not readable!"; } else { print "No files found that match this pattern!"; } } print "
Perl libraries
RRDs, GD
\n"; eval { require "RRDs.pm"; }; if($@) { print $q->b("RRDs library NOT FOUND.")." This may however not be a problem if the library path is amended by the LibAdd birective in the MRTG files.".$q->br; print $@.$q->br; $rrdok = 0; } else { my($v); $RRDs::VERSION =~ /(\d+)\.(\d)(\d\d\d)/ if( $RRDs::VERSION !~ /(\d+)\.(\d\d\d)(\d\d)/ ); $v = "$1.".($2 + 0).".".($3 + 0); print "RRDs library found OK (Version $v)
"; print "You should upgrade to at least v1.0.36 to avoid problems.
" if($RRDs::VERSION < 1.00036); $rrdok = 1; } if( $config{'routers.cgi-compact'} =~ /n/i ) { print "GD library not required as compact is disabled in routers.conf"; } else { eval { require GD; }; if($@) { print $q->b("GD library NOT FOUND.")." This would not be a problem if you had compact=no in the routers.conf.".$q->br; print $@; } else { print "GD library found OK"; my $gd = new GD::Image(1,1); eval { print ": Ver ".$GD::VERSION."
"; }; eval { # must eval because old versions dont have 'can' or VERSION if( $gd->can('png') ) { print "- PNG Supported
"; } else { print "- PNG NOT supported
"; } if( $gd->can('gif') ) { print "- GIF Supported
"; } else { print "- GIF NOT supported
"; } if( $config{'web-png'} and !$gd->can('png')) { print "WARNING: You have PNG enabled in the routers2.conf but your GD does not support it!"; } if( !$config{'web-png'} and !$gd->can('gif')) { print "WARNING: You do not have PNG enabled in the routers2.conf but your GD does not support GIFs!"; } }; } } print "
Routingtable extensions"; if(defined $config{'routers.cgi-routingtableurl'}) { eval { require Net::SNMP; }; if($@) { 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; print $@; } else { print "Net::SNMP library found OK and extensions are enabled."; } } else { print "Routing table extensions are not enabled."; } print "
\n"; print $q->hr.$q->a({name=>"files"},$q->h2("MRTG files check"))."\n"; print $q->p("There files are taken from the cfgpath and cfgfiles directives in the [routers.cgi] section of the routers.conf file. If no files are listed below, then you should check that these definitions are correct."); print "confpath = ".$q->code($confpath).$q->br."\n"; print "cfgfiles = ".$q->code($config{'routers.cgi-cfgfiles'}).$q->br."\n"; print $q->br."\n"; print "\n"; foreach $rtr ( keys %routers ) { print ""; yesno $routers{$rtr}{inmenu}; yesno $routers{$rtr}{hastarget}; print "\n"; } print "
MRTG file nameDescriptionVisibleValidNotes
"; print $q->img({src=>$iconurl.$routers{$rtr}{icon},width=>15, height=>15})." " if(defined $routers{$rtr}{icon}); print $q->a({href=>("$meurlfull?page=verify&rtr=".$q->escape($rtr))},$rtr); if( $rtr !~ /^#/ ) { $okfile = $confpath.$pathsep.$rtr; $okfile =~ s/\.conf$/.ok/; $okfile =~ s/\.cfg$/.ok/; print "
No .ok file found
\n" ."Have you successfully run MRTG on this file yet?" if(!-f $okfile); } print "
".$routers{$rtr}{shdesc}.""; print "" if($routers{$rtr}{group}); print "" if($routers{$rtr}{server}); print "" if($routers{$rtr}{hostname}); print "
Group:".$routers{$rtr}{group}."
Server:".$routers{$rtr}{server}."
Hostname:".$routers{$rtr}{hostname}."
"; print $q->hr.$q->a({name=>"targets"},$q->h2("MRTG targets check"))."\n"; print "Current device: ".$q->b($router)." (".$routers{$router}{desc}.")".$q->br."\n"; print "MRTG file: ".$q->code($routers{$router}{file}).$q->br."\n" if($routers{$router}{file}); print $q->p("These targets are read from the MRTG file, and then displayed according to how they are interpreted."); print "
\n"; print "\n"; foreach $curif ( keys %interfaces ) { next if($interfaces{$curif}{usergraph}); print ""; yesno $interfaces{$curif}{inmenu}; yesno $interfaces{$curif}{insummary}; yesno $interfaces{$curif}{inout}; yesno $interfaces{$curif}{incompact}; print "\n"; } print "
Target
RRD File
ModeIn MenuIn SummaryIn/OutIn CompactArchivesNotes
"; print $q->img({src=>$iconurl.$interfaces{$curif}{icon},width=>15, height=>15})." " if(defined $interfaces{$curif}{icon}); print "$curif
".$interfaces{$curif}{rrd}; if(!-r $interfaces{$curif}{rrd}) { print "
Unable to read RRD file!" } print "
".$interfaces{$curif}{mode}.""; @days = (); if(defined $interfaces{$curif}{origrrd}) { $rrdfilename = $interfaces{$curif}{origrrd}; } else { $rrdfilename = $interfaces{$curif}{rrd}; } if($rrdfilename) { $archroot = dirname($rrdfilename).$pathsep.'archive'; $rrdfilename = basename($rrdfilename); if( defined $cachedays{$rrdfilename} ) { @days = @{$cachedays{$rrdfilename}}; $debugmessage .= "fromcache(dates:$rrdfilename)\n"; } else { foreach ( sort rev findarch( $archroot,$rrdfilename ) ) { if( /(\d\d)(\d\d)-(\d\d)-(\d\d)/ ) { push @days, "$1$2-$3-$4"; } } $cachedays{$rrdfilename} = [ @days ]; # Cache for later $debugmessage .= "cached[dates:$rrdfilename]\n"; } print ( $#days + 1 ); print " from ".$days[$#days] if($#days > -1); } else { print "N/A"; } print ""; if($rrdok and -r $interfaces{$curif}{rrd}) { $rrdinfo = RRDs::info($interfaces{$curif}{rrd}); $e = RRDs::error(); if(defined $rrdinfo and !$e) { print "RRD file format is legal."; print "
Interval ".($rrdinfo->{step}/60) ." minute(s)" if($rrdinfo->{step} != 300); print "
Not in MRTG format!" if(!defined $rrdinfo->{"ds[ds0].type"}); print "
Extended timeframe" if($rrdinfo->{"rra[0].rows"} > 799); } else { print $q->b("Error reading rrd:").$q->br.$e; } } else { print "N/A"; } print "
\n"; print $q->hr.$q->a({name=>"icons"},$q->h2("Available Icons"))."\n"; print "The available icons should be located in the rrdicons directory, currently defined to be:".$q->br."\n"; print "URL: ".$q->code("http$s://$server".$config{'routers.cgi-smalliconurl'}).$q->br; print "If the menu page is installed, you can get to it " .$q->a({href=>$config{'routers.cgi-smalliconurl'}},"here").".".$q->br."\n"; if($iconpath and -d $iconpath ) { # show available icons in here my( $c ) = 0; my($f,$b); print $q->br."\n"; foreach $f ( glob( $iconpath.$pathsep."*-sm.gif" ) ) { $b = basename $f; $c++; if($c eq 5) { $c = 1; print "\n"; } if( -r $f ) { print ""; } else { print ""; } } print "
".$q->img({src=>($iconurl.$b), width=>15, height=>15}); print " ".$b."Unable to read file $b
"; # verify print $q->p("If the above images do not display, then you may need to correct the iconurl parameter in the [routers.cgi] section of your routers.conf file."); } else { print "Checked directory $iconpath
\n"; 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 iconurl parameter in the [routers.cgi] section of your routers.conf file."); } print "This should show a target -->" .$q->img({src=>$iconurl."target-sm.gif",width=>15, height=>15}); print "<--. If it does not, correct your iconurl setting." .$q->br."\n"; print $q->hr.$q->a({name=>"settings"}, $q->h2("Active Configuration Settings"))."\n"; 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"; print "
    \n"; foreach ( sort keys %config ) { if( $_ eq 'web-auth-key' ) { print $q->li($q->b($_)." = \"not displayed\"")."\n"; } else { print $q->li($q->b($_)." = \"".$config{$_}."\"")."\n"; } } print "
".$q->br; do_footer(); } ########################### # If we get a bad page request sub do_bad($) { start_html_ss({-title=>"routers.cgi Error",-bgcolor=>"#ffd0d0", -class=>'error'}); print $q->h1(langmsg(8005,"Bad page request")); print $q->p("Error message was [".$_[0]."]")."\n"; print $q->p(langmsg(8007,"Check the format of the URL parameters for the page you are requesting."))."\n"; eval { print $q->dump; }; print $q->hr.$q->small("Error message generated by routers2.cgi")."\n"; print $q->end_html(); } ######################################################################## # MAIN CODE STARTS HERE ######################################################################## # Initialise parameters $opt_D = $opt_r = $opt_T = $opt_i = $opt_U = $opt_s = $opt_t = $opt_A = ""; $opt_I = $opt_C = $opt_a = ""; getopts('AICD:T:r:i:s:t:a:U:'); $opt_D = $opt_r if($opt_r); $opt_T = $opt_i if($opt_i); # override @pathinfo = split '/',$q->path_info() if($q->path_info()); $pagetype="main"; $pagetype=$q->param('page') if( defined $q->param('page') ); $pagetype=$q->param('xpage')if( defined $q->param('xpage'));# stupid persistence $pagetype="main" if(!$pagetype); $pagetype="graph" if($opt_A or $opt_D); # command line archive or generate $pagetype="image" if($opt_I); # command line archive $pagetype="csv" if($opt_C); # command line CSV extract $pagetype="graph" if(defined $q->param('searchhost')); $archive = ""; if( $q->param('archive') ){ $archive = $q->param('archive'); } # Deal with Authentication requests FIRST, before reading conf. if( $pagetype eq 'login' ) { # generate login page login_page; print "\n"; exit 0; } if( $pagetype eq 'logout' ) { # generate logout page logout_page; exit 0; } if( $q->param('username') ) { # someone is trying to log in if( user_verify( $q->param('username'), $q->param('password') ) ) { # OK $authuser = $q->param('username'); } else { # bad login: force it again force_login(langmsg(1005,"Invalid username/password combination")); exit 0; } } elsif($opt_U) { $authuser = $opt_U; # only via command line } else { # get username from other sources $authuser = verify_id; } # get these sections from the conf file. $extra = lc $q->param('extra') if($q->param('extra')); $bn = lc basename $q->url(-absolute=>1); $myname = $bn if($bn); readconf( 'routers.cgi','web','routerdesc','targetnames','targettitles', 'targeticons', 'servers', 'menu' ); initlang(undef); # initialise the language module, if defined # Generate archived graphs if($pagetype eq "archive") { $pagetype = "graph"; $archiveme = 1 if($config{'routers.cgi-archive'}=~/[y1]/i); } # Allow override for broken web servers $meurlfull = $config{'routers.cgi-myurl'} if( defined $config{'routers.cgi-myurl'} ); # Now, if we have forced security, and no authuser, then force the # login page regardless. if( defined $config{'web-auth-required'} and $config{'web-auth-required'} =~ /^[1y]/i and !$authuser ) { force_login(langmsg(1006,"Authorisation is required to view these pages")); exit 0; } # otherwise, if we have an authuser, set the cookie. if($authuser) { push @cookies, generate_cookie; $headeropts{-cookie} = [@cookies]; } # Find out our security level $seclevel = $config{'routers.cgi-level'} if( defined $config{'routers.cgi-level'} ); # background colour (for the americans) if ( defined $config{'routers.cgi-bgcolor'} and $config{'routers.cgi-bgcolor'} =~ /(#[\da-f]{6})/i ) { $defbgcolour = $1; } if ( defined $config{'routers.cgi-fgcolor'} and $config{'routers.cgi-fgcolor'} =~ /(#[\da-f]{6})/i ) { $deffgcolour = $1; } if ( defined $config{'routers.cgi-menufgcolor'} and $config{'routers.cgi-menufgcolor'} =~ /(#[\da-f]{6})/i ) { $menufgcolour = $1; } if ( defined $config{'routers.cgi-menubgcolor'} and $config{'routers.cgi-menubgcolor'} =~ /(#[\da-f]{6})/i ) { $menubgcolour = $1; } if ( defined $config{'routers.cgi-authfgcolor'} and $config{'routers.cgi-authfgcolor'} =~ /(#[\da-f]{6})/i ) { $authfgcolour = $1; } if ( defined $config{'routers.cgi-authbgcolor'} and $config{'routers.cgi-authbgcolor'} =~ /(#[\da-f]{6})/i ) { $authbgcolour = $1; } if ( defined $config{'routers.cgi-linkcolor'} and $config{'routers.cgi-linkcolor'} =~ /(#[\da-f]{6})/i ) { $linkcolour = $1; } # background colour (for the british) if ( defined $config{'routers.cgi-bgcolour'} and $config{'routers.cgi-bgcolour'} =~ /(#[\da-f]{6})/i ) { $defbgcolour = $1; } if ( defined $config{'routers.cgi-fgcolour'} and $config{'routers.cgi-fgcolour'} =~ /(#[\da-f]{6})/i ) { $deffgcolour = $1; } if ( defined $config{'routers.cgi-menubgcolour'} and $config{'routers.cgi-menubgcolour'} =~ /(#[\da-f]{6})/i ) { $menubgcolour = $1; } if ( defined $config{'routers.cgi-menufgcolour'} and $config{'routers.cgi-menufgcolour'} =~ /(#[\da-f]{6})/i ) { $menufgcolour = $1; } if ( defined $config{'routers.cgi-authbgcolour'} and $config{'routers.cgi-authbgcolour'} =~ /(#[\da-f]{6})/i ) { $authbgcolour = $1; } if ( defined $config{'routers.cgi-authfgcolour'} and $config{'routers.cgi-authfgcolour'} =~ /(#[\da-f]{6})/i ) { $authfgcolour = $1; } if ( defined $config{'routers.cgi-linkcolour'} and $config{'routers.cgi-linkcolour'} =~ /(#[\da-f]{6})/i ) { $linkcolour = $1; } if( defined $config{'web-png'} and $config{'web-png'}=~/[1y]/i ) { $graphsuffix = "png"; } if( defined $config{'routers.cgi-bytes'} and $config{'routers.cgi-bytes'}=~/y/i ) { $bits = "!bytes"; $factor = 1; } # Anyone giving us a cookie? $defgstyle = $q->cookie('gstyle'); if( ! $defgstyle ) { if( $config{'routers.cgi-graphstyle'} ) { my( $w ); # match against all the possibilities if( defined $gstyles{$config{'routers.cgi-graphstyle'}} ) { $defgstyle = $config{'routers.cgi-graphstyle'}; } else { foreach ( keys %gstyles ) { $gstyles{$_} =~ /^\s*(\w+)/; $w = lc $1; if( $w eq lc $config{'routers.cgi-graphstyle'} or $w eq $_ ) { $defgstyle = $_; last; } } } } $defgstyle = 'n' if(!$defgstyle); } $defbaropts = "Cami"; if(defined $config{'routers.cgi-bars'}) { $defbaropts = $config{'routers.cgi-bars'}; } $defgopts = $q->cookie('gopts'); $defgopts = "" if(!defined $defgopts); $defgtype = $q->cookie('gtype'); if( ! $defgtype ) { if( $config{'routers.cgi-graphtype'} ) { foreach ( @gorder ) { if( $_ eq $config{'routers.cgi-graphtype'} ) { $defgtype = $_; last; } } } } $defgtype = $gorder[0] if(! $defgtype); # identify menu type $mtype = "routers"; $mtype = $q->param('xmtype') if( defined $q->param('xmtype') ); if( defined $config{'routers.cgi-allowexplore'} and $mtype ne "options" ) { $mtype = "options" if($config{'routers.cgi-allowexplore'} !~ /y/ ); } # set the current device(router) and interface... $router = ""; $router = $defrouter = $q->cookie('router') if($q->cookie('router')); $router = $pathinfo[1] if($pathinfo[1]); $router = $opt_D if($opt_D); # command line $router = $q->param('rtr') if( $q->param('rtr') ); #$router = "" if(!defined $router or $router eq "none"); $router = "" if(!defined $router); # Only read in the routers table if (1) we need it, or (2) we are caching if(($pagetype eq "config") or ($pagetype =~ /menu/ and ($mtype eq "routers" or !$router)) or(!$router and $pagetype ne "help" and $pagetype ne "main" and $pagetype ne "head" and $pagetype ne "bar" and $pagetype) or($pagetype eq "graph" and -r $config{'routers.cgi-confpath'}.$pathsep.$router ) or ($pagetype eq "verify") or ($q->param('searchhost')) or $CACHE ) { read_routers(); if ((! $router or !defined $routers{$router} ) and $router ne "none") { if($config{'routers.cgi-defaultrouter'} and ( defined $routers{$config{'routers.cgi-defaultrouter'}} or $config{'routers.cgi-defaultrouter'} eq 'none' )) { $router = $defrouter = $config{'routers.cgi-defaultrouter'}; } else { $router = $defrouter = (sort bydesc keys(%routers))[0] ; } } } # Searching? if( $q->param('searchhost') ) { my($sh) = $q->param('searchhost'); $router = 'none'; # If not found foreach ( keys %routers ) { if( $_ =~ /^(.*[\\\/])?$sh\.[^\.\\\/]+$/i ) { $router = $_; last; } } if($router eq 'none') { foreach ( keys %routers ) { if( $_ =~ /$sh/i ) { $router = $_; last; } if( $routers{$_}{shdesc} =~ /$sh/i ) { $router = $_; last; } } } } # Do we need to redirect? if( defined $routers{$router} and $routers{$router}{redirect} ) { print $q->redirect($routers{$router}{redirect}.'?'. optionstring({page=>$pagetype,rtr=>$router}) ); exit(0); } # Get interface information, if we need it $defif = $q->cookie('if'); $defif = $config{'routers.cgi-defaultinterface'} if(!$defif and defined $config{'routers.cgi-defaultinterface'}); $defif = $pathinfo[2] if($pathinfo[2]); $interface = ($q->param('if'))?$q->param('if'):$defif ; $interface = $opt_T if($opt_T); # command line $interface = '_summary_' if($interface eq '__summary'); # backwards compatible $interface = 'none' if($router eq 'none'); $interface = "" if(! defined $interface ); if(( ($pagetype =~ /menu/ and $mtype ne "routers" ) or $pagetype eq "csv" or $pagetype eq "graph" or $pagetype eq "summary" or $pagetype eq "info" or $pagetype eq "compact" or $pagetype eq "compactcsv" or $pagetype eq "verify" or $pagetype eq "image" ) and $router ne "none" ) { if($router =~ /^#SERVER#/ ) { set_svr_ifs(); } else { read_cfg(); } $donecfg = 1; # set flag to show we have read in interfaces data if ( !$interface or $interface eq "__first" or $interface eq "__interface" or $interface eq "__memory" or $interface eq "__cpu" or $interface eq "__userdef" or ( $interface !~ /^__/ and !defined $interfaces{$interface} ) ) { if( $routers{$router}{defif} and defined $interfaces{$routers{$router}{defif}}) { $defif = $routers{$router}{defif}; } else { my( @ifs ); @ifs = sort byifdesc keys(%interfaces); $defif = 'none'; foreach ( @ifs ) { next if(!$interfaces{$_}{inmenu}); if( $interfaces{$_}{default} ) { $defif=$_; last; } $defif = $_ if($defif eq 'none'); if($interface eq "__interface" and $interfaces{$_}{mode} eq "interface") { $defif = $_; last; } if($interface eq "__memory" and $interfaces{$_}{mode} eq "memory") { $defif = $_; last; } if($interface eq "__cpu" and $interfaces{$_}{mode} eq "cpu") { $defif = $_; last; } if($interface eq "__userdef" and !$interfaces{$_}{issummary} and $interfaces{$_}{usergraph} ) { $defif = $_; last; } if($interface eq "__usersummary" and $interfaces{$_}{issummary} and $interfaces{$_}{usergraph} ) { $defif = $_; last; } } } # default specified $interface = $defif; } } # Archive deletion if( $q->param('delete') and $archive ) { # zap the requested archive my( $arch ); $arch = $router; $arch =~ s/[\?#\/\\]//g; $arch = $config{'routers.cgi-graphpath'}.$pathsep.$arch.$pathsep .$interface.$pathsep.$archive; unlink $arch; $archive = ""; } $gtype = $defgtype; $gstyle = $defgstyle; $gopts = $defgopts; $baropts = $defbaropts; $gtype = $q->param('xgtype') if( defined $q->param('xgtype') ); $gtype = $opt_t if($opt_t); $gstyle = $q->param('xgstyle') if( defined $q->param('xgstyle')); $gstyle = $opt_s if($opt_s); $gopts = $q->param('xgopts') if( defined $q->param('xgopts') ); $uopts = $q->param('uopts') if( defined $q->param('uopts') ); $baropts= $q->param('bars') if( defined $q->param('bars') ); $gtype = "d" if(!$gtype); # the graph time options # Allow 6-hour if every RRD involved is able to do it also. if( defined $config{'routers.cgi-6hour'} and $config{'routers.cgi-6hour'} =~ /y/i ) { # 6-hour mode is available. my($thisif); if($donecfg) { # have we read in the cfg files? if( $interface eq "__compact" ) { $usesixhour = 1; foreach $thisif ( keys %interfaces ) { next if(!$interfaces{$thisif}{incompact}); if($interfaces{$thisif}{interval} > 4) { $usesixhour = 0; last; } } } elsif ( $interface and defined $interfaces{$interface} and $interfaces{$interface}{userdefined} ) { # Userdefined - all member interfaces MUST be <5 $usesixhour = 1; foreach $thisif ( @{$interfaces{$interface}{targets}} ) { if($interfaces{$thisif}{interval} > 4) { $usesixhour = 0; last; } } } elsif( $interface and defined $interfaces{$interface} and $interfaces{$interface}{interval} < 5 ) { $usesixhour = 1; } $usesixhour = 1 if($config{'routers.cgi-6hour'} =~ /a/i ); # for 'always' # $gtypes{'6'} = "6-hour"; # already set @gorder = ( "6", @gorder ) # add it to the beginning of the list if($usesixhour); } else { # donecfg @gorder = ( "6", @gorder ); # Assume it's OK, fix it later } } # Should we verify that the RRA has enough data? This would take a bit of # extra time to do, but would prevent glitches. However we could say that # anyone who switches this option on is taking the responsibility for making # sure that the data is valid! if( defined $config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'} =~ /y/i # and $interface and defined $interfaces{$interface} # and $interfaces{$interface}{rrd} ) { push @gorder, "d-","w-","m-","y-"; } elsif ( defined $config{'routers.cgi-extendedtime'} and $config{'routers.cgi-extendedtime'} =~ /t/i and $interface and defined $interfaces{$interface} and $interfaces{$interface}{rrd} ) { # see if we have more data available... eval { require RRDs; }; if( !$@ ) { my( $infop ) = RRDs::info($interfaces{$interface}{rrd}); push @gorder, "d-" if( ${$infop}{"rra[0].rows"} > 799 ); push @gorder, "w-" if( ${$infop}{"rra[1].rows"} > 799 ); push @gorder, "m-" if( ${$infop}{"rra[2].rows"} > 799 ); push @gorder, "y-" if( ${$infop}{"rra[3].rows"} > 799 ); } } # sanity check #if( $gtype eq "6" and $interface !~ /^__/ and ( !$usesixhour # or ($interface and defined $interfaces{$interface} # and $interfaces{$interface}{interval} >= 5 ))) { # $gtype = $gorder[0]; #} if( $gtype eq "6" and $interface !~ /^_/ and !$usesixhour ) { $gtype = $gorder[0]; } if( defined $interfaces{$interface} and defined $interfaces{$interface}{suppress} ) { my($pat) = '['.$interfaces{$interface}{suppress}.']'; $gtype = 'dwmy' if($gtype =~ /$pat/); } if ( ! (defined $gtypes{$gtype}) or ( ($interface eq "__compact" or (defined $interfaces{$interface} and $interfaces{$interface}{issummary})) and (length ($gtype) > 2) )) { $gtype = $gorder[0]; } if( defined $config{'routers.cgi-uselastupdate'} and $config{'routers.cgi-uselastupdate'} =~ /y/i ) { $uselastupdate = 1; # set the flag for later. } else { $uselastupdate = 0; } # How big is a K ? Some people prefer 1024, some prefer 1000 if( defined $config{'routers.cgi-usebigk'} ) { if( $config{'routers.cgi-usebigk'} =~ /y/i ) # yes { $k = 1024; $M = $k * 1024; $G = $M * 1024; $T=$G*1024; $ksym = "K"; } elsif( $config{'routers.cgi-usebigk'} =~ /n/i ) # no { $k = 1000; $M = 1000000; $G = $M * 1000; $T=$G*1000;$ksym = "k"; } elsif( $config{'routers.cgi-usebigk'} =~ /m/i ) # mixed { $k = 1024; $M = 1024000; $G = $M * 1000; $T=$G*1000;$ksym = "K"; } else { $k = 1024; $M = 1024000; $G=$M*1000;$T=$G*1000;$ksym="K"; } # default } else { $k = 1024; $M=1024000; $G=$M*1000;$T=$G*1000;$ksym="K"; # default (mixed) } # Define page title and so on. $windowtitle = $config{'routers.cgi-windowtitle'} if ( defined $config{'routers.cgi-windowtitle'} ); $toptitle = $config{'routers.cgi-pagetitle'} if ( defined $config{'routers.cgi-pagetitle'} ); $toptitle = "".$q->b($windowtitle)."" if(!$toptitle); # Date format labels $monthlylabel=$config{'web-weeknumber'} if( defined $config{'web-weeknumber'} and $config{'web-weeknumber'} =~ /%[UVW]/ ); $dailylabel=$config{'web-hournumber'} if( defined $config{'web-hournumber'} and $config{'web-hournumber'} =~ /%[a-zA-Z]/ ); # Line widths $linewidth = $config{'routers.cgi-linewidth'} if( defined $config{'routers.cgi-linewidth'} and ($config{'routers.cgi-linewidth'}>0) and ($config{'routers.cgi-linewidth'}<5)); # Menu format if( (defined $config{'routers.cgi-twinmenu'} and $config{'routers.cgi-twinmenu'} =~ /y/i and $uopts !~ /T/ ) or $uopts =~ /t/ ) { $twinmenu = 1; } # Archived data # first, clean up cache if polluted if(defined $interfaces{$interface} and $interfaces{$interface}{origrrd}) { $interfaces{$interface}{rrd} = $interfaces{$interface}{origrrd}; } $archdate = ''; $archdate = $q->param('arch') if(defined $q->param('arch')); $archdate = $opt_a if($opt_a); if($archdate and $donecfg) { # archive date, and read in cfg file if($archdate=~/^(\d\d\d\d)-(\d\d)-(\d\d)/) { eval { require Time::Local; # only load it if we need it $archivetime = timelocal(0,0,0,$3,$2-1,$1-1900); }; } if( !$interface or !$interfaces{$interface}{rrd}){ $debugmessage .= "Invalid interface $interface!\n"; $archdate = ''; # This interface is not valid } elsif( !-d (dirname($interfaces{$interface}{rrd}).$pathsep.'archive' .$pathsep.$archdate)) { $debugmessage .= "Invalid date $archdate for interface $interface!\n"; $archdate = ''; # this date archive is not avaiable } else { # CHANGE THE DEFINED RRD FILE(s) IF WE ARE NOT ON MENU if($pagetype eq 'graph' or $pagetype eq 'csv' or $pagetype eq 'image' or $pagetype eq 'summary' or $pagetype eq 'compact' or $pagetype eq 'compactcsv' ) { my($thisif,$dn,$bn); my(@candidates) = ( $interface ); # push @candidates, @{$interfaces{$interface}{targets}} # if($interfaces{$interface}{usergraph} # or $interfaces{$interface}{issummary}); @candidates = (keys %interfaces) if($interface =~ /^__/ or $interfaces{$interface}{usergraph}); foreach $thisif ( @candidates ) { next if($thisif =~ /^_/); # skip userdefineds if(!$interfaces{$thisif}{origrrd}) { $interfaces{$thisif}{origrrd} = $interfaces{$thisif}{rrd}; } else { $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd}; } next if(!$interfaces{$thisif}{rrd}); $dn = dirname($interfaces{$thisif}{rrd}); $bn = basename($interfaces{$thisif}{rrd}); $interfaces{$thisif}{rrd} = $dn.$pathsep.'archive' .$pathsep.$archdate.$pathsep.$bn; if( ! -f $interfaces{$thisif}{rrd} ) { # if the archive doesnt exist $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd}; # $archdate = ''; $debugmessage .= "No archive for $thisif on $archdate\n"; } else { my($a) = (stat $interfaces{$thisif}{rrd})[9]; $archivetime = $a if(!$archivetime or ($a > $archivetime)); } } } else { } $uselastupdate = 2; # since we are now basing from old .rrd file } # $debugmessage .= "Archivetime: $archivetime\nArchdate: $archdate\n"; } elsif(defined $interfaces{$interface}) { if($pagetype eq 'graph' or $pagetype eq 'csv' or $pagetype eq 'compactcsv' or $pagetype eq 'summary' or $pagetype eq 'compact' ) { my($thisif); my(@candidates) = ( $interface ); push @candidates, @{$interfaces{$interface}{targets}} if($interfaces{$interface}{usergraph}); @candidates = (keys %interfaces) if($interface =~ /^__/); foreach $thisif ( @candidates ) { $interfaces{$thisif}{rrd} = $interfaces{$thisif}{origrrd} if($interfaces{$thisif}{origrrd}); } } } if( $opt_A ) { $pagetype = 'COMMAND'; $archiveme = 1; # override $|=1; print "Creating Graph...\n"; if($opt_T) { # target was set # Archive this graph if( !$interface or !defined $interfaces{$interface} or $interface=~/^__/ or $interfaces{$interface}{issummary} ) { print "This target is not appropriate to archive.\n"; print "Device/Target = [$router]/[$interface]\n"; print "Unknown Target\n" if(!defined $interfaces{$interface}); print "Illegal Target\n" if($interface=~/^__/); print "Summary Target\n" if($interfaces{$interface}{issummary}); print "Targets:\n".(join ",",(keys %interfaces))."\n"; print "Devices:\n".(join ",",(keys %routers))."\n"; exit(1); } do_graph(0); } else { # Do them all, for this device foreach $interface ( keys %interfaces ) { next if($interface=~/^__/ or $interfaces{$interface}{issummary} or !$interfaces{$interface}{inmenu} ); print "$interface... "; do_graph(0); } } exit(0); } # Start the page off if( $pagetype eq "graph" and !$archive and !$archdate ) { my($rtime) = 1800; $rtime =900 if($gtype =~ /w/); $rtime =300 if($gtype =~ /d/); $rtime = 60 if($gtype =~ /6/); $rtime = $config{'routers.cgi-minrefreshtime'} if( defined $config{'routers.cgi-minrefreshtime'} and $config{'routers.cgi-minrefreshtime'} > $rtime ); $headeropts{-expires} = "+5s"; $headeropts{-Refresh} = $rtime; $headeropts{-Refresh} .= "; URL=$meurlfull?".optionstring({}) if($archiveme); } $headeropts{-target} = $pagetype if($pagetype =~ /head|menub?|graph/ ); $headeropts{-target} = "graph" if( $pagetype =~ /compact|summary|help|info|config/ ); $headeropts{-target} = "_top" if ( !$pagetype ); if ( $pagetype eq "config" and $q->param('xset')) { push @cookies, $q->cookie( -name=>'gstyle', -value=>$q->param('defgstyle'), -path=>$q->url(-absolute=>1), -expires=>"+10y" ) if( defined $q->param('defgstyle')); push @cookies, $q->cookie( -name=>'gtype', -value=>$q->param('defgtype'), -path=>$q->url(-absolute=>1), -expires=>"+10y" ) if( defined $q->param('defgtype') ); push @cookies, $q->cookie( -name=>'router', -value=>$q->param('defrouter'), -path=>$q->url(-absolute=>1), -expires=>"+10y" ) if( defined $q->param('defrouter') ); push @cookies, $q->cookie( -name=>'if', -value=>$q->param('defif'), -path=>$q->url(-absolute=>1), -expires=>"+10y" ) if( defined $q->param('defif') ); if( defined $q->param('deflang') ) { initlang($q->param('deflang')); if($q->param('deflang')) { push @cookies, $q->cookie( -name=>'lang', -value=>$language, -path=>$q->url(-absolute=>1), -expires=>"+10y" ) ; } else { push @cookies, $q->cookie( -name=>'lang', -value=>'', -path=>$q->url(-absolute=>1), -expires=>"now" ) ; } } } # Character sets if(defined $config{'routers.cgi-charset'}) { $charset = $config{'routers.cgi-charset'}; }elsif(defined $config{'web-charset'}) { $charset = $config{'web-charset'}; } if($charset) { $headeropts{-charset} = $charset; $headeropts{-head} = $q->meta({-http_equiv => 'Content-Type', -content => "text/html; charset=$charset"}); } # Are we exporting CSV? if( $pagetype =~ /csv/ ) { my($fn) = "export.csv"; $csvmime=$config{'web-csvmimetype'} if(defined $config{'web-csvmimetype'}); $fn = $config{'web-csvmimefilename'} if(defined $config{'web-csvmimefilename'}) ; $csvmime .= "; filename=\"".$fn."\""; $headeropts{"-Content-Disposition"} = "filename=\"".$fn."\""; $headeropts{-type} = $csvmime ; } # The bar and image functions have to do their own headers as they may need # to redirect. $headeropts{-cookie} = [@cookies] if(@cookies); print $q->header({ %headeropts }) if($pagetype !~ /bar|image|COMMAND/); # # Now, we check the passed parameters to find out what sort of page to # serve up. If we can't work out which one to do, then we just serve the # index page if($pagetype) { for($pagetype) { /head/ and do { do_head(); last; }; /menu/ and do { do_menu(); last; }; # matches menu and menub /compactcsv/ and do { do_compact(1); last; }; /csv/ and do { if($interface eq "__compact") { do_compact(1); last; } last if( $interface =~ /^__/ ); # oops, this shouldnt happen do_export(); last; }; /image/ and do { if( $interface !~ /^__/ and defined $interfaces{$interface}) { if( $archive ) { do_archive(0); } else { do_graph(0); } } else { if($opt_I) { print "Interface: $interface\nError: Not defined\n"; } else { print $q->redirect($config{'routers.cgi-iconurl'}."error-lg.gif"); } } last; }; /graph|archive/ and do { if ( $interface eq "__info" ) { do_info(); } elsif ( $interface eq "__compact" ) { do_compact(0); } elsif ( $interface eq "__none" ) { do_empty(); } elsif ( $interface =~ /^__/ ) { do_bad("Bad target: $interface"); } elsif ( $interfaces{$interface}{usergraph} and $interfaces{$interface}{issummary} ) { do_summary(); } else { if( $archive ) { do_archive(1); } else { do_graph(1); } } last; }; /help/ and do { do_help(); last; }; /main/ and do { do_main(); last; }; /info/ and do { do_info(); last; }; /summary/ and do { do_summary(); last; }; /compact/ and do { do_compact(0); last; }; /config/ and do { do_config(); last; }; /bar/ and do { do_bar(); last; }; /verify/ and do { if( !defined $config{'routers.cgi-allowexplore'} or $config{'routers.cgi-allowexplore'} =~ /[1y]/i ) { do_verify(); last; } do_bad(langmsg(8006,"You do not have authority to view the configuration")); last; }; do_bad("Bad pagetype: $pagetype"); } } else { do_main() } # Clean up if($CACHE and $archdate) { if(defined $interfaces{$interface} and defined $interfaces{$interface}{origrrd}) { $interfaces{$interface}{rrd} = $interfaces{$interface}{origrrd}; } } exit(0);