# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# with this program; if not, consult the Free Software Foundation's
+# website at www.fsf.org, or the GNU Project website at www.gnu.org.
use strict;
use IO::File;
$progress_fh $warn_fh $modifiers
%group2modcmd %group2used);
+$|=1;
$quis= $0; $quis =~ s,.*/,,;
$mode= '';
$slave_prefix= '';
$slave_suffix= '';
-use vars qw(@self_ns @self_soa @self_addr @forbid_addr @conv_glueless);
-@self_ns= @self_soa= @self_addr= @forbid_addr= ();
+use vars qw(@self_ns @self_soa @self_addr @forbid_addr @forbid_slave
+ @conv_glueless @indirect_glue);
+@self_ns= @self_soa= @self_addr= @forbid_addr= @forbid_slave= @indirect_glue= ();
@conv_glueless= qw(in-addr.arpa ip6.arpa ip6.int);
use vars qw(%zone_cfg @zone_cfg_list);
$mod,$dir,$prefix,$suffix,$subfile,$lprefix,$lsuffix,$zf);
local ($_);
- $fh= new IO::File $if,'r' or cfg_fail("open $if:\n $!");
+ $fh= new IO::File $if,'r';
+ unless ($fh) {
+ return if $! == &ENOENT;
+ cfg_fail("open $if:\n $!");
+ }
$before= '';
for (;;) {
if (!defined($_= <$fh>)) {
@self_soa= @self if $1 ne '-ns';
} elsif (m/^serverless\-glueless\s+(\S.*\S)/) {
@conv_glueless= split /\s+/, $1;
+ } elsif (m/^allow\-indirect\-glue\s+(\S.*\S)/) {
+ @indirect_glue= split /\s+/, $1;
} elsif (m/^self\-addr\s+([0-9. \t]+)/) {
@self_addr= split /\s+/, $1;
} elsif (m/^forbid\-addr(?:\s+([0-9. \t]+))?/) {
@forbid_addr= defined $1 ? split /\s+/, $1 : ();
+ } elsif (m/^forbid\-slave(?:\s+([0-9. \t]+))?/) {
+ @forbid_slave= defined $1 ? split /\s+/, $1 : ();
} elsif (m,^
primary\-dir (\W*)
\s+ (\S+)/([^/ \t]*)
return 0;
}
+sub zone_conf_settings ($$) {
+ my ($cfg,$zone) = @_;
+ my ($sfx,$aref);
+ foreach $sfx (qw(self_soa self_ns self_addr forbid_addr forbid_slave
+ conv_glueless indirect_glue)) {
+ { no strict 'refs'; $aref= [ @$sfx ]; }
+ @$aref or cfg_fail("failed to specify $sfx before zone")
+ if $sfx =~ m/^self/;
+ $cfg->{$sfx}= $aref;
+ }
+ foreach $sfx (qw(self_soa self_ns)) {
+ map { s/\*$/$zone/ } @{ $zone_cfg{$zone}{$sfx} };
+ }
+}
+
sub zone_conf ($$$$$@) {
my ($zone,$style,$sabbr,$mod,$file,@servers) = @_;
- my ($sfx,$aref);
$file= qualify("$slave_dir/$slave_prefix".$zone.$slave_suffix)
unless length $file;
if (!length $output) {
$zone_cfg{$zone}{'maildir'}= qualify($mail_state_dir);
$zone_cfg{$zone}{'mailmwarn'}= $mail_max_warnfreq;
}
- foreach $sfx (qw(self_soa self_ns self_addr forbid_addr conv_glueless)) {
- { no strict 'refs'; $aref= [ @$sfx ]; }
- @$aref or cfg_fail("failed to specify $sfx before zone")
- if $sfx =~ m/^self/;
- $zone_cfg{$zone}{$sfx}= $aref;
- }
- foreach $sfx (qw(self_soa self_ns)) {
- map { s/\*$/$zone/ } @{ $zone_cfg{$zone}{$sfx} };
- }
+ zone_conf_settings($zone_cfg{$zone}, $zone);
$zone_cfg{$zone}{'output'}= $output;
push @zone_cfg_list, $zone;
}
local ($zone,$cfg);
foreach $zone (@zones) {
- $cfg= $zone_cfg{$zone} || {
- 'style_p' => 'foreign',
- 's' => "f $group2modcmd{'foreign'}",
- 'servers' => [ ],
+ if ($zone =~ m/\.$/) {
+ zone_warning("zone specified with trailing dot -".
+ " will not work", '');
+ }
+
+ $cfg= $zone_cfg{$zone};
+ if (!$cfg) {
+ $cfg= {
+ 'style_p' => 'foreign',
+ 's' => "f $group2modcmd{'foreign'}",
+ 'servers' => [ ],
};
+ zone_conf_settings($cfg, $zone);
+ }
mail_zone_before() or next
if $domail;
use vars qw(%delgs); # $delgs{$nameserver_list} = [ $whosaidandwhy ]
use vars qw(%auths); # $auths{$nameserver_list} = [ $whosaidandwhy ]
use vars qw(%glue); # $glue{$name}{$addr_list} = [ $whosaidandwhy ]
-use vars qw(%soas); # $soa{"$serial $origin"} = [ $whosaidandwhy ]
+use vars qw(%soas); # $soa{"$serial $mname"} = [ $whosaidandwhy ]
use vars qw(%addr_is_ok %warned);
use vars qw($delg_to_us);
use vars qw(@to_check); # ($addr,$whyask,$name_if_auth,$glueless_ok, ...)
sub zone_check_nsrrset ($$$$) {
my ($uaddr,$wa, $name_if_auth, $glueless_ok) = @_;
- my (@s, $s, $a, %s2g, @glue, $glue, $delgs_or_auths, $wwn, $ww);
+ my (@s, $s, $a, %s2g, @glue, $glue, $delgs_or_auths, $wwn, $ww, $cg);
my ($rcode);
$ww= "[$uaddr] $wa";
verbose("checking delegation by $ww");
@glue= @{ $s2g{$s} };
if (!@glue) {
zone_warning("glueless NS $s", $ww)
- unless $glueless_ok || zone_style('~',!$needglue) ||
- grep { has_suffix_of($zone,".$_"); }
- @{ $cfg->{'conv_glueless'} };
+ unless $glueless_ok
+ or zone_style('~',!$needglue)
+ or grep { has_suffix_of($zone,".$_"); }
+ @{ $cfg->{'conv_glueless'} }
+ or ((grep { has_suffix_of($s,".$_"); }
+ @{ $cfg->{'indirect_glue'} }) and
+ !(grep { has_suffix_of($zone,".$_"); }
+ @{ $cfg->{'indirect_glue'} }));
+ foreach $cg (@{ $cfg->{'conv_glueless'} }) {
+ zone_warning("nameserver $s (glueless) in".
+ " serverless-glueless namespace area $cg", $ww)
+ if has_suffix_of(".$s",".$cg");
+ }
($rcode,@glue)= lookup($s,'a','0',"glueless NS from $ww");
foreach $a (@glue) {
$wwn= "glueless NS from $ww";
sub zone_ns_name ($$) {
my ($name,$ww) = @_;
- my ($cg);
$delg_to_us=1 if grep { $name eq $_ } @{ $cfg->{'self_ns'} };
- foreach $cg (@{ $cfg->{'conv_glueless'} }) {
- zone_warning("nameserver $name in serverless-glueless".
- " namespace area $cg",
- $ww)
- if has_suffix_of(".$name",".$cg");
- }
zone_warning("published server, as $name, but configured as stealth",
$ww)
if $cfg->{'s'} =~ m/u/ &&
sub zone_server_addr ($$$$$) {
my ($addr,$name,$ww,$wwq,$is_soa) = @_;
- debug_trace("zone_server_addr ".join '|',@_);
+ debug_trace("zone_server_addr ".join('|',@_));
$addr_is_ok{$addr}= "$name ($wwq)"
if $is_soa || $cfg->{'s'} =~ m/u/;
zone_warning("forbidden nameserver address [$addr] $name",$ww)
if grep { $_ eq $addr } @{ $cfg->{'forbid_addr'} };
+ zone_warning("forbidden server address for our slave [$addr] $name",$ww)
+ if $cfg->{'s'} =~ m/p/ and
+ grep { $_ eq $addr } @{ $cfg->{'forbid_slave'} };
my ($name_is_self, $addr_is_self);
$name_is_self= grep { $_ eq $name }
}
if (!$name_is_self && !$addr_is_self &&
$is_soa && $cfg->{'s'} =~ m/p/) {
- zone_warning("SOA ORIGIN $name is not us (".
+ zone_warning("SOA MNAME $name is not us (".
(join ' ', @{ $cfg->{'self_soa'} }).")", $ww);
}
$delg_to_us=1 if $addr_is_self && !$is_soa;
sub zone_check_soa ($$$$) {
my ($uaddr,$wa,$name,$is_ns) = @_;
- my ($lame,$serial,$origin,$got,$rcode,@soa_addrs,$soa_addr,$ww,$wwn);
+ my ($lame,$serial,$mname,$got,$rcode,@soa_addrs,$soa_addr,$ww,$wwn);
verbose("checking service at [$uaddr] $name");
$lame= 'dead or lame';
$ww= "[$uaddr] $wa";
if ($dig_type eq 'flags:') {
$lame= $dig_rdata =~ m/ aa / ? '' : 'lame';
} elsif ($dig_type eq 'soa' && $dig_owner eq $zone && !$lame) {
- die "several SOAs ? $ww" if defined $origin;
+ die "several SOAs ? $ww" if defined $mname;
$got= $dig_rdata;
$got =~ m/^(\d+) (\S+)$/ or die "$got ?";
- ($serial,$origin) = ($1,$2);
+ ($serial,$mname) = ($1,$2);
}
},
$zone,'soa',$uaddr);
- $lame= 'broken' if !$lame && !defined $origin;
+ $lame= 'broken' if !$lame && !defined $mname;
if ($lame) { zone_warning("$lame server [$uaddr]",$wa); return; }
progress(2, sprintf "%-16s %46s has %s%s",
$zone, "$name [$uaddr]", $serial, $is_ns ? '' : '*');
push @{ $soas{$got} }, $ww;
- ($rcode,@soa_addrs)= lookup($origin,'a','0',"SOA ORIGIN");
- $wwn= "SOA ORIGIN from $ww";
+ ($rcode,@soa_addrs)= lookup($mname,'a','0',"SOA MNAME");
+ $wwn= "SOA MNAME from $ww";
foreach $soa_addr (@soa_addrs) {
- zone_server_queue($soa_addr,$origin,$wwn,"SOA [$uaddr]",1);
+ zone_server_queue($soa_addr,$mname,$wwn,"SOA [$uaddr]",1);
}
}
sub zone_consistency() {
- my ($d, $org_ser, $origin, $a, $h, $self_soa, $wa);
+ my ($d, $org_ser, $mname, $a, $h, $self_soa, $wa);
zone_consistency_set('delegations',\%delgs);
foreach $d (keys %delgs) { delete $auths{$d}; }
zone_consistency_set('zone nameserver rrset',\%auths);
foreach $h (keys %glue) {
zone_consistency_set("glue for $h", $glue{$h});
}
- zone_consistency_set("serial number and/or SOA ORIGIN",\%soas);
+ zone_consistency_set("serial number and/or SOA MNAME",\%soas);
$self_soa= $cfg->{'self_soa'};
}
}
sub zone_servers_simplefind () {
- my ($rcode,@nsnames,$ns,@soas,$origin);
+ my ($rcode,@nsnames,$ns,@soas,$mname);
($rcode,@nsnames)= lookup($zone,'ns-','0',"zone's servers");
foreach $ns (@nsnames) {
}
$delgs{join ' ', sort @nsnames} = [ "zone's servers" ];
- ($rcode,@soas)= lookup($zone,'soa','0',"SOA ORIGIN");
+ ($rcode,@soas)= lookup($zone,'soa','0',"SOA MNAME");
die "multiple SOA RRs in set! @soas ?" if @soas!=1;
$soas[0] =~ m/^(\S+)\s/ or die "SOA ? $_";
zone_server_simple(domain_canon($1,"lookup $zone SOA"),'SOA',1);
my ($name,$ww,$is_soa) = @_;
my ($rcode,@addrs,$addr);
($rcode,@addrs)= lookup($name,'a','0', "server - ".
- ($is_soa ? "SOA ORIGIN" : "NS"));
+ ($is_soa ? "SOA MNAME" : "NS"));
foreach $addr (@addrs) { zone_server_addr($addr,$name,$ww,$ww,$is_soa); }
}
if (!$c) {
open STDERR, ">&STDOUT" or die $!;
exec ('dig',
- '+nodef','+nosea','+nodebug','+norecurse',
+ '+nodef','+nosea','+norecurse',
"\@$qaddr",'-t',$qtype,$qowner);
die "$quis: exec dig:\n $!\n";
}