- Timestamp:
- 12/15/20 17:28:55 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bind-import
r822 r824 188 188 # arguably should do some more targeted voodoo when parsing the SOA details 189 189 190 ##fixme: would prefer to break the loop below *AND* next; the while starting above191 190 # check skiplist. do this early since it's (mostly) a simple string match against the raw record line 192 191 my $skipflag = 0; 193 192 foreach (@skipdefs) { 194 #print "skipdbg: $_ =~ $rec\n" if $rec =~ /207/;195 193 if ($rec =~ /\Q$_\E/) { 196 194 $skipflag = 1; 197 # print "skip: $rec\n"; 195 # might want to do something with the skipped records someday 198 196 } 199 197 } 200 198 next if $skipflag; 201 199 202 ##fixme: use external skiplist203 # # skip stale records that have no value204 # next if /^ip-192-168-1(12|20)-\d+/;205 # next if /ip.add.re.\d+\s*$/;206 200 207 201 $i++; … … 218 212 } 219 213 } elsif ($macro eq 'ORIGIN') { 220 ##fixme: going to skip the stupid case of "$ORIGIN com." and the like that lie 221 # between . and the root domain we were told we're importing; anyone using such 222 # a mess outside the root servers is clearly insane 223 224 # $ORIGIN supports cascading/nesting, by watching for fully-qualified names vs partial names. 225 226 print "origin ($mdetail)\n"; 214 # $ORIGIN supports cascading/nesting, by watching for fully-qualified names vs partial names. 227 215 if ($mdetail =~ /\.$/) { 228 216 $origin = $mdetail; … … 231 219 $origin = "$mdetail.$origin"; 232 220 } 233 234 # if ($mdetail eq '.' || $mdetail =~ /$zname\.$/ || $zname =~ /$mdetail\.$/) {235 # $origin = $mdetail;236 # } else {237 # # if we continue, we either use an $ORIGIN that's out of zone, or ignore it and potentially publish incorrect records.238 # die "bad \$ORIGIN: $_\n";239 # }240 241 221 } 242 222 elsif ($macro eq 'GENERATE') { 243 223 # needs to generate CIDR range(s) as needed to match the start/stop points 244 224 } 245 # not handling $INCLUDE or $GENERATE (altho the latter seems to be mostly a less-flexible version of the template types) 225 ##fixme: should arguably handle $INCLUDE 246 226 next; 247 227 } … … 257 237 } 258 238 259 #print " found '$curlabel'\n"; 239 # yay for special cases 240 $origin = '' if $origin eq '.'; 241 242 # leading whitespace indicates "same label as last record" 243 if ($rec =~ /^\s/) { 244 $curlabel = $prevlabel; 245 } else { 246 ($curlabel) = ($rec =~ /^([\w\@_.-]+)\s/); 247 } 260 248 261 249 # magic name! … … 264 252 # append $ORIGIN if name is not fully qualified. 265 253 if ($curlabel !~ /\.$/) { 266 $curlabel .= ($origin eq '.' ? '.' : ".$origin"); 267 } 268 #print " expanded '$curlabel'\n"; 269 270 # hack pthbptt 271 #$curlabel =~ s/\.\.$/./; 254 $curlabel .= ".$origin"; 255 } 256 272 257 # check for zone scope. skip bad records. 273 258 if ($curlabel !~ /$zname.$/) { … … 281 266 $rec =~ s/^([\w\@_.-]*)\s+//; 282 267 283 # # records must begin in the first column, no leading whitespace 284 # my ($name) = /^([\w\@_.-]+)\s/; 285 286 # foo IN A 1.2.3.4 287 # IN A 2.3.4.5 288 # = 289 # foo.zone. IN A 1.2.3.4 290 # foo.zone. IN A 2.3.4.5 291 292 # # "empty" label records inherit the previous label 293 # # RRs start in the first column by definition, so leading whitespace indicates an inherited label 294 # if (/^\s+/) { 295 # # fatal error. if there is no previous label, we can by definition not set 296 # # the current label based on it. this can only happen on the very first 297 # # record, following records will *ALWAYS* have a previous label 298 # die "bad first record ($_): no previous label\n" if !$prevlabel; 299 # $name = $prevlabel; 300 # } 301 302 #print "$i ($rec)\n";#\t$curlabel"; 303 304 305 306 307 # # append zone name to record name if missing AND not dot-terminated; 308 # # this happens automagically for forward zones, but not reverse because Reasons. (fixme?) 309 # # suck up and deal with the error if the dot-termiated name is out of zone; should be 310 # # impossible with valid BIND zone file but... 311 # if ($name !~ /\.$/) { 312 # $name .= ".$zname" if $name !~ /$zname$/; 313 # } else { 314 # warn "skipping out-of-zone record:\n\t($_)\n" if $name !~ /$zname\.$/; 315 # next; 316 # } 317 318 268 # now that we've collected and trimmed off the record's label, unpack the class, TTL, and type. 269 # class and TTL may be omitted, and may appear in either class,TTL or TTL,class order. 319 270 my $nc = 0; 271 # we don't actually use these but we have to recognize them 320 272 my $class = 'IN'; 273 # not preset as we need to detect whether it's present in the record 274 my $ttl; 321 275 my $type; 322 my $ttl;323 my $distance;324 my $weight;325 my $port;326 276 my $badrec; 327 277 my $curatom = 'class'; 328 329 # unpack the class, TTL, and type330 278 eval { 331 279 for (; $nc < 3; $nc++) { 280 last if $type; # short-circuit if we've got a type, further data is record-specific. 332 281 my ($atom) = ($rec =~ /^([\w\d.]+)\s/); 333 282 # should be safe? 334 283 last if !$atom; 335 last if $type;336 #print "nc:$nc: $atom\n";337 284 if ($atom =~ /^\d+$/) { 338 285 if (defined($ttl)) { 286 # we already have a TTL, so another all-numeric field is invalid. 339 287 die "bad record ($origrec)\n"; 340 # warn "bad record ($origrec)\n";341 # $badrec = 1;342 # last;343 288 } else { 344 289 if ($curatom ne 'class' && $curatom ne 'ttl') { 345 290 die "bad record ($origrec)\n"; 346 # warn "bad record ($origrec)\n";347 # $badrec = 1;348 # last;349 291 } 350 292 $curatom = 'ttl'; … … 352 294 } 353 295 } 354 355 296 elsif ($atom =~ /^IN|CS|CH|HS$/) { 356 #print "a$nc: d2: atom [$atom]\n $rec\n" if $i == $debugid;357 297 if ($atom =~ /CS|CH|HS/) { 358 298 die "unsupported class $atom in record ($origrec)\n"; 359 # warn "unsupported class $atom in record ($origrec)\n";360 # $badrec = 1;361 # last;362 299 } 363 300 $curatom = 'class'; 364 301 $class = $atom; 365 302 } 366 367 elsif ($atom =~ /^[A-Z]+/) { 368 # print "dbg: type $atom\n"; 303 elsif ($atom =~ /^[A-Z\d-]+/) { 304 # check against dnsadmin's internal list of known DNS types. 369 305 if ($reverse_typemap{$atom}) { 370 306 $type = $atom; … … 372 308 die "unknown type $atom in record ($origrec)\n"; 373 309 } 310 $curatom = 'type'; 374 311 } 375 312 $rec =~ s/^$atom\s*//; 376 313 } 377 }; # record class/type/TTL parse314 }; # record class/type/TTL loop 378 315 if ($@) { 379 316 warn $@; … … 387 324 #next if $badrec; 388 325 326 327 # Just In Case we need the original rdata after we've sliced off more pieces 328 my $rdata = $rec; 389 329 $prevlabel = $curlabel; 390 330 391 392 ## by convention the optional TTL leads the optional class, but they're apparently swappable. 393 # my ($ttl) = /^(\d+)?\s/; 394 # if (defined $ttl) { 395 # # TTL may be zero 396 # s/(\d+)?\s+//; 397 # } else { 398 # # Fall back to zone default TTL 399 # $ttl = $zonettl; 400 # } 401 # my ($class) = /^(IN|CS|CH|HS|\d+)\s/; 402 # if (defined $class) { 403 # if ($class =~ /\d+/) { 404 # 405 # } 406 # if ($class ne 'IN') { 407 # warn "Non-Internet class ($class) records not supported:\n\t$origrec\n"; 408 # next; 409 # } 410 # s/(IN|CS|CH|HS)\s+//; 411 # } else { 412 # $class = 'IN'; 413 # } 414 # my ($type) = /([A-Z-]+)\s/; 415 # if (!$reverse_typemap{$type}) { 416 # warn "Unknown type $type, skipping\n\t($rec)\n"; 417 # next; 418 # } 419 # s/([A-Z-]+)\s+//; 420 # chomp; 421 331 # part of the record data, when present 332 my $distance; 333 my $weight; 334 my $port; 422 335 423 336 my $itype = $reverse_typemap{$type}; 424 my $rdata = $rec; 425 426 # SOA is the only type that may span multiple lines. Probably. Note even AXFRed zones write multiline SOA records: 427 #@ IN SOA test.example.invalid. test.example.invalid. (2020082500 7200 900 604800 3600) 428 # IN NS olddns.example.com. 429 # IN MX 1 fred.foo.bar.invalid. 430 #foo IN A 192.168.16.45 431 # AXFR'ed zone file gets written as 432 #$ORIGIN . 433 #$TTL 3600 ; 1 hour 434 #example.invalid IN SOA test.example.invalid. test.example.invalid. ( 435 # 2020082500 ; serial 436 # 7200 ; refresh (2 hours) 437 # 900 ; retry (15 minutes) 438 # 604800 ; expire (1 week) 439 # 3600 ; minimum (1 hour) 440 # ) 441 # NS olddns.example.com. 442 # MX 1 fred.foo.bar.invalid. 443 #$ORIGIN example.invalid. 444 #foo A 192.168.16.45 445 $foundtypes{$type}++; 337 338 339 # See RFC1035 and successors for the canonical zone file format reference. We'll 340 # ignore a number of edge cases because they're quite horrible to parse. 341 # Of particular note is use of () to continue entries across multiple lines. Use 342 # outside of SOA records is quite rare, although some compliant zone file 343 # *writers* may use it on TXT records. 344 # We'll also ignore the strict interpretation in SOA records in favour of spotting 345 # the more standard pattern where the SOA serial, refresh, retry, expire, and minttl 346 # numbers are in (): 347 348 #example.invalid IN SOA test.example.invalid. test.example.invalid. ( 349 # 2020082500 ; serial 350 # 7200 ; refresh (2 hours) 351 # 900 ; retry (15 minutes) 352 # 604800 ; expire (1 week) 353 # 3600 ; minimum (1 hour) 354 # ) 355 356 $foundtypes{$type}++; 446 357 447 358 ##fixme: strip trailing . here? dnsadmin's normalized internal format omits it, some validation fails or may go funky … … 451 362 die "Can't parse gibberish SOAish record: $rec\n" if !$ns; 452 363 $rdata =~ s/([\w.]+)\s+([\w.]+)\s+\(\s*//; 453 454 # There are probably more efficient ways to do this but the SOA record455 # format is essentially character based, not line-based.456 # In theory the SOA serial etc may be spread over up to 5 lines, in any combination.457 364 458 365 # Parse fields from $rdata if present … … 488 395 $dnsdb->{dbh}->do("INSERT INTO records (domain_id,host,type,val,ttl,location) VALUES (?,?,?,?,?,?)", undef, @soavals); 489 396 } 490 # $dnsdb->{dbh}->do("INSERT INTO records () VALUES ()");491 # next;492 #Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:timestamp:lo493 #print "Z$zname:$ns:$adminmail:$soabits[0]:$soabits[1]:$soabits[2]:$soabits[3]:$soabits[4]:$ttl\n";494 397 # skip insert at end of loop; SOA records are not handled by DNSDB::addRec() 495 398 next;
Note:
See TracChangeset
for help on using the changeset viewer.