#!/usr/bin/perl

use RRDs ;

# GENERAL options
$html_dir = "/docum.org/project/tc-snmp/example/html" ; # page with an overview of available graphs
$tcrrd = "http://home.docum.org/cgi-bin/docum.org/tc-snmp/tcrrd2.pl" ; # Place and name of the cgi-script on your webserver.  You don't have to specify the server name, but I have because I upload the pages to www.docum.org
$dir_rrd = "/docum.org/project/tc-snmp/example/data" ; # Place where databases are stored.  Make sure your webserver has read access to this dir.

# SNMP options 
# Name or ip-address of the snmp-server
$host = "kriek" ;

# Read community to access the snmp-server
$community = "public" ;

# Snmp version
$version = "2" ;

# OID to query on the snmp-server
$oid = ".1.3.6.1.4.1.18756" ;

##### No editing needed below this line ##############
#$DEBUG = "yes" ; # Uncomment to get debug info

# Check for the rrd-locatie directory
if ( ! -d $dir_rrd ) {
	print "$dir_rrd : not found, Exitting\n" ;
	exit ;
}

# Start a new snmp session
use Net::SNMP ;
($session, $error) = Net::SNMP->session(
       -hostname      => $host,
       #-port          => $port,
       #-localaddr     => $localaddr,
       #-localport     => $localport,
       #-nonblocking   => $boolean,
       -version       => $version,
       #-timeout       => $seconds,
       #-retries       => $count,
       #-maxmsgsize    => $octets,
       #-translate     => $translate,
       #-debug         => $debugmask,
       -community     => $community,   # v1/v2c
       #-username      => $username,    # v3
       #-authkey       => $authkey,     # v3
       #-authpassword  => $authpasswd,  # v3
       #-authprotocol  => $protocol,    # v3
       #-privkey       => $privkey,     # v3
       #-privpassword  => $privpasswd,  # v3
    );
if (!defined($session)) {
  printf("ERROR: %s.\n", $error);
  exit 1;
}

# Get all the counters
my $result = $session->get_table( -baseoid => $oid );

if (!defined($result)) {
  printf("ERROR: %s.\n", $session->error);
  $session->close;
  exit 1;
}

open (MRTG, ">$html_dir/mrtg.cfg") || die "Can not open $html_dir/mrtg.cfg for writing.\n";
$counter = "0" ;
# Process all the counters
foreach $key (keys (%{$result})) {
  @split = split '\.', $key ;
  $major_minor = $split[-1] ;

  if ( $major_minor eq "0" ) {
    next ;
  } else {
    $minor = $major_minor % 65536 ;
    $minor = lc(sprintf'%X', $minor ) ; # Dec -> Hex
    $major = $major_minor / 65536 ;
    $major = lc(sprintf'%X', $major ) ; # Dec -> Hex
  }
  $device = $split[-2] ;
  $date_type   = $split[-3] ;

  if ( $date_type eq "6" ) {
    push @{$child{$device}{$result->{$key}}}, "$major:$minor" ;
  } elsif ( $date_type eq "7" ) {
    $interface{$device} = $result->{$key} ;
    $interface{$device}{"$major:$minor"} = $result->{$key} ;
  } elsif ( $date_type eq "8" ) {
    $type{$device}{"$major:$minor"} = $result->{$key} ;
  } elsif ( $date_type eq "9" ) {
    $bytes{$device}{"$major:$minor"} = $result->{$key} ;
    mrtg_info ("Bytes") ;
  } elsif ( $date_type eq "10" ) {
    $packets{$device}{"$major:$minor"} = $result->{$key} ;
    mrtg_info ("Packets") ;
  } elsif ( $date_type eq "11" ) {
    $dropped{$device}{"$major:$minor"} = $result->{$key} ;
    mrtg_info ("Dropped") ;
  } elsif ( $date_type eq "12" ) {
    $overlimit{$device}{"$major:$minor"} = $result->{$key} ;
#  } else {
#    print "Major:Minor = $major:$minor\n" ;
#    print "  date_type : $date_type\n" ;
#    print "  Result : $result->{$key}\n" ;
  }
}

close MRTG ;

