#!/usr/bin/perl

# Copyright (c) 2004 Torbjörn Svensson <azoff@se.linux.org>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use warnings;
use Date::Format;
use Net::SMTP;
use Net::DNS;
use Net::Ping;


my $ARGC = @ARGV;

my $Domain	= 'azoff.homeip.net'; # what domain
my $MailFrom	= "status\@$Domain"; # who will the mail come from?
my @MailTo	= (
		"info\@$Domain", # my self
		'pelle@teknikpark.se', # cc ISP
	);

my $Debug	=  ( defined($ARGV[0]) && $ARGV[0] eq "--debug" ) || 0;

my $Sleep	= 30; # how long to next check
my $Mail 	=  0; # if we gonna mail 
my $Date	=  0; # just save the date
my $HostDown	=  0; # if host is down of not
my $MailBody	= ''; # The mailbody
my $Subject	= ''; # Subject of the mail
my $PingHost	= ''; # Who should be 
my $MinJumps	=  9; # how many jumps to check for + head
my $Ping	= Net::Ping->new();
my $res		= Net::DNS::Resolver->new;


for( my $i=0; $i<$ARGC; $i++ ){
	if( $ARGV[$i] == '--target' ){
		$i++;
		$host = $ARGV[$i];
	
	} else if( $ARGV[$i] == '--mailto' ){
		$i++;
		$MailTo[0] = $ARGV[$i];
	
	} else if( $argv[$i] == '--mailfrom' ){
		$i++;
		$MailFrom = $argv[$i];
	
	} else if( $argv[$i] == '--debug' ){
		$Debug = $argv[$i];
	
	} else if( $argv[$i] == '--jumps' ){
		$i++;
		$MinJumps = $argv[$i];
	}

}

my $query	= $res->search($host);
if ($query){
	foreach my $rr ($query->answer) {
		next unless $rr->type eq "A";
		$PingHost = $rr->address;
	}
} else {
	warn "query failed: ", $res->errorstring, "\n";
	exit;
}




print "HOST: $PingHost\n";
print "TO: @MailTo\n";
print "Started ping.pl...\n";




# check forever! Just kiding ;)
while (1){

	# check if host is up
	if( $Ping->ping($PingHost, 5) ){
		if( $HostDown == 1 ){
			my $DownTime = time() - $Date;
			
			if ($DownTime > 20 ){
				$Mail	  = 1;
				$Subject  = "[STATUS] Downtime: ".$DownTime."s";
			}

			print "Down: ".time2str("%C", time())."\n";
			print "DownTime: $DownTime"."s\n";
			$Sleep	  = 30;
			$HostDown =  0;
		}
	} else {
		if( $HostDown == 0 ){
			$Sleep	  = 2;
			$HostDown = 1;
			$Subject  = 1;
			print "Down: ".time2str("%C", time())."\n";
		}
	}


	# if status change
	if( length($Subject) > 0 ){
		$Date = time();
		
		# print (for debug)
		if( $Debug ){
			print "Date: $Date\n";
			print "Subject: $Subject\n";
			print "Body: $MailBody\n";
		}
		
		if( $Mail == 0 ){
			# make the mail
			$MailBody  = "Target: $TARGET\n";
			$MailBody .=  "Nere: ".time2str("%C", $Date)."\n";
			

			# print out a traceroute
			$MailBody .= "\n\n";

			open MTR, "/usr/bin/mtr --report -n -c 1 $TARGET|";
			my $i=0;
			#$MailBody .= $_ while(<MTR>);
			while(<MTR>){
				$i++;
				$MailBody .= $_;
			}
			close MTR;
			
			# do not send report if more jumps than $MinJumps
			if( $i > $MinJumps ){
				$HostDown =  0;
				$MailBody = '';
				$Sleep 	  = 30;
			}

			$Subject = '';
		} else {
			$MailBody .= "\n\nUppe: ".time2str("%C", $Date)."\n";

			foreach my $rcpt (@MailTo){
				# skicka iväg mailet
				my $smtp = Net::SMTP->new(
							Host	=> $Domain,
							Hello	=> $Domain,
							TimeOut	=> 30,
							Debug	=> $Debug,
						);
				
				$smtp->mail($MailFrom);
				$smtp->to($rcpt);
				$smtp->data();

				$smtp->datasend("To: $rcpt\n");
				$smtp->datasend("From: $MailFrom\n");
				$smtp->datasend("Subject: $Subject\n");
				$smtp->datasend("\n");

				$smtp->datasend($MailBody);

				$smtp->dataend();

				$smtp->quit();
			}

			# reset
			$MailBody = '';
			$Mail	  =  0;
			$Subject  = '';
		}
	}

	sleep $Sleep; 

}

$Ping->close();

