#!/usr/bin/perl -w

use Net::DNS;
use Algorithm::Diff qw(traverse_sequences);
use Data::Dumper;

my $verbose = 1;
my $debug = 0;

my $res;

sub check {
	my $arg = shift || die "no arg?";

	print "## $arg\n" if ($debug);

	my ($domain,$type,$what,$server) = split(/\s+/,$arg) or die "can't split $arg into domain, type, what, server";

	$res->{$server} ||= Net::DNS::Resolver->new(
		nameservers => [ $server ],
		recurse	=> 0,
		debug	=> $debug,
	);

	my $query = $res->{$server}->query($domain, $type) || die "can't find $type $domain on $server\n";

	my @out;

	if ($query) {
		foreach my $ans ($query->answer) {
			push @out, $ans->$what;
		}
	} else {
		print "query $type $domain failed: ", $res->errorstring, "\n";
	}

	print "# out: ",join(",",(sort @out)),"\n" if ($debug);

	return @out;
}

my $domain = shift @ARGV || die "usage: $0 my.domain.com [primary.dns.com]\n";
my $master = shift @ARGV || '127.0.0.1';

my ($serial) = check("$domain SOA serial $master");
my @ns = check("$domain NS nsdname $master");
@ns = sort @ns;
foreach $ns ( @ns ) {
	print "# testing $ns $domain\n" if ($verbose);

	my ($s) = check("$domain SOA serial $ns");
	if ($s != $serial) {
		print STDERR "ERROR\t$ns: serial $s != $serial\n";
	} else {
		print "ok\t$ns: serial $s\n" if ($verbose);
	}

	my @ns_this = check("$domain NS nsdname $ns");
	@ns_this = sort @ns_this;

	print "### ns: ",join(",",@ns),"\n" if ($debug);
	print "### ns_this: ",join(",",@ns_this),"\n" if ($debug);

	traverse_sequences(\@ns, \@ns_this, {
		MATCH => sub { print "ok\t$ns: $domain NS ",$ns[$_[0]],"\n" if ($verbose); },
		DISCARD_A => sub { print "ERROR\t$ns: $domain NS missing: ",$ns[$_[0]],"\n"; },
		DISCARD_B => sub { print "ERROR\t$ns: $domain NS added: ", $ns_this[$_[1]],"\n"; },
	});

}

