6 $etcfile= "/etc/bind/chiark-conf-gen.zones";
13 while (@ARGV && $ARGV[0] =~ m/^\-/) {
17 if (m/^quiet$/) { $verbosity=0; }
18 elsif (m/^verbose$/) { $verbosity=2; }
19 elsif (m/^root$/) { $fromroot=1; }
20 elsif (m/^(yes|no|force)$/) { m/^./; $mode= $&; }
21 elsif (m/^config$/) { $etcfile= loarg(); $where= '--config option'; }
22 else { usageerr("unknown option --$_"); }
27 if (s/^[ynf]//) { $mode=$&; }
28 elsif (s/^r//) { $fromroot=1; }
29 elsif (s/^v//) { $verbosity=2; }
30 elsif (s/^q//) { $verbosity=0; }
31 elsif (s/^C//) { $etcfile= soarg(); $where= '-C option'; }
32 else { usageerr("unknown option -$&"); }
37 sub loarg() { usageerr("missing option value") if !@ARGV; return shift @ARGV; }
38 sub soarg() { my ($rv); $rv=$_; $_=''; return length $rv ? $rv : loarg(); }
40 usageerr("must specify either -f|-y|-n or zones (and not both)")
41 if !!$mode == !!@ARGV;
46 usage: named-conf-regen [-rvq] -f|-y|-n|<zone>...\n".
48 " -f --force install without checking\n".
49 " -y --yes check and install\n".
50 " -n --no check only\n".
51 "additional options:\n".
52 " -r --root check all the way back to the root\n".
53 " -q --quiet no output for OK zones\n".
54 " -v --verbose extra verbose\n";
57 cfg_fail("config filename $etcfile should have been absolute path of a file")
58 unless $etcfile =~ m,^/, && $etcfile !~ m,/$,;
60 $default_dir= $etcfile;
61 $default_dir =~ s,/[^/]+$,,;
66 @self_ns= @self_soa= ();
73 read_config($etcfile);
75 print Dumper(@zone_cfg_list), Dumper(%zone_cfg);
77 sub cfg_fail ($) { die "$0: $where:\n $_[0]\n"; }
81 my ($fh,$z,@self, $dir,$prefix,$suffix,$lprefix,$lsuffix);
84 $fh= new IO::File $if,'r' or cfg_fail("open $if:\n $!");
86 if (!defined($_= <$fh>)) {
87 cfg_fail("read config file $if:\n $!") if $fh->error();
91 s/^\s+//; chomp; s/\s+$//;
95 if (m/^self(\-ns|\-soa|)\s+(\S.*\S)/) {
96 @self= split /\s+/, $2;
97 @self_ns= @self if $1 ne '-soa';
98 @self_soa= @self if $1 ne '-ns';
99 } elsif (m/^primary\-dir\s+(\S+)((?:\s+(\S+))??:\s+(\S+))?$/) {
100 ($dir, $prefix, $suffix) = (qualify($1),$2,$3);
101 $suffix= '_db' if !length $suffix;
102 opendir D, $dir or cfg_fail("open primary-dir $dir:\n $!");
103 $lprefix= length $prefix; $lsuffix= length $suffix;
104 while ($!=0, $_= readdir D) {
105 next if m/^\./ && !$lprefix;
106 next unless length > $lprefix+$lsuffix;
107 next unless substr($_,0,$lprefix) eq $prefix;
108 next unless substr($_,length($_)-$lsuffix) eq $suffix;
109 $z= substr($_,$lprefix,length($_)-($lprefix+$lsuffix));
110 zone_conf($z,'primary',"$dir/$_");
112 $! and cfg_fail("read primary-dir $dir:\n $!");
113 closedir D or cfg_fail("close primary-dir $dir:\n $!");
114 } elsif (m/^primary\s+(\S+)\s+(\S+)$/) {
115 zone_conf($1,'primary',qualify($2));
116 } elsif (m/^secondary\s+(\S+)\s+([0-9.\t]+)$/) {
117 zone_conf($1,'secondary','',$2);
118 } elsif (m/^stealth\s+(\S+)\s+([0-9. \t]+)$/) {
119 zone_conf($1,'stealth','',split /\s+/, $2);
120 } elsif (m/^slave\-dir\s+(\S+)((?:\s+(\S+))??:\s+(\S+))?$/) {
121 ($slave_dir, $slave_prefix, $slave_suffix) = (qualify($1),$2,$3);
122 } elsif (m/^output\s+bind8\+(\S+)$/) {
123 cfg_fail("default output may not apply to only some zones")
124 if @zone_cfg_list && length $default_output;
125 set_output(qualify($1));
126 } elsif (m/^include\s+(\S+)$/) {
129 cfg_fail("unknown configuration directive".
130 " or incorrect syntax or arguments");
133 $fh->close or cfg_fail("close config file $if:\n $!");
138 $i= "$default_dir/$i" unless $i =~ m,^/,;
141 sub zone_conf ($$@) {
142 my ($zone,$style,$file,@servers) = @_;
143 $file= qualify("$slave_dir/$slave_prefix".$zone.$slave_suffix)
145 if (!length $output) {
146 $default_output= qualify('chiark-conf-gen.bind8')
147 unless length $default_output;
148 set_output($default_output);
150 cfg_fail("redefined zone $zone") if exists $zone_cfg{$zone};
151 $zone_cfg{$zone}{'file'}= $file;
152 $zone_cfg{$zone}{'style'}= $style;
153 $zone_cfg{$zone}{'servers'}= @servers;
154 $zone_cfg{$zone}{'output'}= $output;
155 push @zone_cfg_list, $zone;
161 $output_contents{$output}= '';
169 my ($type,$domain) = @_;
171 defined($c=open ADH, "-|") or die "$0: fork adnshost:\n $!\n";
173 exec 'adnshost','+Do','+Dt','+Dc','-Cf',"-t$type",
175 die "$0: exec adnshost:\n $!\n";
180 die "$0: lookup -t$type $domain failed $? $!\n" if $? or $!;
185 my ($type,$domain) = @_;
186 my (@result)= lookup($type,$domain);
187 @result==1 or die "$0: lookup -t$type $domain gave more than one RR\n";
192 return unless $check;
194 $soa= lookup1('soa',$zone);
195 $soa_origin=$soa; $soa_origin =~ s/ .*//;
196 $soa_origin_addr= lookup1('a',$soa_origin);
198 @zone_ns= lookup('ns-',$zone);
200 @ok_sources= ($soa_origin_addr);
201 $ok_sources_descr= "SOA ORIGIN $soa_origin [$soa_origin_addr]";
203 if ($style eq 'unoff' || $style eq 'backup') {
204 for $zone_ns (@zone_ns) {
205 @zone_ns_addrs= lookup('a',$zone_ns);
206 push @ok_sources, @zone_ns_addrs;
207 $ok_sources_descr.= ", NS $zone_ns [@zone_ns_addrs]";
211 for $server (@servers) {
212 grep { $server eq $_ } @ok_sources
213 or warn "secondarying from $server which is not ".
214 "$ok_sources_desc\n";
217 if ($style eq 'secondary') {
218 grep { $zone_ns=$_, grep { $myname eq $_ } @mynames } @zone_n
219 or warn "supposedly published secondary but we ".
220 "(@mynames) are not published ($@zone_ns)\n";
227 # $superzone= $zone; $superzone =~ s/^[^\.]+\.//;
228 # @super_ns= lookup('ns-',$zone);
233 for $super_ns (@super_ns) {
235 open DIG, "dig @$super_ns. -t ns +norecurse $zone."
236 or die "$0: fork for dig:\n $!\n";
246 warning "$myname unlisted NS $nsnames"
252 warning "$myname advertised NS $nsnames"
260 set -e; a="`host -t a \"$ns\".`"; set +e
261 taddrs="`echo \" $a\" | expand | sed -n '
263 s/^[^ ][^ ]* *A *\([0-9][.0-9]*\)/\1/p
265 equlines "A $ns" "$a" "$taddrs"
266 addrs="$addrs $taddrs"
276 for server in $servers
284 if [ "x$addr" = "x$server" ]
291 warning "server $server? but $rectype $names" $addrs
306 checkhostout -val localhost
312 chdir "$base/primary" or die "$0: chdir $base/primary:\n $!";
313 beginfile('primary.zones');
316 $zone= $f; $zone =~ s/_db$//;
321 zone="`echo $f | sed -e 's/_db$//'`"
335 $currentfile_opened= $install ? "$conf/$currentfile.new" : "/dev/null";
336 open CFF, "> $toopen" or die "$0: begin $currentfile_opened:\n $!\n";
340 close CFF or die "$0: close $currentfile_opened:\n $!\n";
341 push @files, $currentfile;
344 sub installfiles () {
345 return unless $install;
346 chdir $conf or die "$0: chdir $conf:\n $!\n";
348 rename "$f.new", $f or die "$0: install new $f:\n $!\n";
353 echo >&2 "$zone $style: $*"
354 warnings=$[$warnings+1]
358 if [ "x`echo \" $2\" | wc -l`" != "x`echo \" $3\" | wc -l`" ]
366 hostout="`host $1 \"$zone\" 2>&1 >/dev/null $2 | egrep -v \
367 '^ \!\!\! .* SOA primary .* is not advertised via NS$'`"
369 if [ "x$hostout" = x ]; then return; fi
372 warning "warnings from host:"
381 echo -n "$zone $style " >&2
388 if [ $warnings != 0 ]
390 echo >&2 "$warnings warnings "