[merged]
authorHeiko Schlittermann <hs@schlittermann.de>
Tue, 21 Dec 2010 15:59:05 +0100
changeset 46 de6761ce0d5b
parent 45 5dc44dc86f61 (current diff)
parent 43 7e472c559b36 (diff)
child 47 31f29baca131
[merged]
dnssec-keytool
dnssec-keytool.pl
update-serial
update-serial.pl
zone-ls
zone-mk
zone-rm
--- a/.hgignore	Tue Dec 21 15:47:40 2010 +0100
+++ b/.hgignore	Tue Dec 21 15:59:05 2010 +0100
@@ -1,2 +1,6 @@
-creatksk.old
-creatkey.old
+.hgignore
+dnssec-keytool
+update-serial
+zone-ls
+zone-mk
+zone-rm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.perltidyrc	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,2 @@
+--paren-tightness=2
+--square-bracket-tightness=2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,19 @@
+ALL = zone-ls zone-mk zone-rm \
+      update-serial \
+      dnssec-keytool
+
+CLEANFILES = $(ALL)
+
+.PHONY:	all clean distclean install
+
+all:	$(ALL)
+
+clean:	
+distclean:
+	rm -f $(CLEANFILES)
+
+
+%:	%.pl
+	@perl -c $<
+	@cp -f $< $@
+	@chmod a+x-w $@
--- a/dnssec-keytool	Tue Dec 21 15:47:40 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,363 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use FindBin;
-
-sub del_double {
-    my %all;
-    grep { $all{$_} = 0 } @_;
-    return ( keys %all );
-}
-
-sub read_conf {
-    # liest die Konfiguration ein
-    my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
-    our %config;
-
-    for ( grep {-f} @configs ) {
-        open( CONFIG, $_ ) or die "Can't open $_: $!\n";
-    }
-    unless ( seek( CONFIG, 0, 0 ) ) {
-        die "Can't open config (searched: @configs)\n";
-    }
-    while (<CONFIG>) {
-        chomp;
-        s/#.*//;
-        s/\t//g;
-        s/\s//g;
-
-        next unless length;
-        my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
-        $config{$cname} = $ccont;
-    }
-    close(CONFIG);
-}
-
-sub read_argv {
-    # wertet argv aus oder gibt die hilfe aus
-    my $arg = shift @ARGV;
-    my $zone;
-    our $do;
-    our @zones;
-    our $master_dir;
-
-    if ( ! defined $arg ) {
-        print " usage: dnssec-keytool <option> zone\n";
-        print "   -z  erstellt einen neuen ZSK\n";
-        print "   -k  erstellt je einen neuen ZSK und KSK\n";
-        print "   -rm loescht das Schluesselmaterial einer Zone\n";
-        print "   -c  erstellt bei existierenden ksk konfigurationsdateien\n";
-        print "       fuer die dnstools, sowie einen neuen zsk\n";
-        print "\n";
-
-        exit;
-    }
-    elsif ($arg eq "-k")  {$do = "ksk";}
-    elsif ($arg eq "-rm") {$do = "rm";}
-    elsif ($arg eq "-c")  {$do = "ck";}
-    elsif ($arg eq "-z") {$do = "zsk";}
-    else {
-        print "keine gueltige Option.\n";
-        exit;
-    }
-
-    # prueft die zonen in argv ob es verwaltete zonen sind
-    for (@ARGV) {
-        chomp( $zone = `idn --quiet "$_"` );
-        if ( -e "$master_dir/$zone/$zone" ) {
-            push @zones, $zone;
-        }
-    }
-}
-
-sub rm_keys {
-    # loescht alle schluessel wenn -rm uebergeben wurde
-    our @zones;
-    our $master_dir;
-    my $zone;
-    my @new_zone_content;
-    my @old_zone_content;
-
-    for (@zones) {
-        $zone = $_;
-
-        my $zpf = "$master_dir/$zone";
-        my $ep = 0;
-
-        if ( -e "$zpf/$zone.signed" )  { 
-            unlink "$zpf/$zone.signed"  and $ep = 1 }
-        if ( -e "$zpf/.keycounter" )   {
-            unlink "$zpf/.keycounter"   and $ep = 1 }
-        if ( -e "$zpf/.index.ksk" )    {
-            unlink "$zpf/.index.ksk"    and $ep = 1 }
-        if ( -e "$zpf/.index.zsk" )    {
-            unlink "$zpf/.index.zsk"    and $ep = 1 }
-        if ( -e "$zpf/dsset-$zone." )  { 
-            unlink "$zpf/dsset-$zone."  and $ep = 1 }
-        if ( -e "$zpf/keyset-$zone." ) { 
-            unlink "$zpf/keyset-$zone." and $ep = 1 }
-
-        for (glob("$zpf/K$zone*")) { 
-            chomp($_);
-            unlink ("$_");
-        }
-
-        if ($ep == 1) {
-            print " * $zone: schluesselmaterial entfernt\n";
-        }
-
-        open( ZONE, "$zpf/$zone" )
-            or die "$zpf/$zone: $!\n";
-        @old_zone_content = <ZONE>;
-        close(ZONE);
-        
-        for (@old_zone_content) {
-            unless (m#\$INCLUDE.*\"K$zone.*\.key\"#) {
-                push @new_zone_content, $_;
-            }
-        }
-
-        open( ZONE, ">$zpf/$zone" ) or die "$zpf/$zone: $!\n";
-        print ZONE @new_zone_content;
-        close(ZONE);
-    }
-}
-
-sub creat_ksk {
-    our @zones;
-    our $master_dir;
-    my @index;
-    my $zone;
-    my $keyname;
-    my $zpf;
-
-    for (@zones) {
-        $zone = $_;
-        $zpf = "$master_dir/$zone";
-
-        chdir "$zpf" or die "$zpf: $!\n";
-        $keyname = `dnssec-keygen -a RSASHA1 -b 2048 -f KSK -n ZONE $zone`;
-
-        unless ( -f ".index.ksk" ) { @index = ();}
-        else {
-            open( INDEX, ".index.ksk" ) or die "$zpf/.index.ksk: $!\n";
-            @index = <INDEX>;
-            close(INDEX);
-        }
-
-        push @index, $keyname;
-        if ( @index > 2 ) { shift(@index);}
-
-        open( INDEX, ">.index.ksk" ) or die "$zpf/.index.ksk: $!\n";
-        print INDEX @index;
-        close(INDEX);
-
-        chomp($keyname);
-        print " * $zone: neuer KSK $keyname\n";
-        
-
-        print "!! DER KSK muss veroeffentlicht werden !! \n";
-
-    }
-}
-
-sub creat_zsk {
-    our @zones;
-    our $master_dir;
-    my @index;
-    my $zone;
-    my $keyname;
-    my $zpf;
-
-    for (@zones) {
-        $zone = $_;
-        $zpf = "$master_dir/$zone";
-
-        chdir "$zpf" or die "$zpf: $!\n";
-        $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
-
-        unless ( -f ".index.zsk" ) { @index = ();}
-        else {
-            open( INDEX, ".index.zsk" ) or die "$zpf/.index.zsk: $!\n";
-            @index = <INDEX>;
-            close(INDEX);
-        }
-
-        push @index, $keyname;
-        if ( @index > 2 ) { shift(@index);}
-
-        open( INDEX, ">.index.zsk" ) or die "$zpf/.index.zsk: $!\n";
-        print INDEX @index;
-        close(INDEX);
-
-        chomp($keyname);
-        print " * $zone: neuer ZSK $keyname\n";
-
-        open( KC, ">.keycounter" ) or die "$zpf/keycounter: $!\n";
-        print KC "0";
-        close(KC);
-
-    }
-}
-
-sub ck_zone {
-    our @zones;
-    our $master_dir;
-    my $zone;
-
-    for (@zones) {
-        $zone = $_;
-        my $zpf = "$master_dir/$zone";
-        my $keyfile;
-        my @content;
-        my @keylist;
-
-        for (<$zpf/*>) {
-            if (m#(K$zone.*\.key)#) {
-                $keyfile = $1;
-                open (KEYFILE, "<$zpf/$keyfile");
-                @content = <KEYFILE>;
-                close (KEYFILE);
-                for (@content) {
-                    if (m#DNSKEY.257#) {
-                        push @keylist, $keyfile;
-                    }
-                }
-            }
-        }
-
-        open( INDEX, ">.index.ksk" ) or die "$zpf/.index.ksk: $!\n";
-        for (@keylist) {
-            s#\.key##;
-            print INDEX "$_\n";
-        }
-        close(INDEX);
-        
-        print " * $zone: neue .index.ksk erzeugt\n";
-
-        if (-f "$zpf/.index.zsk") {
-            unlink ("$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
-        }
-    }
-}
-
-sub post_creat {
-    our @zones;
-    our $master_dir;
-
-    for (@zones) {
-        my $zone = $_;
-        `touch $master_dir/$zone/$zone`;
-
-        &kill_useless_keys($zone);
-        &key_to_zonefile($zone);
-    }
-
-}
-
-sub kill_useless_keys {
-    # die funktion loescht alle schluessel die nicht in der index.zsk
-    # der uebergebenen zone stehen
-    our $master_dir;
-    my $zone     = $_[0];
-    my @keylist  = ();
-    my $zpf      = "$master_dir/$zone";
-
-    open (INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
-    @keylist = <INDEX>;
-    close(INDEX);
-    open (INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
-    push @keylist, <INDEX>;
-
-    # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie
-    # besser vergleichen zu koennen.
-    for ( @keylist ) {
-        chomp;
-        s#K.*\+.*\+(.*)#$1#;
-    }
-
-    # prueft alle schluesseldateien (ksk, zsk), ob sie in der jeweiligen
-    # indexdatei beschrieben sind. wenn nicht werden sie geloescht.
-    for ( glob("$master_dir/$zone/K*") {
-        chomp;
-        my $file = $_;
-        my $rm_count = 1;
-        my $keyname;
-        for (@keylist) {
-            if ( $file =~ /$_/ ) { $rm_count = 0;}
-        }
-        if ($rm_count == 1) {
-            unlink "$file";
-            if ($file =~ /$zpf\/(.*\.key)/ ) {
-                print " * $zone: Schluessel $1 entfernt \n";
-            }
-        }
-    }
-}
-
-sub key_to_zonefile {
-    # die funktion fugt alle schluessel in eine zonedatei
-    our $master_dir;
-    my $zone = $_[0];
-    my $zpf = "$master_dir/$zone";
-    my @old_content;
-    my @new_content = ();
-
-    open(ZONEFILE, "<$zpf/$zone");
-    @old_content = <ZONEFILE>;
-    close(ZONEFILE);
-
-    for (@old_content) {
-        unless (m#INCLUDE.*key#) { push @new_content, $_; }
-    }
-
-    for (<$zpf/*>) {
-        if (m#(.*\/)(K.*\.key)#) {
-            push @new_content, "\$INCLUDE \"$2\"\n";
-        }
-    }
-    open( ZONEFILE, ">$zpf/$zone" ) or die "$zpf/$zone: $!\n";
-    print ZONEFILE @new_content;
-    close(ZONEFILE);
-}
-
-
-&read_conf;
-
-our %config;
-our $do;     # arbeitsschritte aus argv
-our @zones;  # liste der zonen in argv
-our $master_dir      = $config{master_dir};
-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};
-
-&read_argv;
-
-unless (@zones) {exit;} # beendet das programm, wurden keine
-                        # gueltigen zonen uebergeben
-
-if ($do eq "rm") { &rm_keys; exit;}
-if ($do eq "ck") { &ck_zone;}
-if ($do eq "ksk") { &creat_ksk; }
-
-&creat_zsk;
-&post_creat;
-
-__END__
-
-=pod
-
-=head1 TITLE
-
-dnssec-keytool
-
-=head1 SYNTAX
-
-dnssec-keytool <option> zone
-
-=head1 BESCHREIBUNG
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnssec-keytool.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,371 @@
+#! /usr/bin/perl
+
+use warnings;
+use strict;
+use FindBin;
+
+sub del_double {
+    my %all;
+    grep { $all{$_} = 0 } @_;
+    return (keys %all);
+}
+
+sub read_conf {
+
+    # liest die Konfiguration ein
+    my @configs = ("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+    our %config;
+
+    for (grep { -f } @configs) {
+        open(CONFIG, $_) or die "Can't open $_: $!\n";
+    }
+    unless (seek(CONFIG, 0, 0)) {
+        die "Can't open config (searched: @configs)\n";
+    }
+    while (<CONFIG>) {
+        chomp;
+        s/#.*//;
+        s/\t//g;
+        s/\s//g;
+
+        next unless length;
+        my ($cname, $ccont) = split(/\s*=\s*/, $_, 2);
+        $config{$cname} = $ccont;
+    }
+    close(CONFIG);
+}
+
+sub read_argv {
+
+    # wertet argv aus oder gibt die hilfe aus
+    my $arg = shift @ARGV;
+    my $zone;
+    our $do;
+    our @zones;
+    our $master_dir;
+
+    if (!defined $arg) {
+        print " usage: dnssec-keytool <option> zone\n";
+        print "   -z  erstellt einen neuen ZSK\n";
+        print "   -k  erstellt je einen neuen ZSK und KSK\n";
+        print "   -rm loescht das Schluesselmaterial einer Zone\n";
+        print "   -c  erstellt bei existierenden ksk konfigurationsdateien\n";
+        print "       fuer die dnstools, sowie einen neuen zsk\n";
+        print "\n";
+
+        exit;
+    }
+    elsif ($arg eq "-k")  { $do = "ksk"; }
+    elsif ($arg eq "-rm") { $do = "rm"; }
+    elsif ($arg eq "-c")  { $do = "ck"; }
+    elsif ($arg eq "-z")  { $do = "zsk"; }
+    else {
+        print "keine gueltige Option.\n";
+        exit;
+    }
+
+    # prueft die zonen in argv ob es verwaltete zonen sind
+    for (@ARGV) {
+        chomp($zone = `idn --quiet "$_"`);
+        if (-e "$master_dir/$zone/$zone") {
+            push @zones, $zone;
+        }
+    }
+}
+
+sub rm_keys {
+    # loescht alle schluessel wenn -rm uebergeben wurde
+    our @zones;
+    our $master_dir;
+    my $zone;
+    my @new_zone_content;
+    my @old_zone_content;
+
+    for (@zones) {
+        $zone = $_;
+
+        my $zpf = "$master_dir/$zone";
+        my $ep  = 0;
+
+        if (-e "$zpf/$zone.signed") {
+            unlink "$zpf/$zone.signed" and $ep = 1;
+        }
+        if (-e "$zpf/.keycounter") {
+            unlink "$zpf/.keycounter" and $ep = 1;
+        }
+        if (-e "$zpf/.index.ksk") {
+            unlink "$zpf/.index.ksk" and $ep = 1;
+        }
+        if (-e "$zpf/.index.zsk") {
+            unlink "$zpf/.index.zsk" and $ep = 1;
+        }
+        if (-e "$zpf/dsset-$zone.") {
+            unlink "$zpf/dsset-$zone." and $ep = 1;
+        }
+        if (-e "$zpf/keyset-$zone.") {
+            unlink "$zpf/keyset-$zone." and $ep = 1;
+        }
+
+        for (glob("$zpf/K$zone*")) { 
+            chomp($_);
+            unlink ("$_");
+        }
+
+        if ($ep == 1) {
+            print " * $zone: schluesselmaterial entfernt\n";
+        }
+
+        open(ZONE, "$zpf/$zone")
+          or die "$zpf/$zone: $!\n";
+        @old_zone_content = <ZONE>;
+        close(ZONE);
+
+        for (@old_zone_content) {
+            unless (m#\$INCLUDE.*\"K$zone.*\.key\"#) {
+                push @new_zone_content, $_;
+            }
+        }
+
+        open(ZONE, ">$zpf/$zone") or die "$zpf/$zone: $!\n";
+        print ZONE @new_zone_content;
+        close(ZONE);
+    }
+}
+
+sub creat_ksk {
+    our @zones;
+    our $master_dir;
+    my @index;
+    my $zone;
+    my $keyname;
+    my $zpf;
+
+    for (@zones) {
+        $zone = $_;
+        $zpf  = "$master_dir/$zone";
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        $keyname = `dnssec-keygen -a RSASHA1 -b 2048 -f KSK -n ZONE $zone`;
+
+        unless (-f ".index.ksk") { @index = (); }
+        else {
+            open(INDEX, ".index.ksk") or die "$zpf/.index.ksk: $!\n";
+            @index = <INDEX>;
+            close(INDEX);
+        }
+
+        push @index, $keyname;
+        if (@index > 2) { shift(@index); }
+
+        open(INDEX, ">.index.ksk") or die "$zpf/.index.ksk: $!\n";
+        print INDEX @index;
+        close(INDEX);
+
+        chomp($keyname);
+        print " * $zone: neuer KSK $keyname\n";
+
+        print "!! DER KSK muss veroeffentlicht werden !! \n";
+
+    }
+}
+
+sub creat_zsk {
+    our @zones;
+    our $master_dir;
+    my @index;
+    my $zone;
+    my $keyname;
+    my $zpf;
+
+    for (@zones) {
+        $zone = $_;
+        $zpf  = "$master_dir/$zone";
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
+
+        unless (-f ".index.zsk") { @index = (); }
+        else {
+            open(INDEX, ".index.zsk") or die "$zpf/.index.zsk: $!\n";
+            @index = <INDEX>;
+            close(INDEX);
+        }
+
+        push @index, $keyname;
+        if (@index > 2) { shift(@index); }
+
+        open(INDEX, ">.index.zsk") or die "$zpf/.index.zsk: $!\n";
+        print INDEX @index;
+        close(INDEX);
+
+        chomp($keyname);
+        print " * $zone: neuer ZSK $keyname\n";
+
+        open(KC, ">.keycounter") or die "$zpf/keycounter: $!\n";
+        print KC "0";
+        close(KC);
+
+    }
+}
+
+sub ck_zone {
+    our @zones;
+    our $master_dir;
+    my $zone;
+
+    for (@zones) {
+        $zone = $_;
+        my $zpf = "$master_dir/$zone";
+        my $keyfile;
+        my @content;
+        my @keylist;
+
+        for (<$zpf/*>) {
+            if (m#(K$zone.*\.key)#) {
+                $keyfile = $1;
+                open(KEYFILE, "<$zpf/$keyfile");
+                @content = <KEYFILE>;
+                close(KEYFILE);
+                for (@content) {
+                    if (m#DNSKEY.257#) {
+                        push @keylist, $keyfile;
+                    }
+                }
+            }
+        }
+
+        open(INDEX, ">.index.ksk") or die "$zpf/.index.ksk: $!\n";
+        for (@keylist) {
+            s#\.key##;
+            print INDEX "$_\n";
+        }
+        close(INDEX);
+
+        print " * $zone: neue .index.ksk erzeugt\n";
+
+        if (-f "$zpf/.index.zsk") {
+            unlink("$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
+        }
+    }
+}
+
+sub post_creat {
+    our @zones;
+    our $master_dir;
+
+    for (@zones) {
+        my $zone = $_;
+        `touch $master_dir/$zone/$zone`;
+
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+    }
+
+}
+
+sub kill_useless_keys {
+
+    # die funktion loescht alle schluessel die nicht in der index.zsk
+    # der uebergebenen zone stehen
+    our $master_dir;
+    my $zone    = $_[0];
+    my @keylist = ();
+    my $zpf     = "$master_dir/$zone";
+
+    open(INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
+    @keylist = <INDEX>;
+    close(INDEX);
+    open(INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
+    push @keylist, <INDEX>;
+
+    # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie
+    # besser vergleichen zu koennen.
+    for (@keylist) {
+        chomp;
+        s#K.*\+.*\+(.*)#$1#;
+    }
+
+    # prueft alle schluesseldateien (ksk, zsk), ob sie in der jeweiligen
+    # indexdatei beschrieben sind. wenn nicht werden sie geloescht.
+    for ( glob("$master_dir/$zone/K*") {
+        chomp;
+        my $file     = $_;
+        my $rm_count = 1;
+        my $keyname;
+        for (@keylist) {
+            if ($file =~ /$_/) { $rm_count = 0; }
+        }
+        if ($rm_count == 1) {
+            unlink "$file";
+            if ($file =~ /$zpf\/(.*\.key)/) {
+                print " * $zone: Schluessel $1 entfernt \n";
+            }
+        }
+    }
+}
+
+sub key_to_zonefile {
+
+    # die funktion fugt alle schluessel in eine zonedatei
+    our $master_dir;
+    my $zone = $_[0];
+    my $zpf  = "$master_dir/$zone";
+    my @old_content;
+    my @new_content = ();
+
+    open(ZONEFILE, "<$zpf/$zone");
+    @old_content = <ZONEFILE>;
+    close(ZONEFILE);
+
+    for (@old_content) {
+        unless (m#INCLUDE.*key#) { push @new_content, $_; }
+    }
+
+    for (<$zpf/*>) {
+        if (m#(.*\/)(K.*\.key)#) {
+            push @new_content, "\$INCLUDE \"$2\"\n";
+        }
+    }
+    open(ZONEFILE, ">$zpf/$zone") or die "$zpf/$zone: $!\n";
+    print ZONEFILE @new_content;
+    close(ZONEFILE);
+}
+
+&read_conf;
+
+our %config;
+our $do;       # arbeitsschritte aus argv
+our @zones;    # liste der zonen in argv
+our $master_dir      = $config{master_dir};
+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};
+
+&read_argv;
+
+unless (@zones) { exit; }    # beendet das programm, wurden keine
+                             # gueltigen zonen uebergeben
+
+if ($do eq "rm") { &rm_keys; exit; }
+if ($do eq "ck") { &ck_zone; }
+if ($do eq "ksk") { &creat_ksk; }
+
+&creat_zsk;
+&post_creat;
+
+__END__
+
+=pod
+
+=head1 TITLE
+
+dnssec-keytool
+
+=head1 SYNTAX
+
+dnssec-keytool <option> zone
+
+=head1 BESCHREIBUNG
--- a/update-serial	Tue Dec 21 15:47:40 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,566 +0,0 @@
-#!/usr/bin/perl 
-
-use strict;
-use warnings;
-use FindBin;
-use File::Basename;
-
-sub del_double {
-    # entfernt doppelte eintraege in einer liste
-    my %all;
-    grep { $all{$_} = 0 } @_;
-    return ( keys %all );
-}
-
-sub read_conf {
-    # liest die Konfiguration ein
-    my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
-    our %config;
-
-    for ( grep {-f} @configs ) {
-        open( CONFIG, $_ ) or die "Can't open $_: $!\n";
-    }
-    unless ( seek( CONFIG, 0, 0 ) ) {
-        die "Can't open config (searched: @configs)\n";
-    }
-    while (<CONFIG>) {
-        chomp;
-        s/#.*//;
-        s/\t//g;
-        s/\s//g;
-
-        next unless length;
-        my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
-        $config{$cname} = $ccont;
-    }
-    close(CONFIG);
-}
-
-sub add_argv {
-    # prueft ob zonen aus ARGV verwaltete zonen sind
-    # und fuegt sie, falls ja in die liste @new_serial ein
-    our @new_serial;
-    our $master_dir;
-    my $zone;
-    
-    for (@ARGV) {
-        chomp( $zone = `idn --quiet "$_"` );
-        if ( -e "$master_dir/$zone/$zone" ) {
-            push @new_serial, $zone;
-        }
-    }
-}
-
-sub changed_zone {
-    our $master_dir;
-    our @new_serial;
-
-    for (<$master_dir/*>) {
-        my $zone = basename($_);
-
-        if (-e "$master_dir/$zone/.stamp") {
-            my $stamptime = (-M "$master_dir/$zone/.stamp");
-            my $filetime = (-M "$master_dir/$zone/$zone");
-            if ($stamptime > $filetime) {
-                push @new_serial, $zone;
-                print " * $zone: zonedatei wurde geaendert\n";
-            }
-        }
-        else {
-            print " * $zone: keine .stamp-datei gefunden\n"; # NOCH IN NEW_SERIAL PUSHEN
-            push @new_serial, $zone;
-        }
-    }
-
-}
-
-sub sign_end {
-    our $sign_alert_time;  # die zeit zwischen dem ende und der neuen
-                           # signierung (siehe externe konfiguration)
-    our $master_dir;
-    our @new_serial;
-    
-    # erzeugt $time (die zeit ab der neu signiert werden soll)
-    chomp( my $unixtime = `date +%s` );
-    $unixtime = $unixtime + ( 3600 * $sign_alert_time );
-    my $time = `date -d \@$unixtime +%Y%m%d%H`;
-    
-    ## vergleicht fuer alle zonen im ordner $master_dir mit einer
-    ## <zone>.signed-datei den zeitpunkt in $time mit dem ablaufdatum der
-    ## signatur, welcher aus der datei <zone>.signed ausgelesen wird.
-    for (<$master_dir/*>) {
-        s#($master_dir/)(.*)#$2#;
-        my $zone = $_;
-    
-        if ( -e "$master_dir/$zone/$zone.signed" ) {
-            open( ZONE, "$master_dir/$zone/$zone.signed" );
-            my @zone_sig_content = <ZONE>;
-            close(ZONE);
-            
-            for (@zone_sig_content) {
-                if (m#SOA.*[0-9]{14}#) {
-                    s#.*([0-9]{10})([0-9]{4}).*#$1#;
-                    if ( $_ < $time ) {
-                        push @new_serial, $zone;
-                    }
-                }
-            }
-        }
-    }
-}
-
-sub sign_zone {
-    # signiert die zonen und erhoeht den wert in der keycounter-datei
-    our @new_serial;
-    our $master_dir;
-    my $zone;
-    my $kc;
-
-    for ( &del_double( @new_serial ) ) {
-        $zone = $_;
-
-        unless (-e "$master_dir/$zone/.index.zsk") {
-            next;
-        }
-
-        chdir "$master_dir/$zone";
-        if (`dnssec-signzone $zone 2>/dev/null`) {
-            print " * $zone neu signiert \n";
-
-            # erhoeht den keycounter
-            if ("$master_dir/$zone/.keycounter") {
-                open( KC, "$master_dir/$zone/.keycounter" );
-                $kc = <KC>;
-                close(KC);
-                $kc += 1;
-            }
-            else {
-                $kc = 1;
-            }
-            open( KC, ">$master_dir/$zone/.keycounter" );
-            print KC $kc;
-            close(KC);
-        }
-        else { print "$zone konnte nicht signiert werden \n"; }
-    }
-}
-
-sub update_serial {
-    our $master_dir;
-    our @new_serial;
-    chomp (my  $date = `date +%Y%m%d`);
-    my @new_content;
-    my  $sdate;
-    my  $scount;
-    my  $serial;
-
-    for ( &del_double( @new_serial ) ) {
-        # erhoeht den serial
-        my $zone = $_;
-        my $file = "$master_dir/$zone/$zone";
-        my @new_content = ();
- 
-        open (SER, "<$file") or die "$file: $!\n";
-        for (<SER>) {
-            if (/^\s+(\d+)(\d{2})\s*;\s*serial/i) {
-                $sdate  = $1;
-                $scount = $2;
-                $serial = "$sdate$scount";
-                if ( $date eq $sdate ) {
-                    $scount++;
-                }
-                else {
-                    $sdate = $date;
-                    $scount = "00";
-                }
-            }
-            if ($serial) {
-                s/$serial/$sdate$scount/;
-            }
-            push @new_content, $_;
-        }
-        close (SER);
-
-        open (RES, ">$file") or die "$file: $!\n";
-        print RES @new_content;
-        close (RES);
-        print " * $zone: serial erhoeht \n";
-
-        open(STAMP, ">$master_dir/$zone/.stamp") or die "$master_dir/$zone/.stamp: $!\n";
-        close(STAMP);
-        print " * $zone: stamp aktualisiert \n";
-    }
-}
-
-sub mk_zone_conf {
-    # erzeugt eine named.conf-datei aus den entsprechenden vorlagen.
-    our $bind_dir;
-    our $conf_dir;
-
-    open( TO, ">$bind_dir/named.conf.zones" )
-        or die "$bind_dir/named.conf.zones: $!\n";
-    while (<$conf_dir/*>) {
-        open( FROM, "$_" ) or die "$_: $! \n";
-        print TO <FROM>;
-        close(FROM);
-    }
-    close(TO);
-    print "** zonekonfiguration erzeugt\n";
-}
-
-sub update_index {
-    # aktualisiert die indexzone;
-    our @new_serial;
-    our $indexzone;
-    our $master_dir;
-    my @iz_content_old;
-    my @iz_content_new;
-
-    open (INDEXZONE, "$master_dir/$indexzone/$indexzone")
-        or die "$master_dir/$indexzone/$indexzone: $!\n";
-    @iz_content_old = <INDEXZONE>;
-    close (INDEXZONE);
-
-    for (@iz_content_old) {
-        unless (m#ZONE::#) {
-            push @iz_content_new, $_;
-        }
-    }
-
-    for my $dir ( glob "$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;
-    }
-
-    open (INDEXZONE, ">$master_dir/$indexzone/$indexzone")
-        or die "$master_dir/$indexzone/$indexzone: $!\n";
-    print INDEXZONE @iz_content_new;
-    close (INDEXZONE);
-
-    # fuegt die index-zone in die liste damit der serial erhoet wird
-    push @new_serial, $indexzone;
-
-    print "** index-zone aktualisiert \n";
-}
-
-sub file_entry {
-    # prueft jede domain, die ein verzeichnis in $master_dir hat, ob sie
-    # dnssec nutzt.
-    # passt die eintraege in $config_file falls noetig an.
-    our $master_dir;
-    our $conf_dir;
-
-    while (<$master_dir/*>) {
-        s#($master_dir/)(.*)#$2#;
-        my $zone = $_;
-        my $zone_file = "$master_dir/$zone/$zone";
-        my $conf_file = "$conf_dir/$zone";
-        my @c_content;
-
-        unless ( -f "$conf_file" ) {
-            die "$conf_file: $! \n";
-        }
-
-        if ( -e "$master_dir/$zone/.keycounter" ) {
-            open( FILE, "<$conf_file" ) or die "$conf_file: $!\n";
-            @c_content = <FILE>;
-            close(FILE);
-            for (@c_content) {
-                if (m{(.*)($zone_file)(";)}) {
-                    print " * zonekonfiguration aktualisiert ($2 ==> $2.signed)\n";
-                    $_ = "$1$2.signed$3\n";
-                }
-            }
-            open( FILE, ">$conf_file" ) or die "$conf_file: $!\n";
-            print FILE @c_content;
-            close(FILE);
-        }
-        else {
-            open( FILE, "<$conf_file" ) or die "$conf_file: $!\n";
-            @c_content = <FILE>;
-            close(FILE);
-            for (@c_content) {
-                if (m{(.*)($zone_file)\.signed(.*)}) {
-                    print " * zonekonfiguration aktualisiert ($2.signed ==> $2)\n";
-                    $_ = "$1$2$3\n";
-                }
-            }
-            open( FILE, ">$conf_file" ) or die "$conf_file: $!\n";
-            print FILE @c_content;
-            close(FILE);
-        }
-    }
-}
-
-sub server_reload {
-    if (`rndc reload`) {print "** reload dns-server \n"};
-}
-
-sub to_begin_ro {
-    # gibt alle zonen mit abgelaufenen keycounter in die liste @begin_ro_list
-    our @begin_ro_list;
-    our $master_dir;
-    our $key_counter_end;
-    our @new_serial;
-    my $zone;
-
-    while (<$master_dir/*>) {
-        chomp( $zone = $_ );
-        my $key;
-
-        unless (-f "$zone/.keycounter" ) {next;}
-
-        open( KEY, "$zone/.keycounter" ) or die "$zone/.keycounter: $!\n";
-        $key = <KEY>;
-        close(KEY);
-
-        # vergleicht den wert aus der keycount-datei mit dem wert aus der
-        #dnstools.conf (key_counter_end)
-        if ( $key_counter_end <= $key ) {
-            $zone =~ s#($master_dir/)(.*)#$2#;
-            push @begin_ro_list, $zone;
-        }
-    }
-}
-
-sub to_end_ro {
-    # funktion ueberprueft ob ein keyrollover fertig ist
-    # die bedingung dafuer ist das:
-    # - eine datei .index.zsk vorhanden ist
-    # - die datei .index.zsk vor mehr x stunden geaendert wurde
-    # - die datei .index.zsk ueber mehr als zwei zeilen gross ist
-    our $master_dir;
-    our @end_ro_list;
-    our $ablauf_zeit;
-    chomp( my $now_time = `date +%s` );
-
-    for (<$master_dir/*>) {
-        my $zone = $_;
-        $zone =~ s#($master_dir/)(.*)#$2#;
-
-        my @index = ();
-        my $index_wc;
-        my @status;
-
-        # prueft nach der ".index.zsk"-datei und erstellt den zeitpunkt
-        # an dem das key-rollover endet. - $status[9]
-        if ( -e "$master_dir/$zone/.index.zsk" ) {
-            @status = stat("$master_dir/$zone/.index.zsk");
-            $status[9] += ( 3600 * $ablauf_zeit );
-        }
-        else { next; }
-
-        # $status[9] ist der zeitpunkt an dem der key-rollover endet
-        # prueft ob das key-rollover-ende erreicht ist
-        unless ( $status[9] < $now_time ) { next;}
-
-        # prueft die anzahl der schluessel in der .index.zsk
-        open( INDEX, "$master_dir/$zone/.index.zsk" )
-            or die "$master_dir/$zone/.index.zsk: $!\n";
-        @index    = <INDEX>;
-        $index_wc = @index;
-        close(INDEX);
-        if ( $index_wc > 1 ) {push @end_ro_list, $zone;}
-    }
-}
-
-sub begin_ro {
-    # anfang des key-rollovers
-    our @begin_ro_list;
-    our $master_dir;
-    our @new_serial;
-
-    for ( &del_double( @begin_ro_list ) ) {
-        #erzeugt zsks
-        my $zone = $_;
-        my $zpf   = "$master_dir/$zone";
-        my @index;
-
-        chdir "$zpf" or die "$zpf: $!\n";
-        my $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
-
-        open( INDEX, ".index.zsk" ) or die "$zpf/.index.zsk: $!\n";
-        @index = <INDEX>;
-        close(INDEX);
-
-        push @index, $keyname;
-        if ( @index > 2 ) { shift(@index); }
-
-        open( INDEX, ">.index.zsk" ) or die "$zpf/.index.zsk: $!\n";
-        print INDEX @index;
-        close(INDEX);
-
-        chomp($keyname);
-        print " * $zone: neuer ZSK $keyname erstellt\n";
-
-        open( KC, ">.keycounter" ) or die "$zpf/keycounter: $!\n";
-        print KC "0";
-        close(KC);
-
-        &kill_useless_keys($zone);
-        &key_to_zonefile($zone);
-        push @new_serial, $zone;
-    }
-}
-
-sub key_to_zonefile {
-    # die funktion fugt alle schluessel in eine zonedatei
-    our $master_dir;
-    my $zone = $_[0];
-    my $zpf = "$master_dir/$zone";
-    my @old_content;
-    my @new_content = ();
-
-    open(ZONEFILE, "<$zpf/$zone");
-    @old_content = <ZONEFILE>;
-    close(ZONEFILE);
-
-    for (@old_content) {
-        unless (m#INCLUDE.*key#) { push @new_content, $_; }
-    }
-
-    for (<$zpf/*>) {
-        if (m#(.*\/)(K.*\.key)#) {
-            push @new_content, "\$INCLUDE \"$2\"\n";
-        }
-    }
-    open( ZONEFILE, ">$zpf/$zone" ) or die "$zpf/$zone: $!\n";
-    print ZONEFILE @new_content;
-    close(ZONEFILE);
-}
-
-sub kill_useless_keys {
-    # die funktion loescht alle schluessel die nicht in der index.zsk
-    # der uebergebenen zone stehen
-    our $master_dir;
-    my $zone     = $_[0];
-    my @keylist  = ();
-    my $zpf      = "$master_dir/$zone";
-
-    open (INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
-    @keylist = <INDEX>;
-    close(INDEX);
-    open (INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
-    push @keylist, <INDEX>;
-
-    # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie
-    # besser vergleichen zu koennen.
-    for ( @keylist ) {
-        chomp;
-        s#K.*\+.*\+(.*)#$1#;
-    }
-
-    # prueft alle schluesseldateien (ksk, zsk) ob sie in der jeweiligen
-    # indexdatei beschrieben sind. wenn nicht werden sie geloescht.
-    for (`ls $master_dir/$zone/K*[key,private]`) {
-        chomp;
-        my $file = $_;
-        my $rm_count = 1;
-        my $keyname;
-        for (@keylist) {
-            if ( $file =~ /$_/ ) { $rm_count = 0;}
-        }
-        if ($rm_count == 1) {
-            unlink "$file";
-            if ($file =~ /$zpf\/(.*\.key)/ ) {
-                print " * $zone: Schluessel $1 entfernt \n";
-            }
-        }       
-    }
-}
-
-sub end_ro {
-    our @end_ro_list;
-    our $master_dir;
-    our @new_serial;
-    my @content;
-
-    for (@end_ro_list) {
-        my $zone = $_;
-        my $count = 0;
-        my @content;
-        my $last_key;
-
-        open (INDEX, "<$master_dir/$zone/.index.zsk");
-        @content = <INDEX>;
-        close(INDEX);
-
-        for (@content) {
-            $count++;
-            $last_key = $_;
-        }
-        if ($count > 1) {
-            open (INDEX, ">$master_dir/$zone/.index.zsk");
-            print INDEX $last_key;
-            close (INDEX);
-        }
-        &kill_useless_keys($zone);
-        &key_to_zonefile($zone);
-        push @new_serial, $zone;
-    }
-}
-
-
-&read_conf;
-
-our %config;
-our @new_serial;     # liste fuer neuen serial
-our @begin_ro_list;  # liste mit zonen deren key-rollover beginnt
-our @end_ro_list;    # liste mit zonen deren key-rollover fertig ist
-our $master_dir      = $config{master_dir};
-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;
-&changed_zone;
-&sign_end;
-
-&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
-}
-
-if (@end_ro_list) {
-    &end_ro; # eine rollover-end-squenz
-}
-
-if (@new_serial) {
-    &update_index; # index zone aktuallisieren
-    &update_serial; # serial aktuallisieren
-    &sign_zone; # zone signieren
-}
-
-&file_entry;  # bearbeitet die file-eintraege der konfigurations-datei
-&mk_zone_conf; # konfiguration zusammenfuegen
-&server_reload; # server neu laden
-
-
-
-__END__
-
-=pod
-
-=head1 TITLE
-
-update-serial
-
-=head1 SYNTAX
-
-update-serial
-
-=head1 BESCHREIBUNG
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/update-serial.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,584 @@
+#!/usr/bin/perl 
+
+use strict;
+use warnings;
+use FindBin;
+use File::Basename;
+
+sub del_double {
+
+    # entfernt doppelte eintraege in einer liste
+    my %all;
+    grep { $all{$_} = 0 } @_;
+    return (keys %all);
+}
+
+sub read_conf {
+
+    # liest die Konfiguration ein
+    my @configs = ("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+    our %config;
+
+    for (grep { -f } @configs) {
+        open(CONFIG, $_) or die "Can't open $_: $!\n";
+    }
+    unless (seek(CONFIG, 0, 0)) {
+        die "Can't open config (searched: @configs)\n";
+    }
+    while (<CONFIG>) {
+        chomp;
+        s/#.*//;
+        s/\t//g;
+        s/\s//g;
+
+        next unless length;
+        my ($cname, $ccont) = split(/\s*=\s*/, $_, 2);
+        $config{$cname} = $ccont;
+    }
+    close(CONFIG);
+}
+
+sub add_argv {
+
+    # prueft ob zonen aus ARGV verwaltete zonen sind
+    # und fuegt sie, falls ja in die liste @new_serial ein
+    our @new_serial;
+    our $master_dir;
+    my $zone;
+
+    for (@ARGV) {
+        chomp($zone = `idn --quiet "$_"`);
+        if (-e "$master_dir/$zone/$zone") {
+            push @new_serial, $zone;
+        }
+    }
+}
+
+sub changed_zone {
+    our $master_dir;
+    our @new_serial;
+
+    for (<$master_dir/*>) {
+        my $zone = basename($_);
+
+        if (-e "$master_dir/$zone/.stamp") {
+            my $stamptime = (-M "$master_dir/$zone/.stamp");
+            my $filetime  = (-M "$master_dir/$zone/$zone");
+            if ($stamptime > $filetime) {
+                push @new_serial, $zone;
+                print " * $zone: zonedatei wurde geaendert\n";
+            }
+        }
+        else {
+            print " * $zone: keine .stamp-datei gefunden\n"
+              ;    # NOCH IN NEW_SERIAL PUSHEN
+            push @new_serial, $zone;
+        }
+    }
+
+}
+
+sub sign_end {
+    our $sign_alert_time;    # die zeit zwischen dem ende und der neuen
+                             # signierung (siehe externe konfiguration)
+    our $master_dir;
+    our @new_serial;
+
+    # erzeugt $time (die zeit ab der neu signiert werden soll)
+    chomp(my $unixtime = `date +%s`);
+    $unixtime = $unixtime + (3600 * $sign_alert_time);
+    my $time = `date -d \@$unixtime +%Y%m%d%H`;
+
+    ## vergleicht fuer alle zonen im ordner $master_dir mit einer
+    ## <zone>.signed-datei den zeitpunkt in $time mit dem ablaufdatum der
+    ## signatur, welcher aus der datei <zone>.signed ausgelesen wird.
+    for (<$master_dir/*>) {
+        s#($master_dir/)(.*)#$2#;
+        my $zone = $_;
+
+        if (-e "$master_dir/$zone/$zone.signed") {
+            open(ZONE, "$master_dir/$zone/$zone.signed");
+            my @zone_sig_content = <ZONE>;
+            close(ZONE);
+
+            for (@zone_sig_content) {
+                if (m#SOA.*[0-9]{14}#) {
+                    s#.*([0-9]{10})([0-9]{4}).*#$1#;
+                    if ($_ < $time) {
+                        push @new_serial, $zone;
+                    }
+                }
+            }
+        }
+    }
+}
+
+sub sign_zone {
+
+    # signiert die zonen und erhoeht den wert in der keycounter-datei
+    our @new_serial;
+    our $master_dir;
+    my $zone;
+    my $kc;
+
+    for (&del_double(@new_serial)) {
+        $zone = $_;
+
+        unless (-e "$master_dir/$zone/.index.zsk") {
+            next;
+        }
+
+        chdir "$master_dir/$zone";
+        if (`dnssec-signzone $zone 2>/dev/null`) {
+            print " * $zone neu signiert \n";
+
+            # erhoeht den keycounter
+            if ("$master_dir/$zone/.keycounter") {
+                open(KC, "$master_dir/$zone/.keycounter");
+                $kc = <KC>;
+                close(KC);
+                $kc += 1;
+            }
+            else {
+                $kc = 1;
+            }
+            open(KC, ">$master_dir/$zone/.keycounter");
+            print KC $kc;
+            close(KC);
+        }
+        else { print "$zone konnte nicht signiert werden \n"; }
+    }
+}
+
+sub update_serial {
+    our $master_dir;
+    our @new_serial;
+    chomp(my $date = `date +%Y%m%d`);
+    my @new_content;
+    my $sdate;
+    my $scount;
+    my $serial;
+
+    for (&del_double(@new_serial)) {
+
+        # erhoeht den serial
+        my $zone        = $_;
+        my $file        = "$master_dir/$zone/$zone";
+        my @new_content = ();
+
+        open(SER, "<$file") or die "$file: $!\n";
+        for (<SER>) {
+            if (/^\s+(\d+)(\d{2})\s*;\s*serial/i) {
+                $sdate  = $1;
+                $scount = $2;
+                $serial = "$sdate$scount";
+                if ($date eq $sdate) {
+                    $scount++;
+                }
+                else {
+                    $sdate  = $date;
+                    $scount = "00";
+                }
+            }
+            if ($serial) {
+                s/$serial/$sdate$scount/;
+            }
+            push @new_content, $_;
+        }
+        close(SER);
+
+        open(RES, ">$file") or die "$file: $!\n";
+        print RES @new_content;
+        close(RES);
+        print " * $zone: serial erhoeht \n";
+
+        open(STAMP, ">$master_dir/$zone/.stamp")
+          or die "$master_dir/$zone/.stamp: $!\n";
+        close(STAMP);
+        print " * $zone: stamp aktualisiert \n";
+    }
+}
+
+sub mk_zone_conf {
+
+    # erzeugt eine named.conf-datei aus den entsprechenden vorlagen.
+    our $bind_dir;
+    our $conf_dir;
+
+    open(TO, ">$bind_dir/named.conf.zones")
+      or die "$bind_dir/named.conf.zones: $!\n";
+    while (<$conf_dir/*>) {
+        open(FROM, "$_") or die "$_: $! \n";
+        print TO <FROM>;
+        close(FROM);
+    }
+    close(TO);
+    print "** zonekonfiguration erzeugt\n";
+}
+
+sub update_index {
+
+    # aktualisiert die indexzone;
+    our @new_serial;
+    our $indexzone;
+    our $master_dir;
+    my @iz_content_old;
+    my @iz_content_new;
+
+    open(INDEXZONE, "$master_dir/$indexzone/$indexzone")
+      or die "$master_dir/$indexzone/$indexzone: $!\n";
+    @iz_content_old = <INDEXZONE>;
+    close(INDEXZONE);
+
+    for (@iz_content_old) {
+        unless (m#ZONE::#) {
+            push @iz_content_new, $_;
+        }
+    }
+
+    for my $dir (glob "$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;
+    }
+
+    open(INDEXZONE, ">$master_dir/$indexzone/$indexzone")
+      or die "$master_dir/$indexzone/$indexzone: $!\n";
+    print INDEXZONE @iz_content_new;
+    close(INDEXZONE);
+
+    # fuegt die index-zone in die liste damit der serial erhoet wird
+    push @new_serial, $indexzone;
+
+    print "** index-zone aktualisiert \n";
+}
+
+sub file_entry {
+
+    # prueft jede domain, die ein verzeichnis in $master_dir hat, ob sie
+    # dnssec nutzt.
+    # passt die eintraege in $config_file falls noetig an.
+    our $master_dir;
+    our $conf_dir;
+
+    while (<$master_dir/*>) {
+        s#($master_dir/)(.*)#$2#;
+        my $zone      = $_;
+        my $zone_file = "$master_dir/$zone/$zone";
+        my $conf_file = "$conf_dir/$zone";
+        my @c_content;
+
+        unless (-f "$conf_file") {
+            die "$conf_file: $! \n";
+        }
+
+        if (-e "$master_dir/$zone/.keycounter") {
+            open(FILE, "<$conf_file") or die "$conf_file: $!\n";
+            @c_content = <FILE>;
+            close(FILE);
+            for (@c_content) {
+                if (m{(.*)($zone_file)(";)}) {
+                    print
+                      " * zonekonfiguration aktualisiert ($2 ==> $2.signed)\n";
+                    $_ = "$1$2.signed$3\n";
+                }
+            }
+            open(FILE, ">$conf_file") or die "$conf_file: $!\n";
+            print FILE @c_content;
+            close(FILE);
+        }
+        else {
+            open(FILE, "<$conf_file") or die "$conf_file: $!\n";
+            @c_content = <FILE>;
+            close(FILE);
+            for (@c_content) {
+                if (m{(.*)($zone_file)\.signed(.*)}) {
+                    print
+                      " * zonekonfiguration aktualisiert ($2.signed ==> $2)\n";
+                    $_ = "$1$2$3\n";
+                }
+            }
+            open(FILE, ">$conf_file") or die "$conf_file: $!\n";
+            print FILE @c_content;
+            close(FILE);
+        }
+    }
+}
+
+sub server_reload {
+    if (`rndc reload`) { print "** reload dns-server \n" }
+}
+
+sub to_begin_ro {
+
+    # gibt alle zonen mit abgelaufenen keycounter in die liste @begin_ro_list
+    our @begin_ro_list;
+    our $master_dir;
+    our $key_counter_end;
+    our @new_serial;
+    my $zone;
+
+    while (<$master_dir/*>) {
+        chomp($zone = $_);
+        my $key;
+
+        unless (-f "$zone/.keycounter") { next; }
+
+        open(KEY, "$zone/.keycounter") or die "$zone/.keycounter: $!\n";
+        $key = <KEY>;
+        close(KEY);
+
+        # vergleicht den wert aus der keycount-datei mit dem wert aus der
+        #dnstools.conf (key_counter_end)
+        if ($key_counter_end <= $key) {
+            $zone =~ s#($master_dir/)(.*)#$2#;
+            push @begin_ro_list, $zone;
+        }
+    }
+}
+
+sub to_end_ro {
+
+    # funktion ueberprueft ob ein keyrollover fertig ist
+    # die bedingung dafuer ist das:
+    # - eine datei .index.zsk vorhanden ist
+    # - die datei .index.zsk vor mehr x stunden geaendert wurde
+    # - die datei .index.zsk ueber mehr als zwei zeilen gross ist
+    our $master_dir;
+    our @end_ro_list;
+    our $ablauf_zeit;
+    chomp(my $now_time = `date +%s`);
+
+    for (<$master_dir/*>) {
+        my $zone = $_;
+        $zone =~ s#($master_dir/)(.*)#$2#;
+
+        my @index = ();
+        my $index_wc;
+        my @status;
+
+        # prueft nach der ".index.zsk"-datei und erstellt den zeitpunkt
+        # an dem das key-rollover endet. - $status[9]
+        if (-e "$master_dir/$zone/.index.zsk") {
+            @status = stat("$master_dir/$zone/.index.zsk");
+            $status[9] += (3600 * $ablauf_zeit);
+        }
+        else { next; }
+
+        # $status[9] ist der zeitpunkt an dem der key-rollover endet
+        # prueft ob das key-rollover-ende erreicht ist
+        unless ($status[9] < $now_time) { next; }
+
+        # prueft die anzahl der schluessel in der .index.zsk
+        open(INDEX, "$master_dir/$zone/.index.zsk")
+          or die "$master_dir/$zone/.index.zsk: $!\n";
+        @index    = <INDEX>;
+        $index_wc = @index;
+        close(INDEX);
+        if ($index_wc > 1) { push @end_ro_list, $zone; }
+    }
+}
+
+sub begin_ro {
+
+    # anfang des key-rollovers
+    our @begin_ro_list;
+    our $master_dir;
+    our @new_serial;
+
+    for (&del_double(@begin_ro_list)) {
+
+        #erzeugt zsks
+        my $zone = $_;
+        my $zpf  = "$master_dir/$zone";
+        my @index;
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        my $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
+
+        open(INDEX, ".index.zsk") or die "$zpf/.index.zsk: $!\n";
+        @index = <INDEX>;
+        close(INDEX);
+
+        push @index, $keyname;
+        if (@index > 2) { shift(@index); }
+
+        open(INDEX, ">.index.zsk") or die "$zpf/.index.zsk: $!\n";
+        print INDEX @index;
+        close(INDEX);
+
+        chomp($keyname);
+        print " * $zone: neuer ZSK $keyname erstellt\n";
+
+        open(KC, ">.keycounter") or die "$zpf/keycounter: $!\n";
+        print KC "0";
+        close(KC);
+
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+        push @new_serial, $zone;
+    }
+}
+
+sub key_to_zonefile {
+
+    # die funktion fugt alle schluessel in eine zonedatei
+    our $master_dir;
+    my $zone = $_[0];
+    my $zpf  = "$master_dir/$zone";
+    my @old_content;
+    my @new_content = ();
+
+    open(ZONEFILE, "<$zpf/$zone");
+    @old_content = <ZONEFILE>;
+    close(ZONEFILE);
+
+    for (@old_content) {
+        unless (m#INCLUDE.*key#) { push @new_content, $_; }
+    }
+
+    for (<$zpf/*>) {
+        if (m#(.*\/)(K.*\.key)#) {
+            push @new_content, "\$INCLUDE \"$2\"\n";
+        }
+    }
+    open(ZONEFILE, ">$zpf/$zone") or die "$zpf/$zone: $!\n";
+    print ZONEFILE @new_content;
+    close(ZONEFILE);
+}
+
+sub kill_useless_keys {
+
+    # die funktion loescht alle schluessel die nicht in der index.zsk
+    # der uebergebenen zone stehen
+    our $master_dir;
+    my $zone    = $_[0];
+    my @keylist = ();
+    my $zpf     = "$master_dir/$zone";
+
+    open(INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
+    @keylist = <INDEX>;
+    close(INDEX);
+    open(INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
+    push @keylist, <INDEX>;
+
+    # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie
+    # besser vergleichen zu koennen.
+    for (@keylist) {
+        chomp;
+        s#K.*\+.*\+(.*)#$1#;
+    }
+
+    # prueft alle schluesseldateien (ksk, zsk) ob sie in der jeweiligen
+    # indexdatei beschrieben sind. wenn nicht werden sie geloescht.
+    for (`ls $master_dir/$zone/K*[key,private]`) {
+        chomp;
+        my $file     = $_;
+        my $rm_count = 1;
+        my $keyname;
+        for (@keylist) {
+            if ($file =~ /$_/) { $rm_count = 0; }
+        }
+        if ($rm_count == 1) {
+            unlink "$file";
+            if ($file =~ /$zpf\/(.*\.key)/) {
+                print " * $zone: Schluessel $1 entfernt \n";
+            }
+        }
+    }
+}
+
+sub end_ro {
+    our @end_ro_list;
+    our $master_dir;
+    our @new_serial;
+    my @content;
+
+    for (@end_ro_list) {
+        my $zone  = $_;
+        my $count = 0;
+        my @content;
+        my $last_key;
+
+        open(INDEX, "<$master_dir/$zone/.index.zsk");
+        @content = <INDEX>;
+        close(INDEX);
+
+        for (@content) {
+            $count++;
+            $last_key = $_;
+        }
+        if ($count > 1) {
+            open(INDEX, ">$master_dir/$zone/.index.zsk");
+            print INDEX $last_key;
+            close(INDEX);
+        }
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+        push @new_serial, $zone;
+    }
+}
+
+&read_conf;
+
+our %config;
+our @new_serial;       # liste fuer neuen serial
+our @begin_ro_list;    # liste mit zonen deren key-rollover beginnt
+our @end_ro_list;      # liste mit zonen deren key-rollover fertig ist
+our $master_dir      = $config{master_dir};
+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;
+&changed_zone;
+&sign_end;
+
+&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
+}
+
+if (@end_ro_list) {
+    &end_ro;      # eine rollover-end-squenz
+}
+
+if (@new_serial) {
+    &update_index;     # index zone aktuallisieren
+    &update_serial;    # serial aktuallisieren
+    &sign_zone;        # zone signieren
+}
+
+&file_entry;  # bearbeitet die file-eintraege der konfigurations-datei
+&mk_zone_conf; # konfiguration zusammenfuegen
+&server_reload; # server neu laden
+
+
+
+__END__
+
+=pod
+
+=head1 TITLE
+
+update-serial
+
+=head1 SYNTAX
+
+update-serial
+
+=head1 BESCHREIBUNG
+
+=cut
--- a/zone-ls	Tue Dec 21 15:47:40 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-#! /usr/bin/perl
-
-use strict;
-use warnings;
-use File::Basename;
-use FindBin;
-
-# liest die Konfiguration ein
-my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
-my %config;
-
-for ( grep {-f} @configs ) {
-    open( CONFIG, $_ ) or die "Can't open $_: $!\n";
-}
-
-unless ( seek( CONFIG, 0, 0 ) ) {
-    die "Can't open config (searched: @configs)\n";
-}
-
-while (<CONFIG>) {
-    chomp;
-    s/#.*//;
-    s/\t//g;
-    s/\s//g;
-    next unless length;
-    my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
-    $config{$cname} = $ccont;
-}
-close(CONFIG);
-
-my $master_dir = $config{master_dir};
-my $zone;
-my ( $info_zsk, $info_ksk, $info_kc, $info_end, $info_status );
-
-unless ( -d $master_dir and -r $master_dir ) {
-    die "$master_dir: $!\n";
-}
-
-printf "%-35s %-8s %1s/%1s %3s %7s\n", "Domain", "Status", "ZSK", "KSK",
-    "Used", "Sig-end";
-
-for my $dir ( glob "$master_dir/*" ) {
-
-    $zone = basename($dir);
-
-    # prueft mit dig nach der zone
-    $info_status = "OK";
-    for (`dig \@localhost $zone`) {
-        if (/root-servers/) {
-            $info_status = "FAILED";
-            last;
-        }
-    }
-
-    if ( not -f "$dir/.index.zsk" ) {
-        $info_zsk = $info_ksk = $info_kc = 0;
-        $info_end = "-";
-        next;
-    }
-
-    # prueft wie viele zsks genutzt werden
-    close(FILE);
-    open( FILE, $_ = "<$dir/.index.zsk" ) or die "Can't open $_: $!\n";
-    () = <FILE>;
-    $info_zsk = $.;
-
-    # prueft wie viele ksks genutzt werden
-    close(FILE);
-    open( FILE, $_ = "<$dir/.index.ksk" ) or die "Can't open $_: $!\n";
-    () = <FILE>;
-    $info_ksk = $.;
-
-    # prueft wie oft die schluessel zum signieren genutzt wurden
-    open( FILE, $_ = "<$dir/.keycounter" ) or die "Can't open $_: $!\n";
-    chomp( $info_kc = <FILE> );
-
-    # prueft das ablaufdatum
-    if ( !-f "$dir/$zone.signed" ) {
-        $info_end = "-";
-        next;
-    }
-
-    open( FILE, $_ = "<$dir/$zone.signed" ) or die "Can't open $_: $!\n";
-    while (<FILE>) {
-        $info_end = "$+{day}.$+{mon}.$+{year} $+{hour}:$+{min}"
-            if /RSIG.*SOA.*\s
-			(?<year>\d\d\d\d)
-			(?<mon>\d\d)
-			(?<day>\d\d)
-			(?<hour>\d\d)
-			(?<min>\d\d)\d+\s\(/ix;
-    }
-
-}
-continue {
-    printf "%-35s %-8s %1d/%1d %5d %19s\n", $zone, $info_status, $info_zsk,
-        $info_ksk, $info_kc,
-        $info_end;
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zone-ls.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,100 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use File::Basename;
+use FindBin;
+
+# liest die Konfiguration ein
+my @configs = ("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+my %config;
+
+for (grep { -f } @configs) {
+    open(CONFIG, $_) or die "Can't open $_: $!\n";
+}
+
+unless (seek(CONFIG, 0, 0)) {
+    die "Can't open config (searched: @configs)\n";
+}
+
+while (<CONFIG>) {
+    chomp;
+    s/#.*//;
+    s/\t//g;
+    s/\s//g;
+    next unless length;
+    my ($cname, $ccont) = split(/\s*=\s*/, $_, 2);
+    $config{$cname} = $ccont;
+}
+close(CONFIG);
+
+my $master_dir = $config{master_dir};
+my $zone;
+my ($info_zsk, $info_ksk, $info_kc, $info_end, $info_status);
+
+unless (-d $master_dir and -r $master_dir) {
+    die "$master_dir: $!\n";
+}
+
+printf "%-35s %-8s %1s/%1s %3s %7s\n", "Domain", "Status", "ZSK", "KSK",
+  "Used", "Sig-end";
+
+for my $dir (glob "$master_dir/*") {
+
+    $zone = basename($dir);
+
+    # prueft mit dig nach der zone
+    $info_status = "OK";
+    for (`dig \@localhost $zone`) {
+        if (/root-servers/) {
+            $info_status = "FAILED";
+            last;
+        }
+    }
+
+    if (not -f "$dir/.index.zsk") {
+        $info_zsk = $info_ksk = $info_kc = 0;
+        $info_end = "-";
+        next;
+    }
+
+    # prueft wie viele zsks genutzt werden
+    close(FILE);
+    open(FILE, $_ = "<$dir/.index.zsk") or die "Can't open $_: $!\n";
+    () = <FILE>;
+    $info_zsk = $.;
+
+    # prueft wie viele ksks genutzt werden
+    close(FILE);
+    open(FILE, $_ = "<$dir/.index.ksk") or die "Can't open $_: $!\n";
+    () = <FILE>;
+    $info_ksk = $.;
+
+    # prueft wie oft die schluessel zum signieren genutzt wurden
+    open(FILE, $_ = "<$dir/.keycounter") or die "Can't open $_: $!\n";
+    chomp($info_kc = <FILE>);
+
+    # prueft das ablaufdatum
+    if (!-f "$dir/$zone.signed") {
+        $info_end = "-";
+        next;
+    }
+
+    open(FILE, $_ = "<$dir/$zone.signed") or die "Can't open $_: $!\n";
+    while (<FILE>) {
+        $info_end = "$+{day}.$+{mon}.$+{year} $+{hour}:$+{min}"
+          if /RSIG.*SOA.*\s
+			(?<year>\d\d\d\d)
+			(?<mon>\d\d)
+			(?<day>\d\d)
+			(?<hour>\d\d)
+			(?<min>\d\d)\d+\s\(/ix;
+    }
+
+}
+continue {
+    printf "%-35s %-8s %1d/%1d %5d %19s\n", $zone, $info_status, $info_zsk,
+      $info_ksk, $info_kc,
+      $info_end;
+}
+
--- a/zone-mk	Tue Dec 21 15:47:40 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use FindBin;
-
-if ( @ARGV < 2 ) {
-    print "usage: zone-mk kundennummer domain ... \n";
-    exit 1;
-}
-
-# oeffnet Konfigurations- und Templatefiles - relativ oder absolut
-my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
-my @templc = (
-    "$FindBin::Bin/templates/named.config",
-    "/etc/dnstools/templates/named.config"
-);
-my @templz = (
-    "$FindBin::Bin/templates/named.zone",
-    "/etc/dnstools/templates/named.zone"
-);
-my %config;
-
-for ( grep {-f} @configs ) {
-    open( CONFIG, $_ ) or die "Can't open $_: $!\n";
-}
-unless ( seek( CONFIG, 0, 0 ) ) {
-    die "Can't open config (searched: @configs)\n";
-}
-
-for ( grep {-f} @templc ) {
-    open( TEMPCONF, $_ ) or die "Can't open $_: $!\n";
-}
-unless ( seek( TEMPCONF, 0, 0 ) ) {
-    die "Can't open template (searched: @templc)\n";
-}
-
-for ( grep {-f} @templz ) {
-    open( TEMPZONE, $_ ) or die "Can't open $_: $!\n";
-}
-unless ( seek( TEMPZONE, 0, 0 ) ) {
-    die "Can't open template (searched: @templz)\n";
-}
-
-while (<CONFIG>) {
-    chomp;
-    s/#.*//;
-    s/\t//g;
-    s/\s//g;
-    next unless length;
-    my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
-    $config{$cname} = $ccont;
-}
-close(CONFIG);
-
-my $primary       = $config{primary};
-my $secondary     = $config{secondary};
-my $zone_conf_dir = $config{zone_conf_dir};
-my $master_dir    = $config{master_dir};
-my $customer      = shift @ARGV;
-chomp( my $primary_ip   = `dig +short $primary` );
-chomp( my $secondary_ip = `dig +short $secondary` );
-chomp( my $this_host    = `hostname -f` );
-chomp( my $this_ip      = `hostname -i` );
-chomp( my $this_domain  = `hostname -d` );
-chomp( my $time         = `date +%Y%m%d00` );
-chomp( my $start        = `date -I` );
-my $hostmaster = "hostmaster.$this_domain";
-
-unless ( -d $master_dir and -r $master_dir ) {
-    die "$master_dir: $!\n";
-}
-
-unless ( -d $zone_conf_dir and -r $zone_conf_dir ) {
-    die "$master_dir: $!\n";
-}
-
-# legt fuer jede domain in @ARGV ein verzeichnis in $master_dir an.
-# schreibt aus den angegebenen templates die dateien $zonefile und $config
-# in die entsprechenden verzeichnisse.
-for (@ARGV) {
-
-    chomp( my $domain = `idn --quiet "$_"` );
-    my $zonefile   = "$master_dir/$domain/$domain";
-    my $config     = "$zone_conf_dir/$domain";
-    my $utf8domain = "$_";
-
-    unless ( -d "$master_dir/$domain" ) {
-        `mkdir $master_dir/$domain`;
-    }
-
-    if ( -f $zonefile ) {
-        $zonefile =~ s#/.*/##;
-        print "$zonefile exists. Skipping $domain\n";
-        next;
-    }
-    if ( -f $config ) {
-        $config =~ s#/.*/##;
-        print "$config exists. Skipping $domain\n";
-        next;
-    }
-
-    print "$domain ($_) for $customer \n";
-
-    my @tempzone = <TEMPZONE>;
-    for (@tempzone) {
-        s#<start>#$start#;
-        s#<domain>#$domain#;
-        s#<time>#$time#;
-        s#<primary>#$primary#;
-        s#<secondary>#$secondary#;
-        s#<hostmaster>#$hostmaster#;
-        s#<customer>#$customer#;
-        s#<utf8domain>#$utf8domain#;
-    }
-
-    open( ZONEOUT, ">$zonefile" );
-    print ZONEOUT @tempzone;
-    close(ZONEOUT);
-
-    my @tempconf = <TEMPCONF>;
-    for (@tempconf) {
-        s#<domain>#$domain#;
-        s#<start>#$start#;
-        s#<customer>#$customer#;
-        s#<utf8domain>#$utf8domain#;
-        s#<file>#$master_dir/$domain/$domain#;
-        s#<primary_ip>#$primary_ip#;
-        s#<secondary_ip>#$secondary_ip#;
-    }
-
-    open( CONFOUT, ">$config" );
-    print CONFOUT @tempconf;
-    close(CONFOUT);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zone-mk.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,133 @@
+#!/usr/bin/perl 
+
+use warnings;
+use strict;
+use FindBin;
+
+if (@ARGV < 2) {
+    print "usage: zone-mk kundennummer domain ... \n";
+    exit 1;
+}
+
+# oeffnet Konfigurations- und Templatefiles - relativ oder absolut
+my @configs = ("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+my @templc = (
+    "$FindBin::Bin/templates/named.config",
+    "/etc/dnstools/templates/named.config"
+);
+my @templz =
+  ("$FindBin::Bin/templates/named.zone", "/etc/dnstools/templates/named.zone");
+my %config;
+
+for (grep { -f } @configs) {
+    open(CONFIG, $_) or die "Can't open $_: $!\n";
+}
+unless (seek(CONFIG, 0, 0)) {
+    die "Can't open config (searched: @configs)\n";
+}
+
+for (grep { -f } @templc) {
+    open(TEMPCONF, $_) or die "Can't open $_: $!\n";
+}
+unless (seek(TEMPCONF, 0, 0)) {
+    die "Can't open template (searched: @templc)\n";
+}
+
+for (grep { -f } @templz) {
+    open(TEMPZONE, $_) or die "Can't open $_: $!\n";
+}
+unless (seek(TEMPZONE, 0, 0)) {
+    die "Can't open template (searched: @templz)\n";
+}
+
+while (<CONFIG>) {
+    chomp;
+    s/#.*//;
+    s/\t//g;
+    s/\s//g;
+    next unless length;
+    my ($cname, $ccont) = split(/\s*=\s*/, $_, 2);
+    $config{$cname} = $ccont;
+}
+close(CONFIG);
+
+my $primary       = $config{primary};
+my $secondary     = $config{secondary};
+my $zone_conf_dir = $config{zone_conf_dir};
+my $master_dir    = $config{master_dir};
+my $customer      = shift @ARGV;
+chomp(my $primary_ip   = `dig +short $primary`);
+chomp(my $secondary_ip = `dig +short $secondary`);
+chomp(my $this_host    = `hostname -f`);
+chomp(my $this_ip      = `hostname -i`);
+chomp(my $this_domain  = `hostname -d`);
+chomp(my $time         = `date +%Y%m%d00`);
+chomp(my $start        = `date -I`);
+my $hostmaster = "hostmaster.$this_domain";
+
+unless (-d $master_dir and -r $master_dir) {
+    die "$master_dir: $!\n";
+}
+
+unless (-d $zone_conf_dir and -r $zone_conf_dir) {
+    die "$master_dir: $!\n";
+}
+
+# legt fuer jede domain in @ARGV ein verzeichnis in $master_dir an.
+# schreibt aus den angegebenen templates die dateien $zonefile und $config
+# in die entsprechenden verzeichnisse.
+for (@ARGV) {
+
+    chomp(my $domain = `idn --quiet "$_"`);
+    my $zonefile   = "$master_dir/$domain/$domain";
+    my $config     = "$zone_conf_dir/$domain";
+    my $utf8domain = "$_";
+
+    unless (-d "$master_dir/$domain") {
+        `mkdir $master_dir/$domain`;
+    }
+
+    if (-f $zonefile) {
+        $zonefile =~ s#/.*/##;
+        print "$zonefile exists. Skipping $domain\n";
+        next;
+    }
+    if (-f $config) {
+        $config =~ s#/.*/##;
+        print "$config exists. Skipping $domain\n";
+        next;
+    }
+
+    print "$domain ($_) for $customer \n";
+
+    my @tempzone = <TEMPZONE>;
+    for (@tempzone) {
+        s#<start>#$start#;
+        s#<domain>#$domain#;
+        s#<time>#$time#;
+        s#<primary>#$primary#;
+        s#<secondary>#$secondary#;
+        s#<hostmaster>#$hostmaster#;
+        s#<customer>#$customer#;
+        s#<utf8domain>#$utf8domain#;
+    }
+
+    open(ZONEOUT, ">$zonefile");
+    print ZONEOUT @tempzone;
+    close(ZONEOUT);
+
+    my @tempconf = <TEMPCONF>;
+    for (@tempconf) {
+        s#<domain>#$domain#;
+        s#<start>#$start#;
+        s#<customer>#$customer#;
+        s#<utf8domain>#$utf8domain#;
+        s#<file>#$master_dir/$domain/$domain#;
+        s#<primary_ip>#$primary_ip#;
+        s#<secondary_ip>#$secondary_ip#;
+    }
+
+    open(CONFOUT, ">$config");
+    print CONFOUT @tempconf;
+    close(CONFOUT);
+}
--- a/zone-rm	Tue Dec 21 15:47:40 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use File::Path;
-use FindBin;
-
-# liest die Konfiguration ein
-my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" );
-my %config;
-
-foreach ( grep {-f} @configs ) {
-    open( CONFIG, $_ ) or die "Can't open $_: $!\n";
-}
-
-unless ( seek( CONFIG, 0, 0 ) ) {
-    die "Can't open config (searched: @configs)\n";
-}
-
-while (<CONFIG>) {
-    chomp;
-    s/#.*//;
-    s/\t//g;
-    s/\s//g;
-    next unless length;
-    my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 );
-    $config{$cname} = $ccont;
-}
-close(CONFIG);
-
-my $master_dir = $config{"master_dir"};
-my $conf_dir   = $config{"zone_conf_dir"};
-
-for (@ARGV) {
-    chomp( my $zone = `idn --quiet "$_"` );
-
-    if ( -d "$master_dir/$zone" ) {
-        rmtree "$master_dir/$zone/"
-            and print "zone-dir for $zone removed\n";
-    }
-    else {
-        print "$master_dir/$zone: $!\n";
-    }
-
-    if ( -e "$conf_dir/$zone" ) {
-        unlink "$conf_dir/$zone"
-            and print "configuration-file for $zone removed\n";
-    }
-    else {
-        print "$conf_dir/$zone: $!\n";
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zone-rm.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,52 @@
+#!/usr/bin/perl 
+
+use warnings;
+use strict;
+use File::Path;
+use FindBin;
+
+# liest die Konfiguration ein
+my @configs = ("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+my %config;
+
+foreach (grep { -f } @configs) {
+    open(CONFIG, $_) or die "Can't open $_: $!\n";
+}
+
+unless (seek(CONFIG, 0, 0)) {
+    die "Can't open config (searched: @configs)\n";
+}
+
+while (<CONFIG>) {
+    chomp;
+    s/#.*//;
+    s/\t//g;
+    s/\s//g;
+    next unless length;
+    my ($cname, $ccont) = split(/\s*=\s*/, $_, 2);
+    $config{$cname} = $ccont;
+}
+close(CONFIG);
+
+my $master_dir = $config{"master_dir"};
+my $conf_dir   = $config{"zone_conf_dir"};
+
+for (@ARGV) {
+    chomp(my $zone = `idn --quiet "$_"`);
+
+    if (-d "$master_dir/$zone") {
+        rmtree "$master_dir/$zone/"
+          and print "zone-dir for $zone removed\n";
+    }
+    else {
+        print "$master_dir/$zone: $!\n";
+    }
+
+    if (-e "$conf_dir/$zone") {
+        unlink "$conf_dir/$zone"
+          and print "configuration-file for $zone removed\n";
+    }
+    else {
+        print "$conf_dir/$zone: $!\n";
+    }
+}