--- 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