Blame demo/axfr

Packit Service ab31fe
#!/usr/bin/perl -w
Packit Service f6e53a
# $Id: axfr 264 2005-04-06 09:16:15Z olaf $
Packit Service f6e53a
Packit Service f6e53a
use strict;
Packit Service f6e53a
use vars qw($opt_f $opt_q $opt_s $opt_D);
Packit Service f6e53a
use File::Basename;
Packit Service f6e53a
use Getopt::Std;
Packit Service f6e53a
use Net::DNS;
Packit Service f6e53a
use Storable;
Packit Service f6e53a
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
# Read any command-line options and check syntax.
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
Packit Service f6e53a
getopts("fqsD:");
Packit Service f6e53a
Packit Service f6e53a
die "Usage: ", basename($0), " [ -fqs ] [ -D directory ] [ \@nameserver ] zone\n"
Packit Service f6e53a
	unless (@ARGV >= 1) && (@ARGV <= 2);
Packit Service f6e53a
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
# Get the nameserver (if specified) and set up the zone transfer directory
Packit Service f6e53a
# hierarchy.
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
Packit Service f6e53a
my $nameserver = ($ARGV[0] =~ /^@/) ? shift @ARGV : "";
Packit Service f6e53a
$nameserver =~ s/^@//;
Packit Service f6e53a
Packit Service f6e53a
my $zone = shift @ARGV;
Packit Service f6e53a
my $basedir = defined $opt_D ? $opt_D : $ENV{"HOME"} . "/.dns-zones";
Packit Service f6e53a
my $zonedir = join("/", reverse(split(/\./, $zone)));
Packit Service f6e53a
my $zonefile = $basedir . "/" . $zonedir . "/axfr";
Packit Service f6e53a
Packit Service f6e53a
# Don't worry about the 0777 permissions here - the current umask setting
Packit Service f6e53a
# will be applied.
Packit Service f6e53a
unless (-d $basedir) {
Packit Service f6e53a
	mkdir($basedir, 0777) or die "can't mkdir $basedir: $!\n";
Packit Service f6e53a
}
Packit Service f6e53a
Packit Service f6e53a
my $dir = $basedir;
Packit Service f6e53a
my $subdir;
Packit Service f6e53a
foreach $subdir (split(m#/#, $zonedir)) {
Packit Service f6e53a
	$dir .= "/" . $subdir;
Packit Service f6e53a
	unless (-d $dir) {
Packit Service f6e53a
		mkdir($dir, 0777) or die "can't mkdir $dir: $!\n";
Packit Service f6e53a
	}
Packit Service f6e53a
}
Packit Service f6e53a
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
# Get the zone.
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
Packit Service f6e53a
my $res = Net::DNS::Resolver->new;
Packit Service f6e53a
$res->nameservers($nameserver) if $nameserver;
Packit Service f6e53a
Packit Service f6e53a
my (@zone, $zoneref);
Packit Service f6e53a
Packit Service f6e53a
if (-e $zonefile && !defined $opt_f) {
Packit Service f6e53a
	$zoneref = retrieve($zonefile) || die "couldn't retrieve zone from $zonefile: $!\n";
Packit Service f6e53a
Packit Service f6e53a
	#----------------------------------------------------------------------
Packit Service f6e53a
	# Check the SOA serial number if desired.
Packit Service f6e53a
	#----------------------------------------------------------------------
Packit Service f6e53a
Packit Service f6e53a
	if (defined $opt_s) {
Packit Service f6e53a
		my($serial_file, $serial_zone);
Packit Service f6e53a
Packit Service f6e53a
		my $rr;
Packit Service f6e53a
		foreach $rr (@$zoneref) {
Packit Service f6e53a
			if ($rr->type eq "SOA") {
Packit Service f6e53a
				$serial_file = $rr->serial;
Packit Service f6e53a
				last;
Packit Service f6e53a
			}
Packit Service f6e53a
		}
Packit Service f6e53a
		die "no SOA in $zonefile\n" unless defined $serial_file;
Packit Service f6e53a
Packit Service f6e53a
		my $soa = $res->query($zone, "SOA");
Packit Service f6e53a
		die "couldn't get SOA for $zone: ", $res->errorstring, "\n"
Packit Service f6e53a
			unless defined $soa;
Packit Service f6e53a
Packit Service f6e53a
		foreach $rr ($soa->answer) {
Packit Service f6e53a
			if ($rr->type eq "SOA") {
Packit Service f6e53a
				$serial_zone = $rr->serial;
Packit Service f6e53a
				last;
Packit Service f6e53a
			}
Packit Service f6e53a
		}
Packit Service f6e53a
Packit Service f6e53a
		if ($serial_zone != $serial_file) {
Packit Service f6e53a
			$opt_f = 1;
Packit Service f6e53a
		}
Packit Service f6e53a
	}
Packit Service f6e53a
} else {
Packit Service f6e53a
	$opt_f = 1;
Packit Service f6e53a
}
Packit Service f6e53a
Packit Service f6e53a
if (defined $opt_f) {
Packit Service f6e53a
	@zone = $res->axfr($zone);
Packit Service f6e53a
	die "couldn't transfer zone: ", $res->errorstring, "\n" unless @zone;
Packit Service f6e53a
	store \@zone, $zonefile or die "couldn't store zone to $zonefile: $!\n";
Packit Service f6e53a
	$zoneref = \@zone;
Packit Service f6e53a
}
Packit Service f6e53a
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
# Print the records in the zone.
Packit Service f6e53a
#------------------------------------------------------------------------------
Packit Service f6e53a
Packit Service f6e53a
unless ($opt_q) {
Packit Service f6e53a
	$_->print for @$zoneref
Packit Service f6e53a
}
Packit Service f6e53a
Packit Service f6e53a
__END__
Packit Service f6e53a
Packit Service f6e53a
=head1 NAME
Packit Service f6e53a
Packit Service f6e53a
axfr - Perform a DNS zone transfer
Packit Service f6e53a
Packit Service f6e53a
=head1 SYNOPSIS
Packit Service f6e53a
Packit Service f6e53a
B<axfr> S<[ B<-fqs> ]> S<[ B<-D> I<directory> ]> S<[ B<@>I<nameserver> ]>
Packit Service f6e53a
I<zone>
Packit Service f6e53a
Packit Service f6e53a
=head1 DESCRIPTION
Packit Service f6e53a
Packit Service f6e53a
B<axfr> performs a DNS zone transfer, prints each record to the standard
Packit Service f6e53a
output, and stores the zone to a file.  If the zone has already been
Packit Service f6e53a
stored in a file, B<axfr> will read the file instead of performing a
Packit Service f6e53a
zone transfer.
Packit Service f6e53a
Packit Service f6e53a
Zones will be stored in a directory hierarchy.  For example, the
Packit Service f6e53a
zone transfer for foo.bar.com will be stored in the file
Packit Service f6e53a
$HOME/.dns-zones/com/bar/foo/axfr.  The directory can be changed
Packit Service f6e53a
with the B<-D> option.
Packit Service f6e53a
Packit Service f6e53a
This programs requires that the Storable module be installed.
Packit Service f6e53a
Packit Service f6e53a
=head1 OPTIONS
Packit Service f6e53a
Packit Service f6e53a
=over 4
Packit Service f6e53a
Packit Service f6e53a
=item B<-f>
Packit Service f6e53a
Packit Service f6e53a
Force a zone transfer, even if the zone has already been stored
Packit Service f6e53a
in a file.
Packit Service f6e53a
Packit Service f6e53a
=item B<-q>
Packit Service f6e53a
Packit Service f6e53a
Be quiet -- don't print the records from the zone.
Packit Service f6e53a
Packit Service f6e53a
=item B<-s>
Packit Service f6e53a
Packit Service f6e53a
Perform a zone transfer if the SOA serial number on the nameserver
Packit Service f6e53a
is different than the serial number in the zone file.
Packit Service f6e53a
Packit Service f6e53a
=item B<-D> I<directory>
Packit Service f6e53a
Packit Service f6e53a
Store zone files under I<directory> instead of the default directory
Packit Service f6e53a
(see L<"FILES">).
Packit Service f6e53a
Packit Service f6e53a
=item B<@>I<nameserver>
Packit Service f6e53a
Packit Service f6e53a
Query I<nameserver> instead of the default nameserver.
Packit Service f6e53a
Packit Service f6e53a
=back
Packit Service f6e53a
Packit Service f6e53a
=head1 FILES
Packit Service f6e53a
Packit Service f6e53a
=over 4
Packit Service f6e53a
Packit Service f6e53a
=item B<$HOME/.dns-zones>
Packit Service f6e53a
Packit Service f6e53a
Default directory for storing zone files.
Packit Service f6e53a
Packit Service f6e53a
=back
Packit Service f6e53a
Packit Service f6e53a
=head1 AUTHOR
Packit Service f6e53a
Packit Service f6e53a
Michael Fuhr <mike@fuhr.org>
Packit Service f6e53a
Packit Service f6e53a
=head1 SEE ALSO
Packit Service f6e53a
Packit Service f6e53a
L<perl(1)>, L<check_soa>, L<check_zone>, L<mresolv>, L<mx>, L<perldig>,
Packit Service f6e53a
L<Net::DNS>, L<Storable>
Packit Service f6e53a
Packit Service f6e53a
=cut