use IO::File;
use Data::Dumper;
-use vars qw($etcfile $where);
-$etcfile= "/etc/bind/chiark-conf-gen.zones";
-$where= '<built-in>';
+use vars qw($mode
+ $etcfile $where
+ $debug $needglue $localonly $verbosity);
-use vars qw($mode $verbosity $debug $needglue $localonly);
$mode= '';
-$verbosity= 1;
+$etcfile= "/etc/bind/chiark-conf-gen.zones";
+$where= '<built-in>';
$debug= 0;
-$needglue= 0;
+$needglue= 1;
$localonly= 0;
+$verbosity= 1;
use vars qw($dig_owner $dig_type $dig_rdata);
$_= shift @ARGV;
if (s/^\-\-//) {
last if m/^$/;
- if (m/^quiet$/) { $verbosity=0; }
- elsif (m/^verbose$/) { $verbosity=2; }
- elsif (m/^(yes|no|force)$/) { m/^./; $mode= $&; }
+ if (m/^(yes|no|force)$/) { m/^./; $mode= $&; }
elsif (m/^config$/) { $etcfile= loarg(); $where= '--config option'; }
+ elsif (m/^glueless$/) { $needglue=0; }
+ elsif (m/^localonly$/) { $localonly=1; }
+ elsif (m/^quiet$/) { $verbosity=0; }
+ elsif (m/^verbose$/) { $verbosity=2; }
else { usageerr("unknown option --$_"); }
} else {
s/^\-//;
last if m/^$/;
while (m/^./) {
if (s/^[ynf]//) { $mode=$&; }
- elsif (s/^v//) { $verbosity=2; }
- elsif (s/^q//) { $verbosity=0; }
+ elsif (s/^C//) { $etcfile= soarg(); $where= '-C option'; }
elsif (s/^D//) { $debug++; }
elsif (s/^g//) { $needglue=0; }
- elsif (s/^C//) { $etcfile= soarg(); $where= '-C option'; }
+ elsif (s/^l//) { $localonly=1; }
+ elsif (s/^q//) { $verbosity=0; }
+ elsif (s/^v//) { $verbosity=2; }
else { usageerr("unknown option -$&"); }
}
}
process_zones($mode ? @zone_cfg_list : @ARGV);
debug_dump('%output_contents');
+print STDERR "$0: $warnings warnings\n" if $warnings;
+exit 0;
#-------------------- configuration reading
};
progress(sprintf "%-40s %s", $zone, $$cfg{'style'});
if ($check) {
- eval { zone_check() };
+ eval {
+ if ($localonly && $cfg->{'style'} eq 'foreign') {
+ zone_warning("foreign zone specified with -l");
+ } elsif ($localonly && $cfg->{'style'} ne 'primary') {
+ zone_check_local();
+ } else {
+ zone_check_full();
+ }
+ };
zone_warning("checks failed: $@") if length $@;
}
zone_output() if $install;
use vars qw(@to_check); # ($addr,$whyask,$is_auth,$glueless_ok, ...)
use vars qw(@to_check_soa); # ($addr,$whyask, ...)
-sub zone_check () {
- my ($super_zone, @super_nsnames,
- $super_ns, @super_ns_addrs, $s, $wa, $is_auth,
- %nsrrset_checked, %soa_checked, $addr, $glueless_ok, $rcode);
+sub zone_check_full () {
+ zone_reset();
+ zone_investigate();
+ zone_consistency();
+ zone_servers_ok();
+}
+sub zone_reset() {
%delgs= %auths= %glue= %soas= %addr_is_ok= ();
@to_check= @to_check_soa= ();
+}
+
+sub zone_investigate() {
+ my ($super_zone, @super_nsnames,
+ $super_ns, @super_ns_addrs, $s, $wa, $is_auth,
+ %nsrrset_checked, %soa_checked, $addr, $glueless_ok, $rcode);
$super_zone= $zone;
for (;;) {
last;
}
}
- zone_consistency();
}
sub zone_check_nsrrset ($$$$) {
foreach $s (@s) {
@glue= @{ $s2g{$s} };
if (!@glue) {
- zone_warning("glueless NS $s, from $ww") unless $glueless_ok;
+ zone_warning("glueless NS $s, from $ww")
+ unless $glueless_ok || !$needglue;
next;
}
$glue= join ' ', sort @glue;
}
sub zone_consistency() {
- my ($d, $org_ser, $origin, $a, $showok, $h);
+ my ($d, $org_ser, $origin, $a, $h);
zone_consistency_set('delegations',\%delgs);
foreach $d (keys %delgs) { delete $auths{$d}; }
zone_consistency_set('zone nameserver rrset',\%auths);
" eg from ".((values %{ $soas{$org_ser} })[1]));
}
}
+}
+
+sub zone_servers_ok () {
+ my ($showok);
if (%addr_is_ok) {
$showok= 0;
foreach $a (@{ $cfg->{'servers'} }) {
}
}
+sub zone_check_local () {
+ zone_reset();
+ zone_servers_simplefind();
+ zone_servers_ok();
+}
+
+sub zone_servers_simplefind () {
+ my ($rcode,@nsnames,$ns,@soas,$origin);
+ if ($cfg->{'style'} eq 'stealth') {
+ ($rcode,@nsnames)= lookup($zone,'ns-','0');
+ foreach $ns (@nsnames) { zone_server_simple($ns,'NS'); }
+ }
+ ($rcode,@soas)= lookup($zone,'soa','0');
+ die "multiple SOA RRs in set! @soas ?" if @soas!=1;
+ $soas[0] =~ m/^(\S+)\s/ or die "SOA ? $_";
+ zone_server_simple(domain_canon($1),'SOA');
+}
+
+sub zone_server_simple ($$) {
+ my ($name,$why) = @_;
+ my ($rcode,@addrs,$addr);
+ ($rcode,@addrs)= lookup($name,'a','0');
+ foreach $addr (@addrs) { $addr_is_ok{$addr}= "$name ($why)"; }
+}
#-------------------- outputting
sub domain_canon ($) {
local ($_) = @_;
s/(.)\.$/$1/;
+ die "domain $_ ?" unless m/^[0-9a-z]/i;
return lc $_;
}