chiark / gitweb /
Bugfixes
[chiark-utils.git] / scripts / named-conf
index 1bd4792d038dc51498b843e62044cb9910d1d65e..dfabc82dc36f9e8c3b08bfb538fc2756c32d64ba 100755 (executable)
@@ -231,7 +231,7 @@ sub zone_conf ($$$$$@) {
     $zone_cfg{$zone}{'style_p'}= $style.$mod;
     $zone_cfg{$zone}{'s'}= $sabbr.$mod; # p)rimary s)econdary u)npub f)oreign
     $zone_cfg{$zone}{'servers'}= [ @servers ];
-    foreach $sfx (qw(self_soa self_ns self_addr forbid_addr)) {
+    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/;
@@ -250,7 +250,7 @@ sub set_output($) {
 
 #-------------------- checking
 
-use vars qw($zone $cfg $warnings);
+use vars qw($zone $cfg $warnings %zone_warnings);
 $warnings= 0;
 
 sub progress ($) {
@@ -291,14 +291,22 @@ sub process_zones (@) {
        $output_contents{$$cfg{'output'}} .= zone_output()
            if $install;
     }
-    print STDERR "$quis: $warnings warnings\n" or die $!
-       if $warnings;
+    if ($warnings) {
+       printf STDERR ("%s: %d warning(s) in %d zone(s);".
+                      " %d zone(s) checked ok.\n",
+                      $quis,
+                      $warnings,
+                      scalar(keys %zone_warnings),
+                      scalar(@zones - keys %zone_warnings));
+    } else {
+       progress(sprintf "%d zone(s) checked ok", scalar @zones);
+    }
 }
 
 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{"$origin $serial"} = [ $whosaidandwhy ]
+use vars qw(%soas);  # $soa{"$serial $origin"} = [ $whosaidandwhy ]
 use vars qw(%addr_is_ok %warned);
 use vars qw($delg_to_us);
 use vars qw(@to_check); # ($addr,$whyask,$is_auth,$glueless_ok, ...)
@@ -316,6 +324,7 @@ sub zone_warning ($$) {
     $w .= " ($o)" if length $o;
     print STDERR "$zone: warning: $w\n" or die $!;
     $warnings++;
+    $zone_warnings{$zone}++;
     return 1;
 }
 
@@ -344,12 +353,14 @@ sub zone_investigate() {
     for (;;) {
        debug_trace("zone $zone superzone $super_zone");
        $super_zone =~ s/^[^.]+\.// or die "no superzone ? ($super_zone)\n";
-       ($rcode,@super_nsnames)= lookup($super_zone,'ns-','06');
+       ($rcode,@super_nsnames)=
+           lookup($super_zone,'ns-','06',"superzone search");
        last if !$rcode;
     }
     for $super_ns (@super_nsnames) {
        $super_ns= lc $super_ns;
-       ($rcode,@super_ns_addrs)= lookup($super_ns,'a','0');
+       ($rcode,@super_ns_addrs)=
+           lookup($super_ns,'a','0',"published nameserver");
        foreach $addr (@super_ns_addrs) {
            push @to_check,
                 $addr,
@@ -401,12 +412,13 @@ sub zone_check_nsrrset ($$$$) {
     }
     @s= sort keys %s2g;
     foreach $s (@s) {
-       $delg_to_us=1 if grep { $s eq $_ } @{ $cfg->{'self_ns'} };
+       zone_ns_name($s,$ww);
        @glue= @{ $s2g{$s} };
        if (!@glue) {
            zone_warning("glueless NS $s", $ww)
                unless $glueless_ok || !$needglue ||
-                      grep { has_suffix_of($s,".$_"); } @conv_glueless;
+                      grep { has_suffix_of($s,".$_"); }
+                          @{ $cfg->{'conv_glueless'} };
            next;
        }
        $glue= join ' ', sort @glue;
@@ -417,21 +429,28 @@ sub zone_check_nsrrset ($$$$) {
     push @{ $delgs_or_auths->{$s} }, $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/ &&
+          grep { $_ eq $name }
+               @{ $cfg->{'self_ns'} }, @{ $cfg->{'self_soa'} };
+}
+
 sub zone_server_addr ($$$$$) {
     my ($addr,$name,$ww,$wwq,$is_soa) = @_;
-    my ($cg);
     debug_trace("zone_server_addr ".join '|',@_);
     $addr_is_ok{$addr}= "$name ($wwq)"
        if $is_soa || $cfg->{'s'} =~ m/u/;
-    foreach $cg (@conv_glueless) {
-       next unless has_suffix_of(".$name",".$cg");
-       zone_warning("nameserver [$addr] $name in serverless-glueless".
-                    " namespace area $cg",
-                    $ww);
-    }
-    zone_warning("configured as stealth but we [$addr] $name are published",
-                $ww)
-       if $cfg->{'s'} =~ m/u/ && grep { $_ eq $addr } @self_addr;
     zone_warning("forbidden nameserver address [$addr] $name",$ww)
        if grep { $_ eq $addr } @{ $cfg->{'forbid_addr'} };
 
@@ -469,7 +488,7 @@ sub zone_check_soa ($$$) {
        } elsif ($dig_type eq 'soa' && $dig_owner eq $zone && !$lame) {
            die "several SOAs ? $ww" if defined $origin;
            $got= $dig_rdata;
-           $got =~ m/^(\S+) \d+/ or die "$got ?";
+           $got =~ m/^\d+ (\S+)$/ or die "$got ?";
            $origin= $1;
        }
     },
@@ -477,7 +496,7 @@ sub zone_check_soa ($$$) {
     $lame= 'broken' if !$lame && !defined $origin;
     if ($lame) { zone_warning("$lame server [$uaddr]",$wa); return; }
     push @{ $soas{$got} }, $ww;
-    ($rcode,@soa_addrs)= lookup($origin,'a','0');
+    ($rcode,@soa_addrs)= lookup($origin,'a','0',"SOA ORIGIN");
     $wwn= "SOA ORIGIN from $ww";
     foreach $soa_addr (@soa_addrs) {
        zone_server_addr($soa_addr,$origin,$wwn,"SOA [$uaddr]",1);
@@ -493,7 +512,7 @@ sub zone_consistency() {
     foreach $h (keys %glue) {
        zone_consistency_set("glue for $h", $glue{$h});
     }
-    zone_consistency_set("SOA ORIGIN and SERIAL",\%soas);
+    zone_consistency_set("serial number and/or SOA ORIGIN",\%soas);
     $self_soa= $cfg->{'self_soa'};
 }
 
@@ -539,10 +558,13 @@ sub zone_check_local () {
 sub zone_servers_simplefind () {
     my ($rcode,@nsnames,$ns,@soas,$origin);
 
-    ($rcode,@nsnames)= lookup($zone,'ns-','0');
-    foreach $ns (@nsnames) { zone_server_simple($ns,'NS',0); }
+    ($rcode,@nsnames)= lookup($zone,'ns-','0',"zone's servers");
+    foreach $ns (@nsnames) {
+       zone_ns_name($ns,"NS");
+       zone_server_simple($ns,'NS',0);
+    }
 
-    ($rcode,@soas)= lookup($zone,'soa','0');
+    ($rcode,@soas)= lookup($zone,'soa','0',"SOA ORIGIN");
     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);
@@ -551,7 +573,8 @@ sub zone_servers_simplefind () {
 sub zone_server_simple ($$$) {
     my ($name,$ww,$is_soa) = @_;
     my ($rcode,@addrs,$addr);
-    ($rcode,@addrs)= lookup($name,'a','0');
+    ($rcode,@addrs)= lookup($name,'a','0', "server - ".
+                           ($is_soa ? "SOA ORIGIN" : "NS"));
     foreach $addr (@addrs) { zone_server_addr($addr,$name,$ww,$ww,$is_soa); }
 }
 
@@ -635,13 +658,15 @@ sub debug_trace ($) {
 
 sub has_suffix_of ($$) {
     my ($whole,$suffix) = @_;
+    debug_trace("has_suffix_of $whole $suffix");
     return 0 if length $whole < length $suffix;
     return 0 if substr($whole, length($whole) - length($suffix)) ne $suffix;
+    debug_trace("has_suffix_of $whole $suffix YES");
     return 1;
 }
 
-sub lookup ($$$) {
-    my ($domain,$type,$okrcodes) = @_;
+sub lookup ($$$$) {
+    my ($domain,$type,$okrcodes,$w) = @_;
     my ($c,$h,@result);
     debug_trace("lookup ==> (->$okrcodes) $domain $type");
     $h= new IO::Handle;
@@ -656,13 +681,12 @@ sub lookup ($$$) {
     $h->error and die "$quis: read from adnshost:\n $!\n";
     chomp @result;
     $!=0; $h->close;
-    die "$quis: lookup -t$type $domain $okrcodes failed $? $! @result\n"
+    die "$quis: lookup -t$type $domain $okrcodes ($w) failed $? $! @result\n"
        if $! or $?&255 or $?>1536 or index($okrcodes,$?>>8)<0;
     debug_trace("lookup <== $? @result");
     return ($?,@result);
 }
 
-
 sub dig (&$$$) {
     my ($eachrr, $qowner,$qtype,$qaddr) = @_;
     # also pseudo-rr with type `flags:'
@@ -713,7 +737,7 @@ sub dig (&$$$) {
            } elsif ($dig_type eq 'soa') {
                $irdata =~ m/^([-.0-9a-z]+)\s+.*\s+(\d+)(?:\s+\d\w+){4}$/i
                    or die "bad SOA $irdata ?";
-               $dig_rdata= domain_canon($1,$digwhy).' '.$2;
+               $dig_rdata= $2.' '.domain_canon($1,$digwhy);
            } else {
                debug_trace("ignoring uknown RR type $dig_type");
                next;