#!/usr/bin/perl use warnings; use strict; use Getopt::Long; use Net::DNS::Resolver; my $cfg; GetOptions('config:s' => \$cfg); my %file2zone; my $res; if ($cfg) { # XXX - this is very simplistic open(my $fh, '<', $cfg) or die "cannot open $cfg: $!"; my $currentzone; while (<$fh>) { if (/zone "(.*?)"/) { $currentzone = $1; } elsif (m{file ".*/(.*)"}) { $file2zone{$1} = $currentzone; } } $res = Net::DNS::Resolver->new(); } for my $f (@ARGV) { my $maxserial = 0; if (my $zone = $file2zone{$f}) { my $reply = $res->send($zone, 'NS'); my @nsnames; for my $ans ($reply->answer) { push @nsnames, $ans->nsdname; } my @nsips; for (@nsnames) { my $reply = $res->send($_, 'A'); for my $ans ($reply->answer) { push @nsips, $ans->address if $ans->type eq 'A'; } } for (@nsips) { $res->nameservers($_); my $reply = $res->send($zone, 'SOA'); for my $ans ($reply->answer) { if ($ans->type eq 'SOA') { # XXX assume no wraparound if ($ans->serial > $maxserial) { $maxserial = $ans->serial; } } } } } open (my $in, '<', "$f") or die "cannot open $f: $!"; open (my $out, '>', "$f.new") or die "cannot open $f.new: $!"; while (<$in>) { if (/(.*\bSOA\b.*?)(\d+)( \d+ \d+ \d+ \d+)/) { my $serial = $2; $maxserial = $serial if ($serial > $maxserial); $maxserial++; print $out "$1$maxserial$3\n"; } else { print $out $_; } } close($out) or die "cannot close $f.new: $!"; rename "$f.new", $f || die "cannot rename $f.new to $f: $!"; }