#!/usr/bin/perl
#written Andrew Stringer 03/04/06 to test DNS server response & availability
#This assumes that servers to be tested have a zone of the domain being tested!

use strict;
use warnings;

use Net::DNS;
use XML::Simple;
use Data::Dumper;


sub DNSLOOKUP {
#read in variables
my $query = shift;
my $type = shift;
my $nameserver = shift;

#declare $result2
my $result2 = ' ' ;

my $res = Net::DNS::Resolver->new(
        nameservers => [$nameserver],
        recurse     => 0,
        debug       => 0,
  );

#do query
  my $result1 = $res->send($query, $type);

#test result1 to check if defined
  if ($result1) {
      foreach my $rr ($result1->answer) {
          next unless $rr->type eq "A";
          $result2 = $rr->address ;
      }
  }
  else {
        $result2 = "No response";
  }

return $result2 ;

#end dnslookup
}


sub SERIAL {
my $domain = shift;
my $nameserver = shift;

#if ($debug){print "Serial - nameserver is $nameserver \n";}
print "Serial - nameserver is $nameserver \n";

my $soa_req ;
my $zone_serial ;

my $res = Net::DNS::Resolver->new;
$res->nameservers($nameserver);
$soa_req = $res->send($domain, 'SOA', 'IN');

if (defined ($soa_req))
{
$zone_serial = ($soa_req->answer)[0]->serial ;
}
else
{
$zone_serial = '0';
}
return $zone_serial ;
#end of serial
}


sub PERCENT {
my $success = shift ;
my $failure = shift ;

# % is (amount/total)*100
my $percent1 = ($success/($success+$failure))*100 ;

#round off to two decimal places
my $percent = (int($percent1*100))/100 ;
return $percent

#end of percent sub
}



