#!/usr/local/bin/perl
##################################################################
# $Id: mrtg-ping-probe,v 1.11 1997/08/23 01:33:23 pwo Exp $
# mrtg-ping-probe release $Name: Release_1_6_0 $
#
# Copyright (c) 1997 by Peter W. Osel <pwo@guug.de>, Cupertino.
# All Rights Reserved.
#
# See the file COPYRIGHT in the distribution for the exact terms.
#
##################################################################
#
# "I saw -- from the cathedral -- you were watching me"
#
#	-- Tanita Tikaram, `Cathedral Song'
#	on: Tanita Tikaram, `Ancient Heart', 1988, WEA Records
#
##################################################################
require 5.003;
use Getopt::Std;
use File::Basename;
use Config;

$Prog_name = basename($0);		# Who I am
$Prog_vers = q$Revision: 1.11 $;
$Prog_id = q$Id: mrtg-ping-probe,v 1.11 1997/08/23 01:33:23 pwo Exp $;
$Usage = "Usage: $Prog_name [-hvV] [-k count] [-l length] host\n";

# Parse Command Line:
die $Usage unless getopts('hk:l:vV');

# Generic Options
$PrintHelp	= defined($opt_h) ? $opt_h : 0;
$Verbose	= defined($opt_v) ? $opt_v : 0;
$PrintVersion	= defined($opt_V) ? $opt_V : 0;

# Tool Specific Options
$PacketCount	= defined($opt_k) ? $opt_k : "10";
$PacketLength	= defined($opt_l) ? $opt_l : "56";

# Check Sanity of Arguments
unless ($PacketCount =~ /^\d+$/) {
	print STDERR "$Prog_name: FATAL: option -k requires numeric argument.\n";
	++$err;
	}
unless ($PacketLength =~ /^\d+$/) {
	print STDERR "$Prog_name: FATAL: option -l requires numeric argument.\n";
	++$err;
	}

if ($err) {
	print STDERR $Usage;
	exit(1);
	}


if ($PrintVersion ) {
	print STDERR "$Prog_name: $Prog_vers\n";
	exit(0);
	}

if ($PrintHelp) {
	print $Usage;
	exit(0);
	}

if (@ARGV > 1) {
	print STDERR "$Prog_name: ERROR: ignoring superfluous arguments\n";
	print STDERR "$Usage";
	}

if (@ARGV < 1) {
	print STDERR "$Prog_name: FATAL: ping what?\n";
	print STDERR "$Usage";
	exit(1);
	}


($HostToPing) = @ARGV;

# Still looking for a cool way to automatically support multiple
# different ping programs on multiple platforms.  Or better:
# Still looking for a perl internal ping function that reports
# round trip time.

($pt_min, $pt_avg, $pt_max) = ping($HostToPing, $PacketLength, $PacketCount);

# The external mrtg probe returns up to 4 lines of output:
#	1. Line: current state of the 'incoming bytes counter'
#	2. Line: current state of the 'outgoing bytes counter'
#	3. Line: string, telling the uptime of the target.
#	4. Line: telling the name of the target.
# We leave out line 3, and 4.

print "$pt_max\n$pt_min\n";

exit(0);

##################################################################
# ping host retrieve and return min, avg, max round trip time
# relying on finding a standard ping in PATH.
# Try to not be platform specific if at all possible.
#
sub ping {
	my($host, $length, $count) = @_;
	my(%ping, $ping_output);

	# List of known ping programs
	%ping = (
		'aix'	=>	"/etc/ping $host $length $count",
		'bsdos'	=>	"/bin/ping -s $length -c $count $host",
		'freebsd' =>	"/sbin/ping -s $length -c $count $host",
		'hpux'	=>	"/etc/ping $host $length $count",
		'irix'	=>	"/usr/etc/ping -c $count -s $length $host",
		'linux'	=>	"/bin/ping -c $count -s $length $host",
		'solaris' =>	"/usr/sbin/ping -s $host $length $count",
		'sunos'	=>	"/usr/etc/ping -s $host $length $count",
		);

	unless (defined($ping{$Config{'osname'}})) {
		print STDERR "${Prog_name}: FATAL: Not yet configured for $Config{'osname'}\n";
		exit(1);
		}

	unless (open(PING, "$ping{$Config{'osname'}} 2>&1 |")) {
		print STDERR "${Prog_name}: FATAL: Can't open $ping{$Config{'osname'}}: $!";
		exit(1);
		}

	while (<PING>) {
		$ping_output .= $_;
		close(PING), return($1,$2,$3)
			if m|^round-trip(?: \(ms\) )? min/avg/max = (\d+)(?:\.\d+)?/(\d+)(?:\.\d+)?/(\d+)(?:\.\d+)?|;
		}

	print STDERR "${Prog_name}: ERROR: Could not find ping summary for $host\n";
	print STDERR "${Prog_name}: INFO: The output of the ping command $ping{$Config{'osname'}} was:\n";
	print STDERR "$ping_output\n";

	close(PING), return(0,0,0);
}

