#!/usr/bin/perl $base= "/var/named"; $conf= "$base/conf"; $etcfile= "/etc/named/zones-rgc"; $check= 1; $progress= 1; while ($ARGV[0] =~ m/^\-/) { $_= shift @ARGV; last if m/^\-\-?$/; while (m/^\-./) { if (s/^\-f/-/) { $usage=0; $check=0; $install++; } elsif (s/^\-y/-/) { $usage=0; $check=1; $install++; } elsif (s/^\-n/-/) { $usage=0; $check=1; $install=0; } elsif (s/^\-h/-/) { $hostdelg=1; $hostzone=0; } elsif (s/^\-z/-/) { $hostdelg=1; $hostzone=1; } elsif (s/^\-q/-/) { $progress=0; } else { $usage=1; break; } } } die "usage: named-conf-regen -f|-y|-n [-h|-z]\n". "operation modes:\n". " -f install without checking -ff and then ndc reload\n". " -y check and install -yy and then ndc reload\n". " -n check only\n". "additional options:\n". " -h check output from host -C\n". " -z check output from host -C and host -val\n". if $usage; beginfile('secondary.zones'); open E, "< $etcfile" or die "$0: open $etcfile: $!\n"; for (;;) { $!=0; defined $_= or die "$0: read $etcfile $!\n"; s/^\s+//; chomp; s/\s+$//; next if m/^\#/; last if m/^end$/; if (m/^myname\s+(\S.*\S)/) { @mynames= split /\s+/, $1; } elsif (m/^(secondary|backup|unoff)\s+(\S+)\s+([0-9. \t]+)$/) { $style= $1; $zone= $2; @servers= split /\s+/, $3; $file= "slave/$zone"; progress(); check(); } else { die "$0: $etcfile:$.: syntax error in \`$_'\n"; } } sub lookup ($$) { my ($type,$domain) = @_; my ($c,@result); defined($c=open ADH, "-|") or die "$0: fork adnshost: $!\n"; if (!$c) { exec 'adnshost','+Do','+Dt','+Dc','-Cf',"-t$type", '-',"$domain."; die "$0: exec adnshost: $!\n"; } @result= ; chomp @result; $!=0; close ADH; die "$0: lookup -t$type $domain failed $? $!\n" if $? or $!; return @result; } sub lookup1 ($$) { my ($type,$domain) = @_; my (@result)= lookup($type,$domain); @result==1 or die "$0: lookup -t$type $domain gave more than one RR\n"; return $result[0]; } sub check () { return unless $check; eval { $soa= lookup1('soa',$zone); $soa_origin=$soa; $soa_origin =~ s/ .*//; $soa_origin_addr= lookup1('a',$soa_origin); @zone_ns= lookup('ns-',$zone); @ok_sources= ($soa_origin_addr); $ok_sources_descr= "SOA ORIGIN $soa_origin [$soa_origin_addr]"; if ($style eq 'unoff' || $style eq 'backup') { for $zone_ns (@zone_ns) { @zone_ns_addrs= lookup('a',$zone_ns); push @ok_sources, @zone_ns_addrs; $ok_sources_descr.= ", NS $zone_ns [@zone_ns_addrs]"; } } for $server (@servers) { grep { $server eq $_ } @ok_sources or warn "secondarying from $server which is not ". "$ok_sources_desc\n"; } if ($style eq 'secondary') { grep { $zone_ns=$_, grep { $myname eq $_ } @mynames } @zone_n or warn "supposedly published secondary but we ". "(@mynames) are not published ($@zone_ns)\n"; } } check_after_eval(); # $superzone= $zone; $superzone =~ s/^[^\.]+\.//; # @super_ns= lookup('ns-',$zone); } eval { for $super_ns (@super_ns) { @deleg_ns= (); open DIG, "dig @$super_ns. -t ns +norecurse $zone." or die "$0: fork for dig: $!\n"; while () { split /\n/, lookup(" case "$style" in secondary|backup) if [ $meadvert = 0 ] then warning "$myname unlisted NS $nsnames" fi ;; unoff) if $meadvert = 0 then warning "$myname advertised NS $nsnames" fi ;; esac addrs='' for ns in $names do set -e; a="`host -t a \"$ns\".`"; set +e taddrs="`echo \" $a\" | expand | sed -n ' 1s/^ // s/^[^ ][^ ]* *A *\([0-9][.0-9]*\)/\1/p '`" equlines "A $ns" "$a" "$taddrs" addrs="$addrs $taddrs" done fi cat <) { $zone= $f; $zone =~ s/_db$//; for f in $zones do zone="`echo $f | sed -e 's/_db$//'`" cat < $toopen" or die "$0: begin $currentfile_opened: $!\n"; } endfile () { close CFF or die "$0: close $currentfile_opened: $!\n"; push @files, $currentfile; } sub installfiles () { return unless $install; chdir $conf or die "$0: chdir $conf: $!\n"; for $f (@files) { rename "$f.new", $f or die "$0: install new $f: $!\n"; } } warning () { echo >&2 "$zone $style: $*" warnings=$[$warnings+1] } equlines () { if [ "x`echo \" $2\" | wc -l`" != "x`echo \" $3\" | wc -l`" ] then warning "$1 >$2|$3<" fi } checkhostout () { set +e hostout="`host $1 \"$zone\" 2>&1 >/dev/null $2 | egrep -v \ '^ \!\!\! .* SOA primary .* is not advertised via NS$'`" set -e if [ "x$hostout" = x ]; then return; fi if $hostfirstwarn then warning "warnings from host:" hostfirstwarn=0 fi echo >&2 "$hostout" } progress () { if $progress then echo -n "$zone $style " >&2 echo -ne '\r' >&2 fi } myname='' if [ $warnings != 0 ] then echo >&2 "$warnings warnings " fi installfiles