--- a/update-serial.pl Fri Dec 24 00:15:54 2010 +0100
+++ b/update-serial.pl Tue Dec 28 15:23:35 2010 +0100
@@ -7,16 +7,20 @@
use File::Basename;
use Pod::Usage;
use Getopt::Long;
+use Smart::Comments;
+use File::Temp;
+use POSIX qw(strftime);
sub uniq(@);
sub read_conf(@);
-sub add_argv;
-sub changed_zone;
-sub sign_end;
+sub zones(@);
+sub changed_zones();
+sub update_index($);
+sub sign_expired($);
+
sub sign_zone;
sub update_serial;
sub mk_zone_conf;
-sub update_index;
sub file_entry;
sub server_reload;
sub to_begin_ro;
@@ -27,12 +31,14 @@
sub end_ro;
my %config;
+my %opt;
MAIN: {
GetOptions(
- "h|help" => sub { pod2usage(-exit 0, -verbose => 1) },
- "m|man" => sub {
+ "sign-alert-time=i" => \$opt{sign_alert_time},
+ "h|help" => sub { pod2usage(-exit 0, -verbose => 1) },
+ "m|man" => sub {
pod2usage(
-exit 0,
-verbose => 2,
@@ -41,38 +47,42 @@
},
) or pod2usage;
- %config = read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+ # merge the config and the defined options from commandline
+ %config = (
+ read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf"),
+ map { $_ => $opt{$_} } grep { defined $opt{$_} } keys %opt
+ );
- our @new_serial; # liste fuer neuen serial
+ our @new_serial; # DO NOT USE
our @begin_ro_list; # liste mit zonen deren key-rollover beginnt
our @end_ro_list; # liste mit zonen deren key-rollover fertig ist
our $bind_dir = $config{bind_dir};
our $conf_dir = $config{zone_conf_dir};
- our $sign_alert_time = $config{sign_alert_time};
- our $indexzone = $config{indexzone};
our $key_counter_end = $config{key_counter_end};
our $ablauf_zeit = $config{abl_zeit};
- add_argv;
+ my @candidates = @ARGV ? zones(@ARGV) : changed_zones;
+ push @candidates, update_index($config{indexzone});
+ push @candidates, sign_expired($config{sign_alert_time});
+ ### @candidates
+ exit;
- changed_zone;
- sign_end;
-
- to_begin_ro; # prueft nach beginnenden rollover-verfahren
- to_end_ro; # prueft nach endenden rollover-verfahren
+ to_begin_ro; # prueft nach beginnenden rollover-verfahren
+ to_end_ro; # prueft nach endenden rollover-verfahren
if (@begin_ro_list) {
- begin_ro; # eine rollover-beginn-sequenz
+ begin_ro; # eine rollover-beginn-sequenz
}
if (@end_ro_list) {
- end_ro; # eine rollover-end-squenz
+ end_ro; # eine rollover-end-squenz
}
if (@new_serial) {
- update_index; # index zone aktuallisieren
- update_serial; # serial aktuallisieren
- sign_zone; # zone signieren
+
+ #--update_index; # index zone aktuallisieren
+ update_serial; # serial aktuallisieren
+ sign_zone; # zone signieren
}
file_entry; # bearbeitet die file-eintraege der konfigurations-datei
@@ -82,6 +92,7 @@
}
sub uniq(@) {
+
# remove duplicate entries
my %all;
@all{@_} = ();
@@ -108,74 +119,72 @@
return %config;
}
-sub add_argv {
- # checked whether the zones in argv are managed zones and
- #inserted them into the list new_serial
- our @new_serial;
- my $zone;
+sub zones(@) {
+
+ # check whether the zones in argv are managed zones and
+ # insert them into the list new_serial
+
+ my @r;
- for (@ARGV) {
- chomp($zone = `idn --quiet "$_"`);
- if (-e "$config{master_dir}/$zone/$zone") {
- push @new_serial, $zone;
- }
+ foreach (@_) {
+ chomp(my $zone = `idn --quiet "$_"`);
+ die "$zone is not managed\n"
+ if not -e "$config{master_dir}/$zone/$zone";
+ push @r, $zone;
}
+
+ return @r;
}
-sub changed_zone {
- our @new_serial;
+sub changed_zones() {
+
+ # find candidates in our master dir
+ my @r;
while (glob "$config{master_dir}/*") {
my $zone = basename($_);
- if (-e "$config{master_dir}/$zone/.stamp") {
- my $stamptime = (-M "$config{master_dir}/$zone/.stamp");
- my $filetime = (-M "$config{master_dir}/$zone/$zone");
- if ($stamptime > $filetime) {
- push @new_serial, $zone;
- print " * $zone: zonedatei wurde geaendert\n";
- }
+ if (not -e "$_/.stamp") {
+ say " * $zone: no .stamp file found"; # NOCH IN NEW_SERIAL PUSHEN
+ push @r, $zone;
+ next;
}
- else {
- print " * $zone: keine .stamp-datei gefunden\n"
- ; # NOCH IN NEW_SERIAL PUSHEN
- push @new_serial, $zone;
- }
+
+ my $stamp_age = -M _;
+ my $file_age = -M "$_/$zone";
+
+ next if $stamp_age <= $file_age; # should be only <
+
+ push @r, $zone;
+ say " * $zone: zone file modified";
}
-
+ return @r;
}
-sub sign_end {
- our $sign_alert_time; # the time between the end and the new signing
- # (see external configuration)
- our @new_serial;
+sub sign_expired($) {
+ my $sign_alert_time = shift; # the time between the end and the new signing
+ # (see external configuration)
+ my @r;
# erzeugt $time (die zeit ab der neu signiert werden soll)
- my $unixtime = time + (3600 * $sign_alert_time);
- my $time = `date -d \@$unixtime +%Y%m%d%H`;
+ # ... warum eigentlich nur bis zu den Stunden und nicht auch Minuten und Sekunden?
+ my $time = strftime("%Y%m%d%H" => localtime time + 3600 * $sign_alert_time);
## vergleicht fuer alle zonen im ordner $config{master_dir} mit einer
## <zone>.signed-datei den zeitpunkt in $time mit dem ablaufdatum der
## signatur, welcher aus der datei <zone>.signed ausgelesen wird.
- while (glob "$config{master_dir}/*") {
- s#($config{master_dir}/)(.*)#$2#;
- my $zone = $_;
+ ZONE: while (my $dir = glob "$config{master_dir}/*") {
+ my $zone = basename $dir;
- if (-e "$config{master_dir}/$zone/$zone.signed") {
- open(ZONE, "$config{master_dir}/$zone/$zone.signed");
- my @zone_sig_content = <ZONE>;
- close(ZONE);
+ next if not -e "$dir/$zone.signed";
- for (@zone_sig_content) {
- if (m#SOA.*[0-9]{14}#) {
- s#.*([0-9]{10})([0-9]{4}).*#$1#;
- if ($_ < $time) {
- push @new_serial, $zone;
- }
- }
- }
- }
+ open(my $fh, "$dir/$zone.signed") or die "Can't open $dir/$zone.signed: $!\n";
+ push @r, $zone if
+ /RRSIG\s+SOA[\d ]+(\d{10})\d{4}\s+\(/ ~~ [<$fh>]
+ and $1 < $time;
}
+
+ return @r;
}
sub sign_zone {
@@ -279,47 +288,35 @@
print "** zonekonfiguration erzeugt\n";
}
-sub update_index {
+sub update_index($) {
+ my $indexzone = shift;
- # aktualisiert die indexzone;
- our @new_serial;
- our $indexzone;
- my @iz_content_old;
- my @iz_content_new;
+ my @iz;
- open(INDEXZONE, "$config{master_dir}/$indexzone/$indexzone")
- or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
- @iz_content_old = <INDEXZONE>;
- close(INDEXZONE);
-
- for (@iz_content_old) {
- unless (m#ZONE::#) {
- push @iz_content_new, $_;
- }
+ {
+ open(my $fh, "$config{master_dir}/$indexzone/$indexzone")
+ or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
+ chomp(@iz = grep !/ZONE::/ => <$fh>);
}
for my $dir (glob "$config{master_dir}/*") {
- my $zone = basename($dir);
- my $info_end = "::sec-off";
-
- if (-e "$dir/.keycounter") {
- $info_end = "::sec-on";
- }
-
- my $iz_line = "\t\tIN TXT\t\t\"ZONE::$zone$info_end\"\n";
-
- push @iz_content_new, $iz_line;
+ my $zone = basename($dir);
+ my $info = -e ("$dir/.keycounter") ? "sec-on" : "sec-off";
+ push @iz, join "::", "\t\tIN TXT\t\t\"ZONE", $zone, $info;
}
- open(INDEXZONE, ">$config{master_dir}/$indexzone/$indexzone")
- or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
- print INDEXZONE @iz_content_new;
- close(INDEXZONE);
+ {
+ my $fh = File::Temp->new(DIR => "$config{master_dir}/$indexzone")
+ or die "Can't create tmpdir: $!\n";
+ print $fh join "\n" => @iz, "";
+ rename($fh->filename => "$config{master_dir}/$indexzone/$indexzone")
+ or die "Can't rename "
+ . $fh->filename
+ . " to $config{master_dir}/$indexzone/$indexzone: $!\n";
+ }
- # fuegt die index-zone in die liste damit der serial erhoet wird
- push @new_serial, $indexzone;
-
- print "** index-zone aktualisiert \n";
+ say "** index-zone aktualisiert";
+ return $indexzone;
}
sub file_entry {
@@ -589,7 +586,7 @@
=head1 SYNOPSIS
- update-serial [zone...]
+ update-serial [options] [zone...]
=head1 DESCRIPTION
@@ -598,6 +595,13 @@
=head1 OPTIONS
+=over
+
+=item B<--sign-alert-time> I<days>
+
+
+=back
+
The common options B<-h>|B<--help>|B<-m>|B<--man> are supported.
=head1 AUTHOR