sub mrtg_info {
  $counter ++ ;
  print MRTG "Target[router_$counter]: $key&$key:public\@$host\n" ;
  print MRTG "MaxBytes[router_$counter]: 100000000000\n" ;
  print MRTG "Title[router_$counter]: Class $major:$minor\n" ;
  print MRTG "PageTop[router_$counter]:<ul>\n" ;
  print MRTG "  <li>Interface: $device : $interface{$device}\n" ;
  print MRTG "  <li>Type: $_[0]\n" ;
  print MRTG "  </ul>\n\n\n" ;
}

# Create/Update the rrd files

# Create a page with an overview of all handles we found
# Refresh om de 300 seconden (5 minuten)
open (HTML, ">$html_dir/index.html") || die "Can not open $html_dir/index.html for writing.\n";
print HTML qq{<html><head>
<META HTTP-EQUIV="REFRESH" CONTENT="300">
<META HTTP-EQUIV="EXPIRES" CONTENT="Sat, 01 Jan 2001 00:00:00 GMT">
</head><body>
} ;

print HTML "<ul\n" ;
foreach $device (sort(keys(%interface))) {
  print HTML "<li>$interface{$device}\n" ;
  foreach $major_minor (sort(keys(%{$interface{$device}}))) {
    $rrd = $dir_rrd . "/" . $interface{$device}{$major_minor} . "." . $major_minor ;
    update_rrd ($rrd, "bytes", $bytes{$device}{$major_minor}) ;
    update_rrd ($rrd, "packets", $packets{$device}{$major_minor}) ;
#print "device : $device $interface{$device}{$major_minor}\n" ;
#print "major_minor : $major_minor\n" ;
#print "bytes : $bytes{$device}{$major_minor}\n" ;
#print "packets : $packets{$device}{$major_minor}\n" ;
#print "\n" ;
  }
  process_child ("ffff:ffff") ;
}
print HTML "</ul>\n" ;

sub process_child {
  my $child = $_[0] ;
  #print "child: $child @{$child{$device}{$child}}\n" ;
  print HTML "<ul>\n" ;
  foreach (sort(@{$child{$device}{$child}})) {
    print HTML "<li>$_ : " ;
    my @childs = @{$child{$device}{$_}} ;
    print HTML "<A HREF=$tcrrd?handle=$_&show=bytes&interface=$interface{$device}>bytes</A> / " ;
    print HTML "<A HREF=$tcrrd?handle=$_&show=packets&interface=$interface{$device}>packets</A>" ;
    if ( $#childs ne "-1" ) {
      my $childs = join "_", @childs ;
      print HTML " / Stacked : " ;
      print HTML "<A HREF=$tcrrd?handle=$_&show=bytes_sum&interface=$interface{$device}&childs=$childs>bytes</A> / " ;
      print HTML "<A HREF=$tcrrd?handle=$_&show=packets_sum&interface=$interface{$device}&childs=$childs>packets</A>" ;
    }
    process_child ($_) ;
  }
  print HTML "</ul>\n" ;
}

sub update_rrd () {
	my $rrd = $_[0] . "." . $_[1] . ".rrd" ;
	$rrd =~ s/:/_/g ;
	my $date = time () ;

	if ( not -f $rrd ) {
		print "Creating $rrd\n" if $DEBUG ;
		RRDs::create ($rrd,
			"DS:$_[1]:DERIVE:600:0:U",
			"RRA:AVERAGE:0.5:1:576","RRA:AVERAGE:0.5:6:576","RRA:AVERAGE:0.5:24:576","RRA:AVERAGE:0.5:288:576",
			"RRA:MIN:0.5:1:576","RRA:MIN:0.5:6:576","RRA:MIN:0.5:24:576","RRA:MIN:0.5:288:576",
			"RRA:MAX:0.5:1:576","RRA:MAX:0.5:6:576","RRA:MAX:0.5:24:576","RRA:MAX:0.5:288:576") ;
		$err = RRDs::error;
		print "Error while creating $rrd : $err\n" if $err ;
	}
	print "Updating $rrd\n  with $_[2]\n" if $DEBUG ;
	RRDs::update ("$rrd","$date:$_[2]");
	$err = RRDs::error;
	print "Error while updating $rrd : $err\n" if $err ;
} ;

print HTML qq{</body></html>};
close HTML;
