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 -$&"); }
}
}
};
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 $_;
}
.I config\-file
instead of
.BR /etc/bind/chiark-conf-gen.zones .
+Also changes the default directory.
.TP
-.BR \-q | \-\-quiet
-Do not print any information about zone(s) which do not have warnings.
-.TP
-.BR \-l | \-\-local
-Only checks for mistakes which are the responsibility of the local
-administrator. This means that for secondary and stealth zones we
-only check that we're slaving from the right place. For primary zones
-all checks are still done, unless the
-.B \-l
-option is repeated. It is a mistake to specify
-.B \-l
-with foreign zones (zones supplied explictly on the command line but
-not relevant to the local server), so this counts as a warning.
-.TP
-.BR \-v | \-\-verbose
-Print additional information about each zone.
+.BR \-D
+Enables debugging. Useful for debugging chiark\-named\-conf, but
+probably not useful for debugging your DNS configuration. Repeat to
+increase the debugging level. (Maximum is
+.BR -DD .)
.TP
-.BR \-g | \-\-glueless-ok
+.BR \-g | \-\-glueless
Do not warn about glueless referrals. Not recommended. Note that
-glueless referrals usually causes extra delays looking up names, and
-can cause lookups to fail even if in theory they could succeed. There
-is no generally agreed convention or standard for avoiding circular
+glueless referrals usually cause extra delays looking up names, and
+can make lookups fail even if in theory they could succeed. There is
+no generally agreed convention or standard for avoiding circular
glueless situations such as
.br
.B example.com NS ns0.example.net.uk
example.net.uk and example.com. The best way to be sure to avoid this
is to avoid gluelessness.
.TP
-.BR \-D
-Enables debugging. Useful for debugging chiark\-named\-conf, but
-probably not useful for debugging your DNS configuration.
+.BR \-l | \-\-local
+Only checks for mistakes which are the responsibility of the local
+administrator. This means that for secondary and stealth zones we
+only check that we're slaving from the right place. For primary zones
+all checks are still done. It is a mistake to specify
+.B \-l
+with foreign zones (zones supplied explictly on the command line but
+not relevant to the local server); doing so produces a warning.
+.TP
+.BR \-q | \-\-quiet
+Do not print any information about zone(s) which do not have warnings.
+.TP
+.BR \-v | \-\-verbose
+Print additional information about each zone.
.SH USAGE
The file
.B /etc/bind/chiark-conf-gen.zones
.B stealth
zones, the address should be that of the SOA origin or one of the
published nameservers.
+.SH SECURITY
+chiark\-named\-conf is supposed to be resistant to malicious data in
+the DNS. It is not resistant to malicious data in its own options,
+configuration file or environment. It is not supposed to read its
+stdin, but is not guaranteed to be safe if stdin is dangerous.
+.LP
+Killing chiark-named-conf suddenly should be safe, even with
+.BR -y " or " -f
+(though of course it may not complete its task if killed), provided
+that only one invocation is made at once.
+.LP
+Slow remote nameservers will cause chiark-named-conf to take
+excessively long.
+.SH EXIT STATUS
+.TP
+.B 0
+All went well and there were no warnings.
+.TP
+any other
+There were warnings or errors.
.SH FILES
.TP
.B /etc/bind/chiark-conf-gen.zones
.TP
.B /var/cache/bind/chiark-slave
Default location for slave zones.
+.SH ENVIRONMENT
+.LP
+Setting variables used by
+.BR dig (1)
+and
+.BR adnshost (1)
+will affect the operation of chiark\-named\-conf.
+Avoid messing with these if possible.
+.LP
+.B PATH
+Used to find subprograms such as
+.BR dig " and " adnshost .
.SH BUGS
The determination of the parent zone for each zone to be checked, and
its nameservers, is done simply using the system default nameserver.