#!/usr/local/bin/perl
#
# IPv6 ping statistics gathering tool
# written by SUMIKAWA Munechika <sumikawa@kame.net>
# original implementation by YAMASAKI Yasushi <yamapu@osk3.3web.ne.jp>
#
# Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#    This product includes software developed by WIDE Project and
#    its contributors.
# 4. Neither the name of the project nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $Id: pping.in,v 1.10 1999/02/03 08:03:30 sumikawa Exp $
# 
use Fcntl;
use DB_File;

# you should edit following lines manually
$pinghome = "/mnt/gmirror/ports/dns/geta/work/pping";
$title = "WIDE 6bone ping statistics";
$maintainer = "sumikawa\@kame.net";
$mailaddrs = "sumikawa\@kame.net, sumikawa\@ebina.hitachi.co.jp";

$pinggate = "darwintel";
#$ping    = "rsh $pinggate /sbin/ping6";
$ping     = "/sbin/ping6 -n";
$count    = 10;					# ping count

$hostfile = "$pinghome/hosts.ping";
$htmlfile = "$pinghome/index.html";
$logfile  = "$pinghome/pping.log";

$cache    = "$pinghome/dnscache.db";
$logcache = "$pinghome/logcache.db";

$tmpfile  = "/tmp/ping$$.log";
$lookup   = "/usr/local/bin/geta -s -6";

$fromaddr = "$maintainer";
$mail = "/usr/bin/mail";

$date = `date`;
chdir($pinghome);

tie(%ipaddr, "DB_File", $cache, O_RDWR|O_CREAT, 0644, $DB_HASH);
tie(%backlog, "DB_File", $logcache, O_RDWR|O_CREAT, 0644, $DB_HASH);

&ping_hosts();
&out_html();
&out_log();
#&out_mail();

untie %ipaddr;
untie %backlog;

exit;