=head1 NAME

mrtg-ping-probe - a round trip time probe for MRTG

=head1 SYNOPSIS

B<mrtg-ping-probe>
[ B<-hvV> ]
[ B<-k> I<count> ]
[ B<-l> I<length> ]
I<host>

=head1 DESCRIPTION

B<mrtg-ping-probe> pings the given host I<host> and prints on stdout
two lines with the maximum round trip time, and the minimum round trip
time.  It is meant to be called by the Multi Router Traffic Grapher
(MRTG).


=head1 OPTIONS


=over 8

=item B<-h>

print help on stdout and exit.

=item B<-v>

Be more verbose.

=item B<-V>

Print version number on stderr and exit.

=item B<-k> I<count>

Specifies the number of of ping packets to be sent.
The default is to send 10 ping packets.

=item B<-l> I<length>

Use I<length> as the length of the data portion of the ICMP ECHO
request packet.  The default I<length> is 56 data bytes.


=back


=head1 RETURN VALUE

The program exits with an exit value 0, if it believes it was successful.


=head1 EXAMPLES

To retrieve the maximum and minimum round trip time to the host
B<ricochet>, using the default length and count:

B<mrtg-ping-probe ricochet>


To retrieve the maximum and minimum round trip time to the host
192.168.192.42, using 17 1000 data bytes pings:

B<mrtg-ping-probe -k 17 -l 1000 192.168.192.42>


=head1 FILES

B<mrtg-ping-probe> uses an external ping program,
like F</usr/sbin/ping>.

=head1 SEE ALSO

mrtg(1), mrtg-ping-cfg, ping(1), mrtg.cfg-ping

=head1 DIAGNOSTICS

=over 4

=item FATAL: Not yet configured for I<osname>

Currently B<mrtg-ping-probe> depends on an external ping program,
which every operating systems hides in another place.  Also different
programs require different arguments.  We have a configuration table
listing the ping program for each operating systems.  You have to figure
out how to call which program on your platform, and add to the
information to the table.  Please contribute back any additions, so I
can include them in the next version.

=item ERROR: ignoring superfluous arguments

More than one argument was given.  B<mrtg-ping-probe> will ignore all
but the first argument.  The first argument is taken as a hostname or
IP address of an host and B<mrtg-ping-probe> will try to ping it.

=item FATAL: ping what?

No argument was given.  B<mrtg-ping-probe> terminates, as there is
nothing to ping.

=item FATAL: Can't open ping: I<some reason>

B<mrtg-ping-probe> was not able to execute the external ping program.
Check the pathname and permissions of the external ping program.
I<some reason> might give some useful hints.

=item ERROR: Could not find ping summary

B<mrtg-ping-probe> was not able to find the ping summary.  Most likely,
the host is not reachable.  If your operating system changed (e.g. it
was upgraded to a new version, or a new version of the ping program was
installed), it might also be necessary to change the regular expression
that extracts the round trip times.  You might want to use the perl
script check-ping-fmt (which is part of the soure distribution) to test
the regular expression.

The captured output of the ping program is printed and will (hopefully)
give further hints why this problem occurred.

=back

=head1 RESTRICTIONS

B<mrtg-ping-probe> currently depends on an external ping(1) program.
If the external program does not support an option, the option
given to B<mrtg-ping-probe> will be ignored.

=head1 AUTHOR

Written by Peter W. Osel E<lt>pwo@guug.deE<gt>.

