- Timestamp:
- 09/29/22 13:00:28 (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/DNSDB/ExportBIND.pm
r871 r872 195 195 196 196 } # revsth->fetch 197 198 199 200 ## and now the domains 201 202 $soasth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ". 203 "FROM records WHERE domain_id=? AND type=6"); 204 $recsth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location,extract(epoch from stamp),expires,stampactive ". 205 "FROM records WHERE domain_id=? AND NOT type=6"); 206 # "FROM records WHERE domain_id=? AND type < 65280"); # Just exclude all types relating to rDNS 207 208 # Fetch active zone list 209 my $domsth = $dnsdb->{dbh}->prepare("SELECT domain_id,domain,status,changed FROM domains WHERE status=1 ORDER BY domain_id"); 210 # Unflag changed zones, so we can maybe cache the export and not redo everything every time 211 $zonesth = $dnsdb->{dbh}->prepare("UPDATE domains SET changed='n' WHERE domain_id=?"); 212 $domsth->execute(); 213 214 while (my ($domid,$dom,$domstat,$changed) = $domsth->fetchrow_array) { 215 216 # fetch a list of views/locations present in the zone. we need to publish a file for each one. 217 # in the event that no locations are present (~~ $viewlist is empty), /%view collapses to nothing in the zone path 218 my $tmplocs = $dnsdb->{dbh}->selectall_arrayref("SELECT DISTINCT location FROM records WHERE domain_id = ?", undef, $domid); 219 my @loclist; 220 foreach my $tloc (@{$tmplocs}) { 221 push @loclist, ($tloc->[0] eq '' ? 'common' : $tloc->[0]); 222 } 223 my %zonefiles; # zone file handles 224 225 eval { 226 227 ##fixme: use tmpfile module for more secure temp files? want the zone name at least in it anyway, not sure that works... 228 my $zfile = $dom; # can probably drop this intermediate 229 my $tmpcache = "tmp.$zfile.$$"; # safety net. don't overwrite a previous known-good file 230 foreach my $loc (@loclist) { 231 my $zfilepath = $dnsdb->{bind_export_zone_path}; 232 $zfilepath =~ s/\%view/$loc/; 233 $zfilepath =~ s/\%zone/$zfile/; 234 # $zfilepath =~ s/\%arpazone/$arpazone/; 235 236 # Just In Case(TM) 237 $zfilepath =~ s,[^\w./-],_,g; 238 239 # open $zonefiles{$loc}, ">", $zfilepath; 240 print "open zonefile for '$loc', '$zfilepath'\n"; 241 242 243 # write fresh records if: 244 # - the zone contains ALIAS pseudorecords, which need to cascade changes from the upstream CNAME farm at every opportunity 245 if ( ($dnsdb->{dbh}->selectrow_array("SELECT count(*) FROM records WHERE domain_id = ? AND type=65300", undef, $domid))[0] ) { 246 $changed = 1; # abuse this flag for zones with ALIAS records 247 # also update the serial number, because while it shouldn't matter purely for serving 248 # records, it WILL matter if AXFR becomes part of the publishing infrastructure 249 $dnsdb->_updateserial(domain_id => $domid); 250 } 251 # - the zone contains records which expire in less than 10 minutes or became valid less than 10 minutes ago 252 # note, no need to multi-bump the serial 253 elsif ( ($dnsdb->{dbh}->selectrow_array("SELECT COUNT(*) FROM records WHERE domain_id = ? AND ". 254 "stampactive='t' AND @(extract(epoch from stamp-now())) < 600", undef, $domid))[0] ) { 255 $changed = 1; 256 $dnsdb->_updateserial(domain_id => $domid); 257 } 258 # if (!$self->{usecache} || $self->{force_refresh} || $changed || !-e $cachefile || -z $cachefile) { 259 if ($dnsdb->{force_refresh} || $changed || !-e $zfilepath || -z $zfilepath) { 260 open $zonefiles{$loc}, ">", $zfilepath or die "Error creating temporary file $zfilepath: $!\n"; 261 262 # if ($self->{usecache}) { 263 # open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n"; 264 # $zonefilehandle = *ZONECACHE; 265 # } 266 267 # need to fetch this separately so the SOA comes first in the flatfile.... 268 # Just In Case we need/want to reimport from the flatfile later on. 269 $soasth->execute($domid); 270 my (@zsoa) = $soasth->fetchrow_array(); 271 272 # drop in a header line so we know when things went KABOOM 273 printf {$zonefiles{$loc}} "; %s in view %s exported %s\n", $arpazone, $loc, scalar(localtime) 274 or die "Error writing header [$cidr, '$loc']: $!\n"; 275 276 printrec_bind(\%zonefiles, \@loclist, $zsoa[7], 'n', \%recflags, $dom, 277 $zsoa[0], $zsoa[1], $zsoa[2], $zsoa[3], $zsoa[4], $zsoa[5], $zsoa[6], $loc, ''); 278 279 # $self->_printrec_tiny($zonefilehandle, $zsoa[7], 'n',\%recflags,$dom, 280 # $zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],''); 281 282 # tag the zonefile for publication in the view 283 push @{$viewzones{$loc}}, $arpazone; 284 } # foreach @loclist 285 286 $recsth->execute($domid); 287 while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc,$stamp,$expires,$stampactive) = $recsth->fetchrow_array) { 288 next if $recflags{$recid}; 289 290 # Check for out-of-zone data 291 $host = $dom if $host eq '@'; 292 if ($host !~ /$dom$/i) { 293 warn "Not exporting out-of-zone record $host $type $val, $ttl (zone $dom)\n"; 294 next; 295 } 296 297 # Spaces are evil. 298 $host =~ s/^\s+//; 299 $host =~ s/\s+$//; 300 if ($typemap{$type} ne 'TXT') { 301 # Leading or trailng spaces could be legit in TXT records. 302 $val =~ s/^\s+//; 303 $val =~ s/\s+$//; 304 } 305 $recflags{$recid} = 1; 306 307 printrec_bind(\%zonefiles, \@loclist, $recid, 'n', \%recflags, $dom, 308 $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp, $expires, $stampactive); 309 310 } # while ($recsth) 311 312 313 # if ($self->{usecache}) { 314 # close ZONECACHE; # force the file to be written 315 # # catch obvious write errors that leave an empty temp file 316 # if (-s $tmpcache) { 317 # rename $tmpcache, $cachefile 318 # or die "Error overwriting cache file $cachefile with temporary file: $!\n"; 319 # } 320 # } 321 322 } # if $changed or cache filesize is 0 323 324 }; 325 if ($@) { 326 die "error writing ".($dnsdb->{usecache} ? 'new data for ' : '')."$revzone: $@\n"; 327 # error! something borked, and we should be able to fall back on the old cache file 328 # report the error, somehow. 329 } else { 330 # mark zone as unmodified. Only do this if no errors, that way 331 # export failures should recover a little more automatically. 332 $zonesth->execute($revid); 333 } 334 335 # if ($dnsdb->{usecache}) { 336 # # We've already made as sure as we can that a cached zone file is "good", 337 # # although possibly stale/obsolete due to errors creating a new one. 338 # eval { 339 # open CACHE, "<$cachefile" or die $!; 340 # print $datafile $_ or die "error copying cached $revzone to master file: $!" while <CACHE>; 341 # close CACHE; 342 # }; 343 # die $@ if $@; 344 # } 345 346 } # domsth->fetch 197 347 198 348
Note:
See TracChangeset
for help on using the changeset viewer.