#
# ping6 $count times per host
#
sub ping_hosts {
	open(HOST, $hostfile) || die "can't open host file\n";
	# iterate for each host
	$hosts = 0;
	$nahosts = 0;
	line: while (<HOST>) {
		chop;
		next line if (/^#/);
		if (/^- (.*)/) {
			$orga = $1;
			next;
		}
		if (/^[ \t]*([^ \t]+)/) {
			$org[$hosts] = $orga;
			$count{$orga}++;
			$name[$hosts] = $1;
		} else {
			next;
		}

		# name lookup
		open(LOOKUP, "$lookup $name[$hosts] |")
			|| die "can't exec $lookup\n";
		wait;
		if ($? > 0) {
			$ip = $ipaddr{$name[$hosts]}; 	
			if ($ip =~ /^$/) {
				printf("can't lookup $name[$hosts]\n");
				close(LOOKUP);
				$noaddr[$nahosts++] = $name[$hosts];
				next;
			}
		} else {
			chop($ip = <LOOKUP>);
			$ipaddr{$name[$hosts]} = $ip;
		}
		close(LOOKUP);

		# ping a host
		system("$ping -c $count $ip > $tmpfile");
		open(STAT, $tmpfile)
			 || die "can't open temporally file\n";
		$lossflag = 0;
		$rttflag = 0;
		while (<STAT>) {
			if (/([0-9.]*)% packet loss/) {
				$loss[$hosts] = $1;
				$lossflag = 1;
			} elsif (m|max = ([0-9.]*)/([0-9.]*)/([0-9.]*) ms|) {
				$min[$hosts] = $1;
				$avg[$hosts] = $2;
				$max[$hosts] = $3;
				$rttflag = 1;
			}
		}
		close(STAT);
		unlink($tmpfile);
		if (!$lossflag) {
			$loss[$hosts] = 100;
		}
		if (!$rttflag) {
			$min[$hosts] = "-";
			$avg[$hosts] = "-";
			$max[$hosts] = "-";
		}
		for ($i = 9; $i >= 0; $i--) {
		    $backlog{$hosts,$i+1} = $backlog{$hosts,$i};
		}
		$backlog{$hosts,0} = $loss[$hosts];
		$hosts++;
	}
	close(HOST);
}

#
# make statistics into html format
#
sub out_html {
	open(OUT, ">".$htmlfile) || die "can't open host file\n";
	# output html header
#-----------------------------------------------------
	print(OUT <<"EOF");
<title> $title </title>
<body>
<img src="ipv6.gif"><br>
<b><font size="+2">
  $title
</font></b><br>
<b> Last Updated: $date </b><br>
gathered by $pinggate pinging $count times per host every hour.<br>
<p>
<table border=3>
  <tr><th>packet loss</th>
      <td bgcolor=#c0e0c0> 0% - 20%</td>
      <td bgcolor=#d0e0c0>20% - 40%</td>
      <td bgcolor=#e0e0c0>40% - 60%</td>
      <td bgcolor=#e0d0c0>60% - 80%</td>
      <td bgcolor=#e0c0c0>80% - 100%</td>
</table>
<hr>
<table border=3>
	<tr><th colspan=2>host</th>
	    <th rowspan=2>packet loss</th>
	    <th colspan=3>round trip time [ms]</th>
	    <th colspan=1>host</th>
	    <th colspan=10>packet loss</th>
	<tr><th>org</th>
	    <th>name</th>
	    <th>minimum</th>
	    <th>average</th>
	    <th>maximum</th>
            <th>IPv6 address</th>
	    <th colspan=10>past 10 times</th>
EOF
#-----------------------------------------------------	
	for ($i = 0; $i < $hosts; $i++) {
		if ($loss[$i] < 20) {
			$bgcolor = "#c0e0c0";
		} elsif ($loss[$i] < 40) {
			$bgcolor = "#d0e0c0";
		} elsif ($loss[$i] < 60) {
			$bgcolor = "#e0e0c0";
		} elsif ($loss[$i] < 80) {
			$bgcolor = "#e0d0c0";
		} else {
			$bgcolor = "#e0c0c0";
		}
	if ($dup{$org[$i]} !=  1) {
		print(OUT "	<tr><th rowspan=$count{$org[$i]}>$org[$i]</th><td>$name[$i]</td>");
		$dup{$org[$i]}++;
	} else {
		print(OUT "	<tr><td>$name[$i]</td>");
	}
#-----------------------------------------------------
	print(OUT <<"EOF");
	    <td align=center bgcolor=$bgcolor>$loss[$i]%</td>
	    <td align=center>$min[$i]</td>
	    <td align=center>$avg[$i]</td>
	    <td align=center>$max[$i]</td>
	    <td>$ipaddr{$name[$i]}</td>
EOF
#-----------------------------------------------------	
		for ($j = 1; $j <= 10; $j++) {
			if ($backlog{$i,$j} < 20) {
				$bgcolor = "#c0e0c0";
			} elsif ($backlog{$i,$j} < 40) {
				$bgcolor = "#d0e0c0";
			} elsif ($backlog{$i,$j} < 60) {
				$bgcolor = "#e0e0c0";
			} elsif ($backlog{$i,$j} < 80) {
				$bgcolor = "#e0d0c0";
			} else {
				$bgcolor = "#e0c0c0";
			}
			print(OUT "<td align=center bgcolor=$bgcolor>$backlog{$i,$j}%</td>");
		}
	}
#-----------------------------------------------------	
	print(OUT <<"EOF");
</table>
<hr>
EOF
#-----------------------------------------------------	
	if ($nahosts) {
		print(OUT "cat't lookup: ");
		for ($i = 0; $i < $nahosts; $i++) {
			print(OUT "$noaddr[$i]");
			if ($i != $nahosts - 1) {
				print(OUT ", ");
			}
		}
		print(OUT "\n<br>");
	}
	print(OUT <<"EOF");
<address>
<a href="mailto:$maintainer">
$maintainer</a>
</address>
</body>
EOF
#-----------------------------------------------------	
	close(OUT);
}

#
# make statistics into text format so as to send as a mail
#
sub out_mail {
	open(OUT, "| $mail -s \"$title\" $mailaddrs" ) || die "can't send mails\n";
	print(OUT <<"EOF");
$title
$date
-------------------------------------------------------------------------------
                                                        pkt. round trip time [ms]  
hostname            IPv6 address                        loss minimum average maximum
-------------------------------------------------------------------------------
EOF
	for ($i = 0; $i < $hosts; $i++) {
		printf(OUT "%-20s%-35s", $name[$i], $ipaddr{$name[$i]});
		printf(OUT "%4s%%", $loss[$i]);
		printf(OUT "%8s%8s%8s\n", $min[$i], $avg[$i], $max[$i]);
	}
	print(OUT <<"EOF");
-------------------------------------------------------------------------------
EOF
	close(OUT);
}

sub out_log {
	open(LOG, ">> $logfile") || die "can't open log file\n";
	print(LOG "--- $date");
	for ($i = 0; $i < $hosts; $i++) {
		printf(LOG "%s %s %s\n", $name[$i], $loss[$i], $avg[$i]);
	}
	close(LOG);
}


syntax highlighted by Code2HTML, v. 0.9.1