So koennte das jetzt gehen
authorheiko
Wed, 30 Nov 2005 06:55:20 +0000
changeset 11 d1dd256c037a
parent 10 8f7ba479860c
child 12 2a605c25d2c5
So koennte das jetzt gehen
Makefile
dns-autoslave
dns-autoslave.conf.ex
local.pm.ex
rc.dns-autoslave
--- a/Makefile	Mon Nov 28 13:11:11 2005 +0000
+++ b/Makefile	Wed Nov 30 06:55:20 2005 +0000
@@ -8,9 +8,8 @@
 
 rcdir = /etc/init.d/
 
-install:
+stow:
 	install -m 0755 -d $(sbindir)
 	install -m 0755 -d $(rcdir)
 	install -m 0755 $(SCRIPT) $(sbindir)/
-	install -m 0755 $(RC) $(rcdir)/
 	stow -d /usr/local/stow -vR $(p)
--- a/dns-autoslave	Mon Nov 28 13:11:11 2005 +0000
+++ b/dns-autoslave	Wed Nov 30 06:55:20 2005 +0000
@@ -8,24 +8,24 @@
 use File::Basename;
 use Net::Pcap;
 use Net::DNS::Packet;
+use Fcntl ":flock";
 use AppConfig;
 
 # Es kommen Zeilen
 # add slave domain.com
 use constant ME => basename $0;
-use constant CF_FILE => "/etc/".ME.".conf";
+use constant CF_FILE => "/etc/".ME."/".ME.".conf";
+use constant LIB_DIR => "/etc/".ME;
 
 use constant CONFIG => (
     { CASE => 1 },
     dev =>	{ ARGS => "=s", DEFAULT => "eth0", ALIAS => "interface" },
     filter =>	{ ARGS => "=s", DEFAULT => "udp and src host (%accept) and dst port domain" },
     accept =>	{ ARGS => "=s" },
-
-    cmd =>	{ ARGS => "=s", DEFAULT => "/usr/local/sbin/add-slave" },
+    pid =>	{ ARGS => "=s",	DEFAULT => "/var/run/".ME.".pid" },
 );
 
 sub process($$$);
-sub createZone($$$);
 
 openlog(ME, LOG_PERROR | LOG_NDELAY | LOG_PID, LOG_DAEMON);
 $SIG{__DIE__} = sub { die @_ if $^S; syslog(LOG_ERR, shift, @_); exit 1; };
@@ -43,6 +43,11 @@
     s/%accept/join " or ", split " ", $Cf->accept/e;
     $Cf->filter($_);
 
+    require lib;
+    import lib LIB_DIR;
+    require "local.pm";
+    
+
     my $err;
     my ($net, $mask);
     my ($pcap, $filter);
@@ -52,6 +57,31 @@
     0 == Net::Pcap::compile($pcap, \$filter, $Cf->filter, 1, $mask) or die $@;
     Net::Pcap::setfilter($pcap, $filter);
 
+    ##
+    my $pidfile = $Cf->pid;
+    my $pid;
+    open(PID, "+>>$pidfile") or die "Can't open $pidfile: $!\n";
+    flock(PID, LOCK_EX) or die "Can't flock $pidfile: $!\n";
+    seek(PID, 0, 0) or die "Can't seek $pidfile: $!\n";
+    if (defined ($pid = <PID>)) {
+	chomp $pid;
+	die "Process $pid is running\n" if kill 0, $pid;
+    }
+    seek(PID, 0, 0);
+    truncate(PID, 0);
+
+    $pid = fork;
+    die "Can't fork: $!\n" if not defined $pid;
+
+    if ($pid) {
+	print PID "$pid\n";
+	warn "Child pid: $pid\n";
+	exit 0;
+    }
+
+    $SIG{TERM} = sub { warn "Exit.\n"; exit 0; };
+    close(STDIN); close(STDOUT); close(STDERR); close(PID);
+    $0 = ME." [capturing]";
     Net::Pcap::loop($pcap, -1, \&process, undef);
 }
 
@@ -104,16 +134,26 @@
 	next unless $q->qtype eq "SOA";
 
 	my $domain = $q->qname;
-	print "NOTIFY from $src about $domain";
+	my $msg = "NOTIFY from $src about $domain:";
 
