--- a/vidns Thu May 22 16:17:47 2014 +0200
+++ b/vidns Thu May 22 17:18:07 2014 +0200
@@ -5,14 +5,12 @@
use File::Temp;
use Smart::Comments;
use Digest::SHA qw(sha512_hex);
+use Getopt::Long;
+use Pod::Usage;
sub parse {
- my $file = shift;
- my @lines = split /\n/, do {
- local $/ = undef;
- local @ARGV = $file;
- <>;
- };
+ my $data = join '', @_;
+ my @lines = split /\n/, $data;
my @zone;
my ($origin, $ttl, $last_label, $soa_seen);
@@ -20,14 +18,15 @@
foreach (@lines) {
s{;.*$}{};
given ($_) {
+ when (m{^\s*$}) { next }
when (m{^\s*\$ORIGIN\s+(\S+)}) { $origin = $1 }
- when (m{^\s*\$TTL\s+(\S+)}) { $ttl = $1 }
+ when (m{^\s*\$TTL\s+(\S+)}) { $ttl = $1 }
when (
m{^(?<label>\S+)?
- \s+(?<ttl>\S+(?=\s+))?
- \s+(?:(?:IN|ANY)\s+)?(?<rrtype>\S+(?=\s+))
+ \s+(?<ttl>\d[\dwdmhs]*(?=\s+))?
+ \s+(?:(?:IN|ANY)\s+)?(?<rrtype>[a-z]\S*(?=\s+))
\s+(?<data>.*)
- }x
+ }ix
)
{
my %rrset = (
@@ -163,27 +162,76 @@
my @keys2 = keys %zone2;
delete @zone1{@keys2};
delete @zone2{@keys1};
- ### %zone1
- ### %zone2
+ say 'update add ', join ' ' => @{$_}{qw/label ttl rrtype data/}
+ foreach values %zone2;
+ say 'update delete ', join ' ' => @{$_}{qw/label ttl rrtype data/}
+ foreach values %zone1;
exit;
}
sub main {
- my ($file) = @_;
- my @zone1 = grep {
+ my %o = (
+ key => undef,
+ server => undef,
+ );
+
+ GetOptions(
+ 'k|key=s' => \$o{key},
+ 's|server=s' => \$o{server},
+ )
+ && @ARGV == 1
+ or pod2usage();
- # get { id => $id, rrset => \%rrset }
- not $_->{rrset}{rrtype} ~~ [qw(RRSIG NSEC3 NSEC3PARAM NSEC DNSKEY TSIG)]
+ my @dig = (
+ dig => 'AXFR',
+ defined $o{key} ? (-k => $o{key}) : (),
+ defined $o{server} ? ("\@$o{server}") : (),
+ $ARGV[0]
+ );
- #$_->{rrset}{rrtype} ~~ [qw(SOA NS MX)]
- } parse($file);
+ my @zone1 = grep {
+ not $_->{rrset}{rrtype} ~~
+ [qw(RRSIG NSEC3 NSEC3PARAM NSEC DNSKEY TSIG)]
+ } parse(`@dig`);
+
my $tmp = File::Temp->new();
$tmp->print(nice @zone1);
- $tmp->close();
+ $tmp->flush();
system $ENV{EDITOR} // 'vi' => $tmp->filename;
- my @zone2 = parse($tmp->filename);
+ $tmp->seek(0, 0);
+ my @zone2 = parse(<$tmp>);
delta(\@zone1, \@zone2);
exit;
}
exit main(@ARGV) if not caller;
+
+__END__
+
+=head1 NAME
+
+ vidns -- editor for dynamically maintained zones
+
+=head1 SYNOPSIS
+
+ vidns [-k key] [-s server] <zone>
+
+=head1 DESCRIPTION
+
+=head1 PREREQUISITES
+
+We need some tools to be installed:
+
+=over
+
+=item B<dig>
+
+The domain information grabber is used for the zone transfer currently.
+
+=item B<nsupdate>
+
+The nsupdate tool is used to send the updates back to the server.
+
+=back
+
+=cut