From 5a432a75a87ce8f9f653a44e1d10680e50dce806 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Sat, 24 Jan 2026 16:44:21 -0500 Subject: [PATCH] default to the correct server --- bin/sync-slave | 62 +++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/bin/sync-slave b/bin/sync-slave index d842e79..0b82202 100755 --- a/bin/sync-slave +++ b/bin/sync-slave @@ -4,24 +4,34 @@ use strict; use warnings; use Martnet::DDNS; use File::Temp qw/tempfile/; +use Getopt::Long qw(GetOptions); -# Optional positional "force" flag (legacy behavior): -# sync-slave [force] -# If more than 10 changes would be made, the script will refuse unless force is set. +# Defaults +my $server = 'mister-dns.martnet.com'; + +# Optional flags +# --server Override control-plane master +# force Legacy positional flag +my $opt_server; +GetOptions( + 'server=s' => \$opt_server, +) or die "Usage: sync-slave [--server host] [force]\n"; + +$server = $opt_server if defined $opt_server; + +# Optional positional "force" flag (legacy behavior) my $force = shift; -my $ddns = Martnet::DDNS->new(); +my $ddns = Martnet::DDNS->new(server => $server); -# Pull all control-plane entries, then filter out datasets that are not zones. -# In the new model, _config is metadata and must never appear in slave zone stanzas. -# Also guard against any malformed 'master' that could result in invalid BIND config. +# Pull all control-plane entries, excluding metadata (_config) my @vh_all = $ddns->get(); my @vh = grep { $_->{type} ne '_config' && defined($_->{zone}) && $_->{zone} ne '' && defined($_->{master}) && $_->{master} ne '' && - $_->{master} !~ /^\s*[\{\[]/ # never allow JSON into masters { ... } + $_->{master} !~ /^\s*[\{\[]/ } @vh_all; my %vhh = map { $_->{zone} => 1 } @vh; @@ -29,7 +39,7 @@ my %vhh = map { $_->{zone} => 1 } @vh; my @all = parse_slavefile("/etc/bind/martnet.slave.zones.9"); my %allh = all_zones_hash(@all); -# For each managed zone, see if it's already present with the same masters list. +# Detect changes my $changecount = 0; foreach my $i (@vh) { unless (contains_zone($i, @all)) { @@ -38,7 +48,6 @@ foreach my $i (@vh) { } } -# For each zone currently in the file, see if it's still managed. foreach my $z (keys %allh) { $changecount++ unless ($vhh{$z}); } @@ -54,15 +63,12 @@ exit 0; sub parse_slavefile { my ($f) = @_; - my @ret; open(my $fh, $f) || die "Can't open $f: $!"; while (<$fh>) { - # Example generated line: - # zone "example.com" { type slave; file "..."; masters { 1.2.3.4;5.6.7.8; }; allow-notify {...}; }; - if (/^zone\s+\"([^\"]+)\"\s+\{.+masters\s?\{\s?([^\}]+);\s?\};/) { - push(@ret, { zone => $1, master => $2 }); + if (/^zone\s+"([^"]+)"\s+\{.*masters\s+\{\s*([^}]+);\s*\}/) { + push @ret, { zone => $1, master => $2 }; } } close $fh; @@ -77,23 +83,27 @@ sub do_rewrite { foreach my $i (sort { $a->{zone} cmp $b->{zone} } @vh) { die "No master(s) found for slave zone $i->{zone}" - unless defined($i->{master}) && $i->{master} ne '' && $i->{master} !~ /^\s*[\{\[]/; + unless defined($i->{master}) && $i->{master} ne ''; - print $fh "zone \"$i->{zone}\" { type slave; file \"/var/cache/bind/db.$i->{zone}\"; masters { $i->{master}; }; allow-notify {key \"notify-key\";}; };\n"; + print $fh + "zone \"$i->{zone}\" { " + . "type slave; " + . "file \"/var/cache/bind/db.$i->{zone}\"; " + . "masters { $i->{master}; }; " + . "allow-notify { key \"notify-key\"; }; " + . "};\n"; } close $fh; print "Installing new slave host list\n"; my $dest = "/etc/bind/martnet.slave.zones.9"; - my ($old_uid, $old_gid) = (0, 0); - + my ($uid, $gid) = (0, 0); if (-e $dest) { - $old_uid = (lstat $dest)[4]; - $old_gid = (lstat $dest)[5]; + ($uid, $gid) = (lstat $dest)[4,5]; } - system("install -o $old_uid -g $old_gid $path $dest") == 0 + system("install -o $uid -g $gid $path $dest") == 0 or die "install failed: $?"; print "Reloading DNS files\n"; @@ -103,21 +113,15 @@ sub do_rewrite { sub all_zones_hash { my (@zl) = @_; - my %ret; - foreach my $i (@zl) { - $ret{$i->{zone}}++; - } + $ret{$_->{zone}}++ for @zl; return %ret; } sub contains_zone { my ($zone, @zl) = @_; - foreach my $i (@zl) { if ($i->{zone} eq $zone->{zone}) { - print "m: '$i->{master}' ne '$zone->{master}'\n" - unless ($i->{master} eq $zone->{master}); return 1 if ($i->{master} eq $zone->{master}); } }