master_watcher
changeset 1 f1a025736621
child 3 2699119ec0ea
equal deleted inserted replaced
0:0c554cc52ba0 1:f1a025736621
       
     1 #! /usr/bin/perl -w
       
     2 my $USAGE = <<'#';
       
     3 Usage: $ME [options]
       
     4        -l --logfile=s   Name of the logfile we've to read [$opt_logfile]
       
     5        -d --dir=s       Where the named.conf's are expected [$opt_zonesdir]
       
     6        -u --[no]update  Update the "masters"-entries [$opt_update]
       
     7        -c --[no]create  Add newly appeared domains [$opt_create]
       
     8        -f --[no]follow  Follow the end of the logfile [$opt_follow]
       
     9        -h --help        This text [$opt_help]
       
    10 #
       
    11 # Es wird ein Verzeichnis geben, in diesem Verzeichnis liegt für 
       
    12 # *jede* Zone eine eigene Konfigurations-Datei.
       
    13 # Diese ganzen Konfigurationsdateien werden dann zusammengefaßt
       
    14 # und diese zusammengefaßte wird dem bind per "include" mitgeteilt.
       
    15 
       
    16 use strict;
       
    17 use File::Basename;
       
    18 use IO::Handle;
       
    19 use File::Path;
       
    20 use Getopt::Long;
       
    21 use Unix::Syslog qw/:macros :subs/;
       
    22 
       
    23 my $ME = basename $0;
       
    24 
       
    25 
       
    26 my %auth = (
       
    27     "212.172.233.34" => "pu.schlittermann.de",
       
    28     "212.80.235.130" => "pu2.schlittermann.de",
       
    29     "145.253.160.50" => "bastion.actech.de",
       
    30     "212.172.233.146" => "ns.flaemingnet.de",
       
    31     "212.172.127.34" => "mango.compot.com",
       
    32     "62.144.175.34" => "ns.add-on.de",	    
       
    33     "195.145.19.34" => "ns.datom.de",
       
    34 );
       
    35 
       
    36 $SIG{__DIE__} = sub { syslog(LOG_ERR, $_[0]); exit -1; };
       
    37 $SIG{__WARN__} = sub { syslog(LOG_WARNING, $_[0]); };
       
    38 
       
    39 my %seen;
       
    40 
       
    41 my $opt_help = 0;
       
    42 my $opt_logfile = "./syslog";
       
    43 my $opt_zonesdir = "./zones";
       
    44 my $opt_follow = 0;
       
    45 my $opt_create = 1;
       
    46 my $opt_update = 1;
       
    47 
       
    48 my $naptime = 1;
       
    49 
       
    50 
       
    51 sub updateFile($@);
       
    52 
       
    53 
       
    54 MAIN: {
       
    55 
       
    56 
       
    57     openlog($ME, LOG_PID | LOG_PERROR, LOG_DAEMON);
       
    58     syslog(LOG_NOTICE, "starting");
       
    59 
       
    60     GetOptions(
       
    61 	"help" => \$opt_help,
       
    62 	"logfile=s" => \$opt_logfile,
       
    63 	"follow!" => \$opt_follow,
       
    64 	"dir=s" => \$opt_zonesdir)
       
    65     or die "$ME: Bad Usage\n";
       
    66 
       
    67     if ($opt_help) {
       
    68 	print eval "\"$USAGE\"";
       
    69 	exit 0;
       
    70     }
       
    71 
       
    72     open (LOGFILE, $_ = "<$opt_logfile") or die "Can't open $_: $!\n";
       
    73     for (;;) {
       
    74 	my (%masters, my %missing);
       
    75 	while (<LOGFILE>) {
       
    76 	    
       
    77 	    my ($domain, $ip);
       
    78 	    
       
    79 	    # NOTIFY-Zeilen
       
    80 	    ($domain, $ip) = /NOTIFY.*?\((\S+?),.*?\[([\d.]+)\]/ and do {
       
    81 		if (not exists $auth{$ip}) {
       
    82 		    warn "notify for $domain from unauthorized ip $ip\n";
       
    83 		    next;
       
    84 		};
       
    85 		$masters{$domain}->{$ip} = 1;
       
    86 		next;
       
    87 	    };
       
    88 
       
    89 	    # NOTIFY for vergessene 
       
    90 	    /NOTIFY for "(\S+?)".*not one of our zones/ and do {
       
    91 		if (not exists $masters{$1}) {
       
    92 		    warn "skipping $1 (not authorized)\n";
       
    93 		    next;
       
    94 		}
       
    95 		$missing{$1} = 1;
       
    96 	    };
       
    97 	}
       
    98 
       
    99 	# Jetzt sind wir erstmal durch und verarbeiten alles
       
   100 
       
   101 	#foreach my $domain (sort keys %missing) {
       
   102 	    #updateFile($domain, keys %{$masters{$domain}});
       
   103 	    #delete $masters{$domain};
       
   104 	    #delete $missing{$domain};
       
   105 	#}
       
   106 
       
   107 	foreach my $domain (sort keys %masters) {
       
   108 	    updateFile($domain, keys %{$masters{$domain}});
       
   109 	    delete $masters{$domain};
       
   110 	    delete $missing{$domain} if exists $missing{$domain};
       
   111 	}
       
   112 
       
   113 	last if !$opt_follow;
       
   114 	sleep $naptime;
       
   115 	# seek(LOGFILE, 0, 1);
       
   116 	LOGFILE->clearerr();
       
   117     }
       
   118 }
       
   119 
       
   120 sub updateFile($@)
       
   121 {
       
   122     local $_;
       
   123     my $domain = shift;
       
   124     my $masters = join "; ", @_;
       
   125     my $file = "$opt_zonesdir/$domain";
       
   126 
       
   127     syslog(LOG_NOTICE, "Updating/Creating $file ($masters)\n");
       
   128     return;
       
   129 
       
   130     if (-f $file) {
       
   131 	open (IN, $_ = "<$file") or die "Can't open $_: $!\n";
       
   132 	# ein etwas anderer Versuch - noch nicht fertig
       
   133 	$_ = join "", <IN>;
       
   134 	close(IN); open(OUT, ">&STDOUT"); # Wenn's geht, dann in's File
       
   135 	s/(masters\s*{)(.*?)(};)/$1$2; $masters; $3/;
       
   136 	print OUT;
       
   137     }
       
   138     
       
   139     else {
       
   140 	open(OUT, $_ = ">$file") or die "Can't open $_: $!\n";
       
   141     
       
   142 	    print OUT <<_EOF_;
       
   143 // Autogenerated
       
   144 zone "$domain" {
       
   145     type slave;
       
   146     masters { $masters; };
       
   147     file "/etc/bind/slave/$domain";
       
   148     allow-query { any; };
       
   149     allow-transfer { none; };
       
   150     allow-update { none; };
       
   151 };
       
   152 _EOF_
       
   153     close OUT;
       
   154     }
       
   155     
       
   156     return;
       
   157 }
       
   158 	    
       
   159 
       
   160 # vim:sts=4 sw=4 aw ai sm: