chiark / gitweb /
Print warning count
[chiark-utils.git] / scripts / named-conf
index 2dada625ab644d4539cd1add4816767bd2cd8cdf..0f4861e2e594933be1a05f8682ec3399a24164c0 100755 (executable)
@@ -4,16 +4,17 @@ use strict;
 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);
 
@@ -21,21 +22,24 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
     $_= 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 -$&"); }
        }
     }
@@ -93,6 +97,8 @@ debug_dump('@zone_cfg_list %zone_cfg');
 process_zones($mode ? @zone_cfg_list : @ARGV);
 debug_dump('%output_contents');
 
+print STDERR "$0: $warnings warnings\n" if $warnings;
+exit 0;
 
 #-------------------- configuration reading
 
@@ -212,7 +218,15 @@ sub process_zones (@) {
            };
        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;
@@ -239,13 +253,22 @@ use vars qw(%addr_is_ok);
 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 (;;) {
@@ -282,7 +305,6 @@ sub zone_check () {
            last;
        }
     }
-    zone_consistency();
 }
 
 sub zone_check_nsrrset ($$$$) {
@@ -309,7 +331,8 @@ 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;
@@ -349,7 +372,7 @@ sub zone_check_soa ($$) {
 }
 
 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);
@@ -366,6 +389,10 @@ sub zone_consistency() {
                         " eg from ".((values %{ $soas{$org_ser} })[1]));
        }
     }
+}
+
+sub zone_servers_ok () {
+    my ($showok);
     if (%addr_is_ok) {
        $showok= 0;
        foreach $a (@{ $cfg->{'servers'} }) {
@@ -391,6 +418,30 @@ sub zone_consistency_set ($%) {
     }
 }
 
+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
 
@@ -514,6 +565,7 @@ sub dig (&$$$) {
 sub domain_canon ($) {
     local ($_) = @_;
     s/(.)\.$/$1/;
+    die "domain $_ ?" unless m/^[0-9a-z]/i;
     return lc $_;
 }