#!/usr/bin/perl # # ifstatus.pl v0.1 # # This is an Extension script for the routers.cgi program. Install it # in your cgi-bin directory, and modify your MRTG .cfg files to call it: # # routers.cgi*Extension[targetname]: "Show current interface status" /cgi-bin/ifstatus.cgi camera2-sm.gif # # See the routers.cgi documentation for how to link this script in to your # MRTG .cfg files. # Remember that the SNMP community string is passed as a parameter to this # script, and be aware of the security implications of this. # # Remember to change the first line and the default .conf file location below # # Steve Shipway Jun 2002 # This script is covered by the terms of the GNU GPL. ########################################################################### use strict; use CGI; use Net::SNMP; my($VERSION) = "v0.1"; # Variables my( $conffile ) = '/usr/local/etc/routers2.conf'; my( $device, $community, $targetwindow, $target, $file, $backurl, $ifno ) = ( "","","graph","","","",""); my( $routersurl, $msg ); my( $q ) = new CGI; my( %config, %headeropts ); my( $thishost ) = $q->url(); my( $NT, $pathsep) = ( 0, '/' ); my( %portstat ) = (); my($SHDESC ) = "1.3.6.1.2.1.2.2.1.2"; my($DESC ) = "1.3.6.1.2.1.31.1.1.1.18"; my($SYSDESC) = "1.3.6.1.2.1.1.1.0"; my($IFINDEX) = "1.3.6.1.2.1.2.2.1.1"; my($IFDESCR) = "1.3.6.1.2.1.2.2.1.2"; my($IFTYPE ) = "1.3.6.1.2.1.2.2.1.3"; my($IFMTU ) = "1.3.6.1.2.1.2.2.1.4"; my($IFSPEED) = "1.3.6.1.2.1.2.2.1.5"; my($IFADMINSTATUS) = "1.3.6.1.2.1.2.2.1.7"; my($IFOPERSTATUS) = "1.3.6.1.2.1.2.2.1.8"; my($IFINOCTETS) = "1.3.6.1.2.1.2.2.1.10"; my($IFOUTOCTETS) = "1.3.6.1.2.1.2.2.1.16"; my($IFINERRORS) = "1.3.6.1.2.1.2.2.1.14"; my($IFOUTERRORS) = "1.3.6.1.2.1.2.2.1.20"; my($IPIFINDEX) = "1.3.6.1.2.1.4.20.1.2"; my($IPROUTEGW) = "1.3.6.1.2.1.4.21.1.7"; $thishost =~ /http:\/\/([^\/]+)\//; $thishost = $1; ####################################################################### # readconf: pass it a list of section names sub readconf(@) { my ($inlist, $i, @secs, $sec); @secs = @_; %config = (); # set defaults %config = ( 'routers.cgi-confpath' => ".",); ( open CFH, "<".$conffile ) || do { errorpage( "Error: unable to open file $conffile"); exit 0; }; $inlist=0; $sec = ""; while( ) { /^\s*#/ && next; /^\s*\[(\S*)\]/ && do { $sec = $1; $inlist=0; foreach $i ( @secs ) { if ( $i eq $1 ) { $inlist=1; last; } } next; }; if ( $inlist ) { /(\S+)\s*=\s*(\S.*?)\s*$/ and $config{"$sec-$1"}=$2; } } close CFH; # 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 ) { $pathsep = "\\"; $NT = 1; } # some path corrections: remove trailing path separators on f/s paths foreach ( qw/dbpath confpath graphpath graphurl/ ) { $config{"routers.cgi-$_"} =~ s/[\/\\]$//; } $config{"routers.cgi-iconurl"}.= '/' if( $config{"routers.cgi-iconurl"} !~ /\/$/); } ####################################################################### # read $file and get the interface details for $target sub read_file() { my( $c, $i ); if( $ifno != "" ) { # we already know it $portstat{'Interface Number'} = $ifno; return if($community) ; } return if(! -r $file or !$target); open CFG, "<$file" or return; while( ) { if( /^\s*Target\[(\S+)\]\s*:\s*(\S+):(\S+)@([^:\s]+)/i ) { next if($1 ne $target); $c = $3; $i = $2; $community = $c if($c); if( $i =~ /\d+/ ) { $ifno = $i; $portstat{'Interface Number'} = $i; last; } if( $i =~ /^\/([\d\.]+)/ ) { $portstat{'IP Address'} = $1; last; } if( $i =~ /^#(\S+)/ ) { $portstat{'Interface Name'} = $1; last; } last; } } close CFG; return if($ifno ne "" or !$community); # at this point, we should use SNMP if to get the ifno return; } ####################################################################### # return error message if there was an error # load up the $portstat hash, keyed on description sub snmpquery() { my( $tick, $cross ); my( $snmp, $snmperr, $resp ); $tick = $q->img({ src=>($config{'routers.cgi-iconurl'}."tick-sm.gif"), alt=>"Yes", border=>0}); $cross = $q->img({ src=>($config{'routers.cgi-iconurl'}."cross-sm.gif"), alt=>"No", border=>0}); ($snmp, $snmperr) = Net::SNMP->session( -hostname=>$device, -community=>$community, -timeout=>4 ); if($snmperr) { return $snmperr; } $resp = $snmp->get_request( "$IFDESCR.$ifno", "$IFADMINSTATUS.$ifno", "$IFOPERSTATUS.$ifno", "$IFSPEED.$ifno", "$IFMTU.$ifno", "$IFTYPE.$ifno", "$IFINOCTETS.$ifno", "$IFOUTOCTETS.$ifno", "$IFINERRORS.$ifno", "$IFOUTERRORS.$ifno" ); $portstat{"Description"} = $resp->{"$IFDESCR.$ifno"}; $portstat{"Errors total IN"} = $resp->{"$IFINERRORS.$ifno"}." bytes"; $portstat{"Errors total OUT"} = $resp->{"$IFOUTERRORS.$ifno"}." bytes"; $portstat{"Traffic total IN"} = $resp->{"$IFINOCTETS.$ifno"}." bytes"; $portstat{"Traffic total OUT"} = $resp->{"$IFOUTOCTETS.$ifno"}." bytes"; $portstat{"Interface Speed"} = $resp->{"$IFSPEED.$ifno"}." bps"; $portstat{"MTU"} = $resp->{"$IFMTU.$ifno"}." bytes"; $portstat{"Admin status"} = ($resp->{"$IFADMINSTATUS.$ifno"}?$tick:$cross) ." (".$resp->{"$IFADMINSTATUS.$ifno"}.")"; $portstat{"Operational status"} = ($resp->{"$IFOPERSTATUS.$ifno"}?$tick:$cross) ." (".$resp->{"$IFOPERSTATUS.$ifno"}.")"; $snmp->close; return 0; } ####################################################################### sub do_footer() { print $q->hr."\n"; print $q->a({ href=>"javascript:location.reload(true);" }, $q->img({alt=>"Refresh", border=>0, src=>$config{'routers.cgi-iconurl'}."refresh.gif" }))."\n"; print $q->hr.$q->small("$VERSION: Interface Status extension script for routers.cgi")."\n"; print $q->end_html(); } ####################################################################### # at this point, %portstat should hold the interface number that we query. sub mypage() { my( $javascript ) = "function RefreshMenu() { var mwin; var uopts; mwin = parent.menu; uopts = 'T'; if( parent.menub ) { mwin = parent.menub; uopts = 't'; } mwin.location = '".$routersurl."?if=__none&rtr=" .$q->escape($file)."&page=menu&xmtype=options&uopts='+uopts; }"; print $q->start_html({-title=>"Current Interface Status", -script=>$javascript, -onLoad=>"RefreshMenu()"}); print $q->h1("Current Interface Status"); print "\n"; foreach ( sort keys %portstat ) { print "\n"; } print "
$_".$portstat{$_}."
\n"; do_footer(); } ####################################################################### sub errorpage($) { my( $javascript ) = "function RefreshMenu() { var mwin; var uopts; mwin = parent.menu; uopts = 'T'; if( parent.menub ) { mwin = parent.menub; uopts = 't'; } mwin.location = '".$routersurl."?if=__none&rtr=" .$q->escape($file)."&page=menu&xmtype=options&uopts='+uopts; }"; print $q->start_html({-title=>"Error", -script=>$javascript, -onLoad=>"RefreshMenu()"}); print $q->h1("Unable to retrieve interface status"); print $q->p($_[0])."\n"; do_footer(); } ####################################################################### # Process parameters $device = $q->param('h') if(defined $q->param('h')); $file = $q->param('fi') if(defined $q->param('fi')); $target = $q->param('ta') if(defined $q->param('ta')); $ifno = $q->param('ifno') if(defined $q->param('ifno')); $community = $q->param('c') if(defined $q->param('c')); $backurl = $q->param('b') if(defined $q->param('b')); $targetwindow = $q->param('t') if(defined $q->param('t')); $conffile = $q->param('conf') if(defined $q->param('conf')); $routersurl = $q->param('url') if(defined $q->param('url')); $routersurl = "http://$thishost/cgi-bin/routers2.cgi" if(!$routersurl); readconf('routers.cgi','web'); # HTTP headers %headeropts = ( -expires=>"now" ); $headeropts{target} = $targetwindow if($targetwindow); print $q->header(%headeropts); read_file; if($ifno == "") { errorpage("Unable to identify a valid interface on the device."); } else { if( $msg = snmpquery() ) { errorpage("Unable to SNMP query the device.\n$msg"); } else { mypage(); } } # End exit(0);