#!/usr/bin/perl use strict; use warnings; use Martnet::DDNS; use File::Temp qw/tempfile/; my $force = shift; # a "force" flag, if the update is big my $ddns = Martnet::DDNS->new(); my @vh = $ddns->get(); my %vhh = map { $_->{zone} => 1 } @vh; my @all = parse_slavefile("/etc/bind/martnet.slave.zones.9"); my %allh = all_zones_hash(@all); use Data::Dumper; # For each virtual host, see if we've got it already my $changecount = 0; foreach my $i (@vh) { unless (contains_zone($i, @all)) { $changecount++; } } foreach my $i (keys %allh) { $changecount++ unless ($vhh{$i}); } die "Cowardly refusing to make a big update automatically [$changecount]" if ($changecount > 10 && !$force); if ($changecount) { do_rewrite(@vh); } exit 0; sub parse_slavefile { my ($f) = @_; my @ret; open(my $fh, $f) || die "Can't open $f: $!"; while (<$fh>) { if (/^zone\s+\"([^\"]+)\"\s+\{.+masters\s?\{\s?([^;]+);/) { push ( @ret, { zone => $1, master => $2 } ); } } return @ret; } sub do_rewrite { my (@vh) = @_; my ($fh, $path) = tempfile(); print "Differences found; rewriting slave file.\n"; foreach my $i (sort {$a->{zone} cmp $b->{zone}} @vh) { next if ($i->{type} eq '_dnssec'); print $fh "zone \"$i->{zone}\" { type slave; file \"/var/cache/bind/db.$i->{zone}\"; masters { $i->{master}; }; };\n"; } close $fh; print "Installing new slave host list\n"; system("install -o bind -g bind $path /etc/bind/martnet.slave.zones.9"); print "Reloading DNS files\n"; system("/usr/sbin/rndc reload"); } sub all_zones_hash { my (@zl) = @_; my %ret; foreach my $i (@zl) { $ret{$i->{zone}}++; } return %ret; } sub contains_zone { my ($zone, @zl) = @_; foreach my $i (@zl) { return 1 if ($i->{zone} eq $zone->{zone} && $i->{master} eq $zone->{master} ); } return 0; }