--- a/master_watcher Tue Dec 24 00:15:01 2002 +0000
+++ b/master_watcher Tue Dec 24 02:05:56 2002 +0000
@@ -3,7 +3,7 @@
Usage: $ME [options]
-l --logfile=s Name of the logfile we've to read [$opt_logfile]
-z --zonesdir=s Where the named.conf's are expected [$opt_zonesdir]
- -u --[no]update Update the "masters"-entries [$opt_update]
+ -u --[no]update Update the \"masters\"-entries [$opt_update]
-f --[no]follow Follow the end of the logfile [$opt_follow]
-d --[no]debug extra debug output [$opt_debug]
-h --help This text [$opt_help]
@@ -68,10 +68,9 @@
my $opt_debug = 0;
my $naptime = 60;
-my $inode = 0;
-sub updateFile($@);
+sub updateFile($$$);
sub debug($;@) { syslog(LOG_DEBUG, "DEBUG " . shift @_, @_) if $opt_debug; }
MAIN: {
@@ -95,9 +94,8 @@
}
open (LOGFILE, $_ = "<$opt_logfile") or die "Can't open $_: $!\n";
- $inode = (LOGFILE->stat)[1];
for (;;) {
- my (%masters, my %missing);
+ my (%masters, %missing, %nomasters);
while (<LOGFILE>) {
my ($domain, $ip);
@@ -130,6 +128,7 @@
debug("Missing file for $domain\n");
$missing{$domain} = 1;
+ next;
};
# Wenn wir ein "... loaded" finden, dann fehlt das File nicht gänzlich!
@@ -139,15 +138,29 @@
debug("Missing file for $domain is not longer missing\n");
delete $missing{$domain};
+ next;
+ };
+
+ /\[([\d.]+)\] not authoritative for (\S+), SOA/ and do {
+ my ($master, $domain) = ($1, $2);
+ next if exists $nomasters{$domain}->{$master};
+
+ debug "$master isn't a auth. master for $domain\n";
+ $masters{$domain}->{$master} = 1; # sieht blöd aus, wird aber gebraucht,
+ # weil wir nur die bearbeiten, die einen
+ # master haben
+ $nomasters{$domain}->{$master} = 1;
+ next;
};
}
# Jetzt sind wir erstmal durch und verarbeiten alles
my $changed = 0;
foreach my $domain (sort ($opt_update ? keys %masters : keys %missing)) {
- $changed += updateFile($domain, keys %{$masters{$domain}});
+ $changed += updateFile($domain, [keys %{$masters{$domain}}], [keys %{$nomasters{$domain}}]);
delete $masters{$domain};
delete $missing{$domain} if exists $missing{$domain};
+ delete $nomasters{$domain} if exists $nomasters{$domain};
}
debug "$changed changes.";
@@ -163,59 +176,72 @@
}
last if !$opt_follow;
- debug("Sleeping for $naptime seconds\n");
+ syslog LOG_INFO, "Sleeping for $naptime seconds\n";
sleep $naptime;
- if ((LOGFILE->stat())[1] != $inode) {
+ if ((LOGFILE->stat())[1] != (stat($opt_logfile))[1]) {
# new file to follow
syslog(LOG_NOTICE, "Logfile changed, re-open it.\n");
open(LOGFILE, $_ = "<$opt_logfile")
or die "Can't open $_: $!\n";
- $inode = (LOGFILE->stat())[1];
} else {
LOGFILE->clearerr();
}
}
}
-sub updateFile($@)
+sub updateFile($$$)
{
local $_;
- my $domain = shift;
- my %new_masters = map { $_, 1 } @_;
- my %old_masters = ();
+ my $domain = $_[0];
+ my @new_masters = @{$_[1]};
+ my @no_masters = @{$_[2]};
+
+ my %masters = ();
my $masters;
+
my $file = "$opt_zonesdir/$domain";
+ debug "updateFile: $domain, @new_masters, @no_masters\n";
+
if (-f $file) {
# Das File ist also schon da, wir müssen nur mal gucken, ob die Master,
# von denen wir ein NOTIFY erhalten haben, auch in unserer Datei stehen.
- # Vorerst entfernen wir keinen Master, wir fügen lediglich welche hinzu,
- # wenn Sie noch nicht dabei sind.
#
open (F, $_ = "+<$file") or die "Can't open $_: $!\n";
flock(F, LOCK_EX); seek(F, 0, 0);
$_ = join "", <F>;
- # Liste der Master raussuchen
+ # Liste der Master raussuchen, darus noch die löschen, die uns
+ # die Mitarbeit verweigert haben..
/^(\s*masters\s*{\s*)(.*?);(\s*}\s*;)(\s*\/\/.*?\n)/ims;
- %old_masters = map { $_, 1 } split/\s*;\s*/, $2;
+ %masters = map { $_, 1 } split/\s*;\s*/, $2;
+ $masters = %masters; # für den späteren Vergleich
- # Aus den neuen löschen wir die, die bereits bekannt sind
- delete @new_masters{keys %old_masters};
+ # noch unsere neuen hinzufügen...
+ @masters{@new_masters} = map { 1 } @new_masters;
- # Wenn nun noch welche übring sind, dann müssen wir diese
- # mit eintragen. Ansonsten haben wir fertig.
- if (not %new_masters) {
- debug("Uptodate file for $domain\n");
+ # nun die weg, die sich nicht zuständig fühlen
+ delete @masters{@no_masters};
+
+ # Wenn sich nach alldem nichts verändert hat, haben wir fertig.
+ if ($masters eq %masters) {
+ debug("File is up-to-date for $domain\n");
syslog(LOG_NOTICE, "No changes made for $domain (no \"loaded\" seen, defective master?)\n")
unless $opt_update;
close(F);
return 0;
}
- syslog(LOG_NOTICE, "Updated masters list for $domain\n");
- $masters = join ";", keys %old_masters, keys %new_masters;
+ if (not %masters) {
+ syslog LOG_NOTICE, "REMOVING $file (empty masters list)\n";
+ close F;
+ unlink $file;
+ return 1;
+ }
+
+ $masters = join ";", keys %masters;
+ syslog(LOG_NOTICE, "Updated masters ($masters) list for $domain\n");
s/^(\s*masters\s*{\s*)(.*?);(\s*}\s*;)/$1$masters;$3/ims;
truncate(F, 0);
@@ -228,7 +254,15 @@
my $date = localtime();
- $masters = join "; ", keys %new_masters;
+ my %new_masters = map { $_, 1 } @new_masters;
+ delete @new_masters{@no_masters};
+
+ if (not %new_masters) {
+ syslog LOG_INFO, "not creating $file (empty masters list)\n";
+ return 0;
+ }
+
+ $masters = join "; ", @new_masters;
-d $opt_zonesdir or mkpath($opt_zonesdir, 0, 0755);