2023-05-07 13:54:20 +02:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
#
|
2023-05-08 19:09:30 +02:00
|
|
|
# Copyright (c) 2023 Mischa Peters <mischa @ openbsd.amsterdam>
|
|
|
|
#
|
|
|
|
# Permission to use, copy, modify, and distribute this software for any
|
|
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
|
|
# copyright notice and this permission notice appear in all copies.
|
|
|
|
#
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
#
|
2023-05-07 13:54:20 +02:00
|
|
|
use 5.024;
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use autodie;
|
|
|
|
use Fcntl qw(:flock);
|
|
|
|
use File::Basename;
|
|
|
|
use File::Copy;
|
|
|
|
use POSIX qw(strftime);
|
|
|
|
use Net::IP;
|
|
|
|
|
|
|
|
my $ipv4_range = new Net::IP("46.23.80.0/20");
|
|
|
|
my $ipv6_range = new Net::IP("2a03:6000::/29");
|
|
|
|
my $nsd = "/var/nsd/zones/master";
|
|
|
|
my $zonefile = "high5.nl";
|
|
|
|
my $workdir = dirname($0);
|
|
|
|
my $serial;
|
|
|
|
my $serial_prev;
|
|
|
|
|
|
|
|
opendir my $dh, "${workdir}/records";
|
|
|
|
while (my $file = readdir $dh) {
|
|
|
|
chomp $file;
|
|
|
|
next if $file =~ /^\./;
|
|
|
|
|
|
|
|
open my $fh_ptr, '<', "${workdir}/records/$file";
|
|
|
|
my $replace = <$fh_ptr>;
|
|
|
|
chomp $replace;
|
|
|
|
my ($_hostname, $_in, $_a, $match) = split(' ', $replace, 4);
|
|
|
|
close $fh_ptr;
|
|
|
|
|
|
|
|
if (qx(rlog ${nsd}/${zonefile} | grep 'locked by') =~ m/locked by/) {
|
|
|
|
_log("$file zone file locked, trying again later...");
|
|
|
|
next;
|
|
|
|
} else {
|
|
|
|
open my $fh_in, '<', "${nsd}/$zonefile";
|
|
|
|
open my $fh_out, '>', "${workdir}/zonefiles/$zonefile";
|
|
|
|
while (my $row = <$fh_in>) {
|
|
|
|
chomp $row;
|
|
|
|
if ($row =~ m/^\s*(\d+)\s*; serial$/) {
|
|
|
|
$serial = $serial_prev = $1;
|
|
|
|
my $timestamp = strftime ("%Y%m%d", localtime()) . "01";
|
|
|
|
if ($serial < $timestamp) {
|
|
|
|
$serial = $timestamp;
|
|
|
|
} else {
|
|
|
|
$serial++;
|
|
|
|
}
|
|
|
|
$row =~ s/${serial_prev}/${serial}/;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($row =~ m/^[0-9a-z-]+\s+IN\s+A{1,4}\s+${match}( ;.*)?$/) {
|
|
|
|
if ($1) {
|
|
|
|
my $comment = $1;
|
|
|
|
$row =~ s/^.*\s+${match}.*$/${replace}${comment}/;
|
|
|
|
} else {
|
|
|
|
$row =~ s/^.*\s+${match}.*$/${replace}/;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
print $fh_out "$row\n";
|
|
|
|
}
|
|
|
|
close $fh_in;
|
|
|
|
close $fh_out;
|
|
|
|
|
|
|
|
(my $diff = qx(diff ${nsd}/${zonefile} ${workdir}/zonefiles/${zonefile} | wc -l)) =~ s/^\s*(.*?)\s*$/$1/;
|
|
|
|
if ($diff == 8) {
|
|
|
|
_log("$file diff within limits ($diff), $serial_prev -> $serial");
|
|
|
|
copy("${nsd}/${zonefile}", "${workdir}/zonefiles-archive/${zonefile}-${serial}");
|
|
|
|
qx(co -q -l ${nsd}/${zonefile});
|
|
|
|
copy("${workdir}/zonefiles/${zonefile}", "${nsd}/${zonefile}");
|
|
|
|
qx(ci -q -u -m"updated for ${file}" ${nsd}/${zonefile});
|
|
|
|
move("${workdir}/records/${file}", "${workdir}/records-archive/${file}-${serial}");
|
|
|
|
|
|
|
|
qx(${workdir}/../bin/auto-sign.sh ${zonefile});
|
|
|
|
qx(rcctl reload nsd);
|
|
|
|
qx(rdist -f /etc/Distfile) if (-r '/etc/Distfile');
|
|
|
|
|
|
|
|
open my $fh_email, '|-', '/usr/sbin/sendmail -t';
|
|
|
|
print $fh_email "To: ard\@high5.nl\n";
|
|
|
|
print $fh_email "From: ard\@high5.nl\n";
|
|
|
|
print $fh_email "Subject: High5! A(AAA) $zonefile\n";
|
|
|
|
print $fh_email "Content-Type: text/plain; charset=utf-8\n\n";
|
|
|
|
print $fh_email "$serial_prev -> $serial\n$file\n$replace\n";
|
|
|
|
close $fh_email;
|
|
|
|
} else {
|
|
|
|
_log("$file diff is outside limits ($diff), cleaning up");
|
|
|
|
unlink("${workdir}/records/${file}", "${workdir}/zonefiles/${zonefile}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _log {
|
|
|
|
my ($msg) = @_;
|
|
|
|
open my $fh, '>>', '/var/log/ard.log';
|
|
|
|
flock $fh, LOCK_EX;
|
|
|
|
print $fh sprintf("%s %s: %s \n", strftime("%b %d %H:%M:%S", localtime), basename($0), $msg);
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
|