#!/usr/bin/perl

use strict;
use warnings;
use English qw(-no_match_vars);
use Getopt::Std;

my $dig = 'dig';

my %opts;
getopts('s:z:d:p:h', \%opts);

$dig = $opts{d} if($opts{d});
$dig .= " -p $opts{p} " if($opts{p});

show_help() && exit 0 if($opts{h});

if($opts{s}) {
    print $opts{s}, ": ", clockskew($opts{s}), "\n";
}
elsif($opts{z}) {
    my @nameservers = `$dig +short $opts{z} IN NS`;
    foreach my $ns (@nameservers) {
        chomp $ns;
        print $ns, ": ", clockskew($ns), "\n";
    }
}

sub clockskew {
    my $ns = shift;
    my $command = $dig . ' -y clockskew.:427Y2BhT3VM= \@' . $ns . ' . IN SOA';

    my $tsig = `$command`;
    if($tsig =~ /\n.*?\s+\d+\s+ANY\s+TSIG\s+.*?\s+(\d+)\s+\d+\s+/) {
        return defined($1) ? $1 - time : undef;
    }
}

sub show_help {
    print "\n"
        . "$0 [OPTIONS]\n"
        . "\n"
        . "    -h            display usage message\n"
        . "    -s <server>   check this nameserver\n"
        . "    -z <zone>     check all nameservers for this zone\n"
        . "    -d <dig>      specify an alternate dig command\n"
        . "    -p <port>     specify an alternate nameserver port\n"
        . "\n";
}
