diff -r 6d79c81a2931 -r 50fbb0fb1120 bin/dns-vi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/dns-vi Thu Jun 05 08:50:19 2014 +0200 @@ -0,0 +1,173 @@ +#! /usr/bin/perl +#line 3 +use 5.010; +use strict; +use warnings; +use if $ENV{DEBUG} // '' eq 'dns-vi' => 'Smart::Comments'; +use Getopt::Long; +use Pod::Usage; +use File::Copy; + +#use blib; +use DNS::Vi; + +sub slurp { + local $/ = undef; + local @ARGV = @_; + <>; +} + +sub main { + my %o = ( + local => undef, + key => undef, + server => undef, + debug => undef, + editor => $ENV{EDITOR} // 'vi', + skip => [qw/NS RRSIG NSEC3 NSEC3PARAM NSEC DNSKEY TSIG/], + ); + + GetOptions( + 'k|key=s' => \$o{key}, + 's|server=s' => \$o{server}, + 'd|debug!' => \$o{debug}, + 'l|local!' => \$o{local}, + 'editor=s' => \$o{editor}, + ) + && @ARGV >= 1 + or pod2usage(); + + my $zone = shift @ARGV; + + $o{server} = + $o{local} ? 'localhost' : (split ' ', `dig +short soa $zone`)[0] + if not defined $o{server}; + + my @dig = ( + dig => 'AXFR', + defined $o{key} ? (-k => $o{key}) : (), + defined $o{server} ? ("\@$o{server}") : (), + $zone + ); + + my @zone1 = parse($_ = `@dig`, { -skip => $o{skip} } ) + or die "Empty zone\n"; + my $fh2; + my @zone2 = do { + if (my $file = shift @ARGV) { + parse(slurp($file), { -skip => $o{skip} }); + } + else { + edit(@zone1, { -skip => $o{skip}, -editor => $o{editor}, -backup => \$fh2 }); + } + }; + ### @zone2 + + my ($add, $del) = delta(\@zone1, \@zone2); + if ((@$add + @$del) == 0) { + say 'nothing changed'; + return 0; + } + + say 'The following changes need your confirmation.'; + say join "\n", show($add, $del); + print 'confirm (yes|NO): '; + return 1 if !~ /^y/i; + + update(\@zone1, $add, $del, { + -server => $o{server}, + -local => $o{local}, + -debug => $o{debug}, + -key => $o{key}}) + or do { + copy($fh2->filename, ",dns-vi-$$") + and say "Saved as ',dns-vi-$$'" + if $fh2; + }; + + return 0; +} + +exit main(@ARGV) if not caller; + +__END__ + +=head1 NAME + + dns-vi -- editor for dynamically maintained zones + +=head1 SYNOPSIS + + dns-vi [[-l] | [[-k key] [-s server]]] [-d] [] + +=head1 DESCRIPTION + +This tools supports you in maintaining a dynamic zone. Normally you'll +use it with the name of zone. For batch mode you may use it with an +additional parameter, die edited zone file. + +=head2 OPTIONS + +=over + +=item B<-l>|B<--local> + +Local mode, when running on the server where the updates need to go to. +But still zone transfers need to be enabled! (default: off) + +=item B<-s>|B<--server> B + +The name of the server to contact for the AXFR and the update. +(default: main nameserver from the SOA record) + +=item B<-k>|B<--key> B + +The name of the key file we need for TSIG (the AXFR will use it, +as well as the update). + +To create such a key you may use + + dnssec-keygen -a HMAC-MD5 -b 512 -n USER heiko + +Then copy the resulting files somewhere (you'll need both files). +On the server side include the key into to configuration: + + key "" { + algorithm HMAC-MD5; + secret "" + }; + +Per zone you should use + + zone "" { + ... + update-policy { + grant local-ddns zonesub any; // support for -l + grant zonesub; // support for -k + }; + ... + }; + +=item B<-d> + +This option enables debugging of C. (default: off) + +=back + +=head1 PREREQUISITES + +We need some tools to be installed: + +=over + +=item B + +The domain information grabber is used for the zone transfer currently. + +=item B + +The nsupdate tool is used to send the updates back to the server. + +=back + +=cut