MAIN:
#start of body of program
{
#set up & declare environment variables

#set to 1 for diagnostic output, 0 for normal operation
use vars qw($debug);
$debug = '1';

my $rootdomain = 'rainsbrook.co.uk';
my $query = 'walnut.rainsbrook.co.uk' ;
#my $nameserver = '82.71.89.10' ;
my $nameserver = '192.168.5.11' ;
my $configfile = '/data/rainsbrook/http/monitor/dns-rainsbrook-monitor.xml' ;
my $resultfile = '/data/rainsbrook/http/monitor/dns-rainsbrook-monitor.html' ;
my $tempresultfile = '/data/rainsbrook/http/monitor/dns-rainsbrook-monitor.tmp' ;
my $url = 'http://192.168.5.11/monitor/dns-rainsbrook-monitor.html' ;
my $counter1 = '0' ;
my $sla = '90' ;
my @serialnumber ;
my $zonestatus ;
my $dnsresultcolour = '#ff0000';
my $serialresultcolour = '#ff0000';
my $slaresultcolour = '#ff0000';
my $success ;
my $failure ;
my $percent ;

#set localtime
my $time = localtime ;


#open file for html output
open (OUTPUTFILE, ">$tempresultfile") ;

#write out html header
print OUTPUTFILE <<ENDOFTEXT1 ;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>$rootdomain DNS server test stats.</title>
<meta http-equiv="refresh" content="30;URL=$url">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="Stylesheet" type="text/css" href="http://ns0.example.com/layout.css" />
    <!-- Disable IE6 image toolbar -->
<meta http-equiv="imagetoolbar" content="no" />
<link rel="icon" href="./favicon.ico" type="image/x-icon"

</head>

<body text="#000000" bgcolor="#ffffff" link="0000EE" vlink="#551A8B">
<div>
<a href="http://ns0.example.com/index.shtml">
<img src="http://ns0.example.com/bcclogo-ns0.png" class="logo" 
 border="1" title="Back to ns0.example.com" height="76" width="429" />

</a>
</div>

<div class="box">
<h5>DNS results for $rootdomain</h5>
<div class="body">
Last updated at $time
<br>

<!--start of results table-->
<table border = "1">
<tr>
<th>DNS server</th>
<th>query</th>
<th>result</th>
<th>answer</th>
<th>Success :-)</th>
<th>Failure :-(</th>
<th>Percent</th>
</tr>
ENDOFTEXT1

#read in config file
my $config = XMLin($configfile);

foreach my $e (@{$config->{server}})
{
        my $nameserver = $e->{nameserver};
        my $query = $e->{query};
        my $domain = $e->{domain};
        my $type = $e->{type};
        my $reply = $e->{reply};
        my $success = $e->{success};
        my $failure = $e->{failure};

        my $fqdn = "$query.$domain" ;
        my $dnsresult = ' ' ;

        if ($debug){print "++++++++++++++++++++++++++++++++++++++++\n";}
        if ($debug){print "Asking $nameserver for $fqdn type $type.\n";}

        $dnsresult = &DNSLOOKUP ($fqdn, $type, $nameserver);
        if ($dnsresult eq "") {$dnsresult = 'Resolution error'; }

        if ($debug){print "Reply is $dnsresult, expected $reply. \n";}

        if ($dnsresult eq $reply)
        {
        $dnsresultcolour = '#00ff00' ;
        $success++ ;
        }
        else
        {
        $dnsresult = 'Error';
        $dnsresultcolour = '#ff0000' ;
        $failure++ ;
        }

        $e->{success} = $success ;
        $e->{failure} = $failure ;

        #calculate percent availability
        $percent = &PERCENT ($success, $failure) ;

        #test for sla in compliance
        if ($percent > $sla )
        {
        $slaresultcolour = '#00ff00' ;
        }
        else {
        $slaresultcolour = '#ff0000' ;
        }

print OUTPUTFILE <<ENDOFTEXT2 ;
        <tr>
        <td>$nameserver</td>
        <td>$fqdn</td>
        <td bgcolor = "$dnsresultcolour">$dnsresult</td>
        <td>$reply</td>
        <td>$success</td>
        <td>$failure</td>
        <td bgcolor = "$slaresultcolour">$percent %</td>
        </tr> \n
ENDOFTEXT2


        my $zone_serial = &SERIAL ($rootdomain, $nameserver) ;

        #add each serial number to @serialnumber
        $serialnumber[$counter1] = $zone_serial ;

        if ($debug){print "Zone serial number is $zone_serial on $nameserver \n\n";}

        $counter1++ ;
#end foreach
}

print OUTPUTFILE "</table>\n   \n";


my $masterserial = $serialnumber[0] ;
if ($debug){print "Master is $masterserial \n" ;}

#force error in serial number
#$serialnumber[2] = '2005040401' ;

#test for zone serial number inconsistancy,
#bale out if any inconsistancies found (last)
foreach my $slaveserial (@serialnumber)
        {
        if ($debug){print "Slave is $slaveserial \n";}
        if ($masterserial ne $slaveserial)
                {
                $zonestatus = "Serial numbers are inconsistant";
                $serialresultcolour = '#ff0000';
                last ;
                }
        else
                {
                $zonestatus = "Serial numbers are consistant" ;
                $serialresultcolour = '#00ff00';
                }

        }

print OUTPUTFILE "<table border=\"1\">\n";
print OUTPUTFILE "<th colspan=\"3\">Zone serial numbers for $rootdomain</th>\n";

print OUTPUTFILE <<ENDOFTEXT3 ;
<tr>
<td>$rootdomain</td>
<td>Master is $masterserial</td>
<td bgcolor ="$serialresultcolour">$zonestatus</td>
</tr>
</table>

</div>
</div>

</body>
</html>

ENDOFTEXT3
close OUTPUTFILE ;

#write back xml file,
#use $configfile1 to write back to test file
XMLout($config,
        keeproot => 0,
        RootName => 'testdata',
        NoAttr   => '1',
        XMLDecl  => '1',
        keyattr  => [],
        OutputFile => $configfile) ;


#move temp file to correct file & set correct permissions
`mv $tempresultfile $resultfile` ;
`chmod a+r $resultfile` ;

}
#exit (0);
