vidns
changeset 5 70ecc1882968
parent 4 f77aa03e2d39
--- 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