|
Packit |
e6c8bb |
#!/usr/local/bin/perl -w
|
|
Packit |
e6c8bb |
# $Id: check_soa 264 2005-04-06 09:16:15Z olaf $
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=head1 NAME
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
check_soa - Check a domain's nameservers
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=head1 SYNOPSIS
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
B<check_soa> I<domain>
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=head1 DESCRIPTION
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
B<check_soa> queries each of a domain's nameservers for the Start
|
|
Packit |
e6c8bb |
of Authority (SOA) record and prints the serial number. Errors
|
|
Packit |
e6c8bb |
are printed for nameservers that couldn't be reached or didn't
|
|
Packit |
e6c8bb |
answer authoritatively.
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=head1 AUTHOR
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
The original Bourne Shell and C versions were printed in
|
|
Packit |
e6c8bb |
I<DNS and BIND> by Paul Albitz & Cricket Liu.
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
This Perl version was written by Michael Fuhr <mike@fuhr.org>.
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=head1 SEE ALSO
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
L<perl(1)>, L<axfr>, L<check_zone>, L<mresolv>, L<mx>, L<perldig>, L<Net::DNS>
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
=cut
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
use File::Basename;
|
|
Packit |
e6c8bb |
use Net::DNS;
|
|
Packit |
e6c8bb |
use strict;
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Get the domain from the command line.
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
die "Usage: ", basename($0), " domain\n" unless @ARGV == 1;
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my ($domain) = @ARGV;
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Find all the nameservers for the domain.
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my $res = Net::DNS::Resolver->new();
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
$res->defnames(0);
|
|
Packit |
e6c8bb |
$res->retry(2);
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my $ns_req = $res->query($domain, "NS");
|
|
Packit |
e6c8bb |
die "No nameservers found for $domain: ", $res->errorstring, "\n"
|
|
Packit |
e6c8bb |
unless defined($ns_req) and ($ns_req->header->ancount > 0);
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
# Send out non-recursive queries
|
|
Packit |
e6c8bb |
$res->recurse(0);
|
|
Packit |
e6c8bb |
# Do not buffer standard out
|
|
Packit |
e6c8bb |
$| = 1;
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Check the SOA record on each nameserver.
|
|
Packit |
e6c8bb |
#------------------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
foreach my $nsrr (grep {$_->type eq "NS" } $ns_req->answer) {
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Set the resolver to query this nameserver.
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
my $ns = $nsrr->nsdname;
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
# In order to lookup the IP(s) of the nameserver, we need a Resolver
|
|
Packit |
e6c8bb |
# object that is set to our local, recursive nameserver. So we create
|
|
Packit |
e6c8bb |
# a new object just to do that.
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my $local_res = Net::DNS::Resolver->new();
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my $a_req = $local_res->query($ns, 'A');
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
unless ($a_req) {
|
|
Packit |
e6c8bb |
warn "Can not find address for $ns: ", $res->errorstring, "\n";
|
|
Packit |
e6c8bb |
next;
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
foreach my $ip (map { $_->address } grep { $_->type eq 'A' } $a_req->answer) {
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Ask this IP.
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
$res->nameservers($ip);
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
print "$ns ($ip): ";
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Get the SOA record.
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
my $soa_req = $res->send($domain, 'SOA', 'IN');
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
unless (defined($soa_req)) {
|
|
Packit |
e6c8bb |
warn $res->errorstring, "\n";
|
|
Packit |
e6c8bb |
next;
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Is this nameserver authoritative for the domain?
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
unless ($soa_req->header->aa) {
|
|
Packit |
e6c8bb |
warn "isn't authoritative for $domain\n";
|
|
Packit |
e6c8bb |
next;
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# We should have received exactly one answer.
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
unless ($soa_req->header->ancount == 1) {
|
|
Packit |
e6c8bb |
warn "expected 1 answer, got ", $soa_req->header->ancount, "\n";
|
|
Packit |
e6c8bb |
next;
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Did we receive an SOA record?
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
unless (($soa_req->answer)[0]->type eq "SOA") {
|
|
Packit |
e6c8bb |
warn "expected SOA, got ", ($soa_req->answer)[0]->type, "\n";
|
|
Packit |
e6c8bb |
next;
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
# Print the serial number.
|
|
Packit |
e6c8bb |
#----------------------------------------------------------------------
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
print "has serial number ", ($soa_req->answer)[0]->serial, "\n";
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
}
|
|
Packit |
e6c8bb |
|
|
Packit |
e6c8bb |
0;
|