-	print " OK\n" and next if exists $Seen{$domain};
-	print " OK(new)\n" and next if -f $Cf->zones . "/$domain" and $Seen{$domain} = time;
+	if (exists $Seen{$domain} && (time - $Seen{$domain} < 60) ) {
+	    warn "$msg OK(seen)\n";
+	    next;
+	}
 
-	print " Create....\n";
-	$ENV{ZONE} = $domain;
-	$ENV{SOURCE} = $src;
-	$ENV{DATE} = scalar localtime;
-	system $Cf->cmd;
+	if ((new Net::DNS::Resolver (recurse => 0))->query($domain, "SOA")) {
+	    $Seen{$domain} = time;
+	    warn "$msg OK(soa checked)\n";
+	    next;
+	}
+
+	if (local::addZone($domain, $src)) {
+	    warn "$msg ADDED", $@ ? "($@)" : "", "\n";
+	    next;
+	}
+
+	warn "ERROR ", $@ ? "($@)" : "", "\n";
+
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dns-autoslave.conf.ex	Wed Nov 30 06:55:20 2005 +0000
@@ -0,0 +1,2 @@
+accept = 192.168.7.2 \
+	 192.168.7.3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/local.pm.ex	Wed Nov 30 06:55:20 2005 +0000
@@ -0,0 +1,58 @@
+# Example
+# $Id$
+# $URL$
+
+# remove the next line if you know, what you're doing
+die "Sure?  You should adapt this file to your needs!";
+
+package local;
+
+# in:	zone name
+#       src ip
+# out:  0 failure ($@ contains message)
+#      !0 ok      ($@ may contain message)
+sub addZone($$) {
+    my ($zone, $src) = @_;
+
+    my $txt = <<__;
+// Autoadded %time by $0
+zone "$zone" IN {
+    type slave;
+    file "/var/cache/bind/slave/$zone";
+    masters { %masters; };
+    allow-query { any; };
+    allow-transfer { none; };
+};
+
+__
+
+    $txt =~ s/%time/scalar localtime/eg;
+    $txt =~ s/%masters/$src/g;
+
+    if (-f ($_ = "/etc/bind/zones.auto/$zone")) {
+	$@ = "$_ already exists";
+	return 0;
+    }
+
+    open(OUT, $_ = ">$_") or die "Can't open $_: $!\n";
+    print OUT $txt;
+
+    open(OUT, $_ = ">>/etc/bind/zones.all") or die "Can't open $_: $!\n";
+    print OUT $txt;
+
+    close OUT;
+
+    # return 0 == system("rndc reload");
+    local @ARGV = qw(/var/run/bind/run/named.pid);
+    chomp($_ = <>);
+    warn "Sending HUP to $_\n";
+    $@ = "Nameserver reloaded (HUP sent)";
+    kill "HUP", $_ and return 1;
+
+    $@ = "No process $_";
+    return 0;
+}
+	
+
+1;
+# vim:sts=4 sw=4 aw ai sm:
--- a/rc.dns-autoslave	Mon Nov 28 13:11:11 2005 +0000
+++ b/rc.dns-autoslave	Wed Nov 30 06:55:20 2005 +0000
@@ -1,31 +1,29 @@
-#! /bin/bash
+#! /bin/sh
+# $Id$
+# $URL$
 
-DAEMON=/usr/local/sbin/master_watcher
-PIDFILE=/var/run/master_watcher.pid
+DAEMON=/usr/local/sbin/dns-autoslave
+NAME=`basename $DAEMON`
 
 test -x $MASTER_WATCHER || exit 0
 
 case $1 in
 	
 	start)	
-		echo -n "Starting $DAEMON..."
-		start-stop-daemon --start --pid $PIDFILE --exec $DAEMON -- -f
-		echo " OK";
+		start-stop-daemon  -v --start --name $NAME --startas $DAEMON
 		;;
 		
 	stop)	
-		echo -n "Stopping $DAEMON..."
-		start-stop-daemon --stop --pid $PIDFILE
-		echo " OK";
+		start-stop-daemon -v --stop --retry 30 --name $NAME
 		;;
 		
-	restart) echo -n "Restarting $DAEMON..."
+	restart) echo "Restarting $NAME..."
 		$0 stop
 		$0 start
 		;;
 
 	*)
-		echo "Usage: /etc/init.d/$DAEMON {start|stop|restart}" >&2
+		echo "Usage: $0 {start|stop|restart}" >&2
 		exit 1			
 		;;
 esac