#!/usr/local/bin/perl -w # CHANGE ABOVE PATH TO MATCH YOUR PERL LOCATION! You may remove the -w ##############################################################################. # routingtable.cgi : Version v1.4 # # Display the routing table for a specifiecd router # # 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.28, Perl 5.005_03, under Linux (RH6.1) # Also tested with ActivePerl 5.6 with Apache under NT # # This requires Net::SNMP to be installed. # First read the information in INSTALL and README about the security # issues of using this extension. # # Only Netscape appears to correctly support server push with MIME # multipart/replace - so, this script detects Netscape, and uses normal # delivery if Netscape is not sensed. # ##############################################################################. use strict; use CGI; # for CGI #use Net::SNMP; # ActivePerl users may need this uncommented ##############################################################################. my ($VERSION) = "v1.4"; my ($APPURL ) = "http://www.steveshipway.org/software/"; my ($APPMAIL) = "mailto:steve\@steveshipway.org"; ############################################################################## my( %protocol ) = ( 1=>"Other", 2=>"Local", 3=>"Net Mgmt", 4=>"ICMP", 5=>"EGP", 6=>"GGP", 7=>"Hello", 8=>"RIP", 9=>"IS-IS", 10=>"ES-IS", 11=>"IGRP", 12=>"bbnSpfIgp", 13=>"OSPF", 14=>"BGP", 15=>"15", 16=>"16", 17=>"17", 18=>"18", 19=>"19", 20=>"20" ); my( %types ) = ( 1=>"Other", 2=>"Invalid", 3=>"Direct", 4=>"Indirect" ); my( $Netscape ) = 0; my( $agent, $back, $router, $community, %headeropts ); my( %table ) = (); my( $IP ) = "1.3.6.1.2.1.4"; # oid of ip in mib my( $ROUTEENTRY ) = "$IP.21.1"; my( $message ) = ""; my( $BOUNDARY ) = "boundary--fhdsjkgfdrfy78975j0fhnrdhsdh"; my( $UPDATE ) = 4; # refresh 'working' page in this many seconds my( $thishost , $javascript, $file, $routersurl ); # initialize CGI use vars qw($q); $q = new CGI; $q->import_names('CGI'); my $meurl = $q->url(); ########################## # for parts sub start_section() { print "Content-Type: text/html\n\n"; } sub end_section() { print "\n--$BOUNDARY\n"; } sub end_multipart() { print "\n--$BOUNDARY--\n"; } ########################## # show progress of table load... sub progress($$) { return if(!$Netscape); start_section(); print $q->start_html(); print $q->h1(""); print $q->p("Loaded ".$_[0]." MIB entries, and ".$_[1]." routes...")."\n" if($_[0]); print $q->p("If you have a large routing table, or the remote router is on a distant or slow network, this may take a long time to complete. There will be approximately 12 MIB entries for each defined route.")."\n"; print $q->end_html(); end_section(); } ########################## # An entry in the table list is a hash: # dest, mask, cost, gw ########################## # collect the snmp data into %table # we snmpwalk ipRouteMetric1, ipRouteNextHop, ipRouteType, ipRouteProto, # and ipRouteMask, loading the data into the hash as we go. my( $ROUTEDEST ) = 1; my( $ROUTEMETRIC ) = 3; my( $ROUTENEXTHOP ) = 7; my( $ROUTETYPE ) = 8; my( $ROUTEPROTO ) = 9; my( $ROUTEAGE ) = 10; my( $ROUTEMASK ) = 11; sub fetch_table() { my($snmp, $snmperr, $resp); my( $k, $ip, $mib,$sec, $c, $u, $r ); my( $lasttime, $thistime ); ($snmp, $snmperr) = Net::SNMP->session( -hostname=>$router, -community=>$community, -timeout=>4 ); if($snmperr) { $message = $snmperr; return; } $c = $r = 0; progress(0,0); $lasttime = time; $resp = $snmp->get_next_request( $ROUTEENTRY ); if(!defined $resp ) { $message = $snmp->error(); $snmp->close(); return; } while( defined $resp ) { foreach $k ( keys %$resp ) { $k =~ /^(.+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)$/; $ip = "$3.$4.$5.$6"; $sec = $1; $mib = $2; last if( $sec ne $ROUTEENTRY ); $c++; if( $Netscape and (time - $lasttime) > $UPDATE ) { progress($c,$r); $lasttime = time; }; if( $mib == $ROUTEDEST ) { if($resp->{$k} eq "0.0.0.0" ) { $table{$ip}{dest} = "default"; } else { $table{$ip}{dest} = $resp->{$k}; } $r++; next; } if( $mib == $ROUTEMETRIC ) { $table{$ip}{metric} = $resp->{$k}; next; } if( $mib == $ROUTENEXTHOP ) { $table{$ip}{gw} = $resp->{$k}; next; } if( $mib == $ROUTETYPE ) { $table{$ip}{type} = $types{$resp->{$k}}; next; } if( $mib == $ROUTEPROTO ) { $table{$ip}{proto} = $protocol{$resp->{$k}}; next; } if( $mib == $ROUTEAGE ) { $table{$ip}{age} = $resp->{$k}; next; } if( $mib == $ROUTEMASK ) { $table{$ip}{mask} = $resp->{$k}; next; } } last if( $sec ne $ROUTEENTRY ); $resp = $snmp->get_next_request( keys %$resp ); } $snmp->close; } ########################## # print it out in HTML sub print_table() { my( $bg, $fg, %c, $s, $e ); print "
" .$q->code($@)."\n"; print $q->p($q->a({href=>$back,target=>"_self"},"Return to previous")),"\n" if($back); do_footer; print $q->end_html(); end_multipart() if($Netscape); exit(0); } if( !$router or !$community ) { start_section() if($Netscape); do_bad(); end_multipart() if($Netscape); exit(0); } fetch_table(); # This assumes that the routingtable and routers2 scripts are on the same # server, and that the routers2.cgi script has not been renamed. This may # not be the case. It may be better to parse the URL up to the ? and add # different options? $javascript = "function RefreshMenu() { var mwin; var uopts; uopts = 'T'; mwin = parent.menu; if( parent.menub ) { mwin = parent.menub; uopts = 't'; } mwin.location = '".$routersurl."?if=__none&rtr=" .$q->escape($file)."&page=menu&xmtype=options&uopts='+uopts; }"; start_section() if($Netscape); print $q->start_html({title=>"Routing table for $router", script=>$javascript,onLoad=>"RefreshMenu()"}); print $q->h1("Routing table: $router"),"\n"; print_table(); if($back) { print $q->p($q->a({href=>$back,target=>"_self"},"Return to previous")),"\n"; } do_footer(); print "\n\n"; print $q->end_html(); end_multipart() if($Netscape); exit(0);