#!/usr/bin/perl

open (STDERR, ">&STDOUT");
select ((select(STDOUT), $| = 1)[0]); # Synchronize STDOUT
select ((select(STDERR), $| = 1)[0]); # with STDERR

($dns_lib = $0) =~ s:(^|/)[^/]*$::;
($script=$0) =~ s:^.*/([^/]*)$:$1:;	# Get the simple name of this script.

push (@INC, $dns_lib);

require 5.0;
require 'dns_lib.perl';

use Getopt::Long;
$Getopt::Long::autoabbrev=1;    # Allow keyword abbreviations (to uniqueness).
$Getopt::Long::getopt_compat=1; # Allow both "--foo=bar" and "+foo=bar" style.
#$Getopt::Long::option_start='(--|-|\+)';       # [Use the defaults]
#$Getopt::Long::order=$Getopt::Long::REQUIRE_ORDER; # Options can't intermingle
$Getopt::Long::order=$Getopt::Long::PERMUTE;    # or options may intermingle.
$Getopt::Long::ignorecase=1;    # Don't consider case in options.
$Getopt::Long::debug=0;         ### Debug ###

$opt_help = ($#ARGV < 0);

&GetOptions ('help') || die "\nTry: $script --help for more information.\n\n";

if ($opt_help) { 
 
    print <<"EndOfHelp";
Usage: $script [OPTION] zone
 
  --help   This page.

  zone     The DNS zone to verify
 
EndOfHelp
    
    exit;

} # End if - help

$zone = $ARGV[0];

if (! $zone) {

    die "\nError.  Try: $script --help for more information.\n\n";

} else {

    $zone = &zone_or_subnet ($zone);
    $subnet = 1 if $zone =~ m/\.in-addr\.arpa\.?$/;
    
    if ($subnet) {

	$fwd = 'PTR';
	$rev = 'A';

    } else {

	$fwd = 'A';
	$rev = 'PTR';

    }

}

@file = &read_file ($zone, '.primary');
print "Checking $fwd Records in $zone for matching $rev records:\n";
print "\n";

foreach (@file) {

    chomp;
    if (m/^(\S+)\s+IN\s+$fwd\s+(\S+)$/) {

	$r_host = $1;
	$r_val = $2;

	if ($r_val =~ m/^(\d+\.\d+\.\d+)\.(\d+)$/) {

	    $net = $1;
	    $n_host = $2;

	} elsif ($r_val =~ m/^([^\.]+)\.(\S+)$/) {

	    $net = $2;
	    $n_host = $1;

	}

	$lookup{$net} = [] if ! defined ($lookup{$net});

	if ($r_host eq '@') {

	    push (@{$lookup{$net}}, "$n_host|$zone");

	} else {

	    push (@{$lookup{$net}}, "$n_host|$r_host.$zone");

	}

    }

}

foreach $z (keys (%lookup)) {

    if ((($x = &verify_zone ($z)) eq 'PRIMARY') || ($x eq 'SEC_W_GLUE')){

	$primary = 1;
	@tmp = &read_file ($z, '.primary');

    } else {
	
	$primary = 0;

    }

    foreach $entry (@{$lookup{$z}}) {

	($host,$val) = split ('\|', $entry);

	$val = &reverse_ip ($val) if $subnet;
	$entry = "$val <--> $z.$host" unless $subnet;
	$entry = "$val <--> $host.$z" if $subnet;

	if ($primary) {

	    $record = &build_record ($host, $rev, '', '');
	    @find = &find_record ($record, @tmp);

	    if ($#find < 0) {

		print "No matching $rev record: $entry\n";
	    
	    } else {

		print "Multiple reverse records found for: $host\n" if ($#find > 0);

		foreach $f (@find) {

		    chomp ($f);
		    print "$fwd and $rev do not match: $entry\n$f\n\n" if $f !~ m/^$host\s+IN\s+$rev\s+$val$/;

		}

	    }

	} else {

	    print "Unknown (not primary for $z): $entry\n";

	}

    }

}

exit;

