Changeset 819
- Timestamp:
- 12/04/20 13:20:46 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bind-import
r818 r819 22 22 use strict; 23 23 use warnings; 24 use Getopt::Long; 25 24 26 use Data::Dumper; 25 27 28 ##fixme 26 29 use lib '.'; 27 30 use DNSDB; 28 31 29 32 my $dnsdb = new DNSDB; 30 my $doimport = 0;33 my $doimport = 1; 31 34 32 35 #print Dumper(\%reverse_typemap); … … 34 37 local $dnsdb->{dbh}->{AutoCommit} = 0; 35 38 local $dnsdb->{dbh}->{RaiseError} = 1; 39 40 # from tiny-import: arguably can't use -r, -c is irrelevant. others useful? 41 # -r rewrite imported files to comment imported records 42 # -c coerce/downconvert A+PTR = records to PTR 43 # -l swallow A+PTR as-is 44 # -m merge PTR and A/AAAA as possible 45 # -t trial mode; don't commit to DB or actually rewrite flatfile (disables -r) 46 # -g import to specified group (name or ID) instead of group 1 36 47 37 48 ##fixme: command arguments/flags to set these to alternate values … … 42 53 my $serial = time(); 43 54 55 my @skipdefs; 56 my $skipfile; 57 58 GetOptions( 59 "skip=s" => \@skipdefs, 60 "skipfile=s" => \$skipfile, 61 "test|dry-run" => sub { $doimport = 0; }, 62 ); 63 64 my $usage = "usage: bind-import [--skip pattern [--skip pattern2 ...]] [--skipfile file] 65 zonename [zonefile] 66 --skip 67 Specify a string to skip in the records. If an IP-like string is 68 used, and the zone is a reverse zone, it will also search for the 69 octet-reversed form. Specify multiple times to skip multiple 70 different record patterns. 71 --skipfile 72 A file containing patterns to skip. Patterns from the file and 73 any --skip arguments are merged. 74 zonename 75 The name of the zone to import. Required. 76 zonefile 77 Specify the zone file as an argument. If not specified, the zone 78 data will be read from STDIN. 79 "; 80 44 81 my $zname = shift @ARGV; 45 82 my $origzone = $zname; 46 die "usage: bind-import zonename\n" if !$zname; 83 die $usage if !$zname; 84 85 my $zonefile = shift @ARGV; 86 if(!$zonefile) { 87 $zonefile = '&STDIN'; 88 } 89 47 90 my $rev = 'n'; 48 91 my $zid; 92 my %foundtypes; 93 94 if ($skipfile) { 95 if (-f $skipfile) { 96 open SKIP, "<$skipfile"; 97 while (<SKIP>) { 98 push @skipdefs, $_; 99 } 100 } else { 101 warn "skipfile $skipfile requested but it doesn't seem to exist. Continuing.\n"; 102 } 103 } 104 105 #sub setreplace { 106 ## print "dbg1: $_[0]\ndbg2: $_[1]\n"; 107 ##($_[1] eq '' ? $replace = 1 : $replace = $_[1]); 108 # if ($_[1] eq '') { 109 # print "no arg value, setting 1\n"; 110 # $replace = 1; 111 # } else { 112 # print "arg value $_[1]\n"; 113 # $replace = $_[1]; 114 # } 115 #} 116 49 117 50 118 my %amap; … … 52 120 my %cmap; 53 121 122 # wrap all the DB stuff in eval{}, so the entire thing either succeeds or fails. 123 124 eval { 125 126 local $dnsdb->{dbh}->{AutoCommit} = 0; 127 local $dnsdb->{dbh}->{RaiseError} = 1; 128 54 129 ##fixme: this is wrong, BIND zone files are generally complete and we're adding. merging records is an entire fridge full of worms. 55 130 ##fixme: for import, should arguably check for zone *non*existence 56 if ($zname =~ /\.arpa\.?$/ || $zname =~ m,^[\d./]+$,) { 57 $rev = 'y'; 58 $zname = _zone2cidr($zname) if $zname =~ /\.arpa\.?$/; 59 $zid = $dnsdb->revID($zname,':ANY:'); 60 if ($zid) { 61 # die "zone $origzone already present, not merging records\n"; 62 #$zname = new NetAddr::IP $zname; 63 # $zname = DNSDB::_ZONE($zname, 'ZONE', 'r', '.').($zname->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 131 if ($zname =~ /\.arpa\.?$/ || $zname =~ m,^[\d./]+$,) { 132 $rev = 'y'; 133 $zname = _zone2cidr($zname) if $zname =~ /\.arpa\.?$/; 134 $zid = $dnsdb->revID($zname,':ANY:'); 135 if ($zid) { 136 die "zone $origzone already present, not merging records\n"; 137 $zname = new NetAddr::IP $zname; 138 $zname = DNSDB::_ZONE($zname, 'ZONE', 'r', '.').($zname->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 139 } 140 $zid = $dnsdb->{dbh}->do("INSERT INTO revzones (revnet,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING rnds_id", 141 undef, ($zname, $group, $status, $location, $serial)); 142 143 } else { 144 print "dbg: forward zone\n"; 145 $zid = $dnsdb->domainID($zname,':ANY:'); 146 if ($zid) { 147 # die "zone $origzone already present, not merging records\n"; 148 print "dbg: skip add domain\n"; 149 } 150 else { 151 $zid = $dnsdb->{dbh}->do("INSERT INTO domains (domain,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING domain_id", 152 undef, ($zname, $group, $status, $location, $serial)); 153 } 154 64 155 } 65 # $zid = $dnsdb->{dbh}->do("INSERT INTO revzones (revnet,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING rnds_id", 66 # undef, ($zname, $group, $status, $location, $serial)); 67 68 } else { 69 $zid = $dnsdb->domainID($zname,':ANY:'); 70 if ($zid) { 71 # die "zone $origzone already present, not merging records\n"; 72 } 73 # $zid = $dnsdb->{dbh}->do("INSERT INTO domains (domain,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING domain_id", 74 # undef, ($zname, $group, $status, $location, $serial)); 75 } 76 77 die "error creating zone stub for $zname: ".$dnsdb->{dbh}->errstr if !$zid; 78 79 80 81 # still no sane way to expose a human-friendly view tag on the command line. 82 my $view = shift @ARGV; 83 $view = '' if !$view; 84 85 ##fixme: retrieve defttl from SOA record 86 my $zonettl = 900; 87 my $defttl = $zonettl; 88 my $origin = "$zname."; # to append to unqualified names 89 my %foundtypes; 90 91 # need to spin up a full state machine-ish thing, because BIND zone files are all about context 92 # see ch4, p56-72 in the grasshopper book 93 my $prevlabel = ''; 94 my $curlabel = ''; 95 96 my $i = 0; 97 98 while (my $rec = <>) { 99 chomp $rec; 100 next if $rec =~ /^\s*$/; 101 next if $rec =~ /^\s*;/; # comments 102 next if $rec =~ /^\s*\)/; # SOA closing (possibly other records too?) 156 157 die "error creating zone stub for $zname: ".$dnsdb->{dbh}->errstr if !$zid; 158 159 160 ##fixme: should probably make this a named argument so it doesn't get confused with the zone filename 161 # still no sane way to expose a human-friendly view tag on the command line. 162 my $view = shift @ARGV; 163 $view = '' if !$view; 164 165 ##fixme: retrieve defttl from SOA record 166 my $zonettl = 900; 167 my $defttl = $zonettl; 168 my $origin = "$zname."; # to append to unqualified names 169 170 # need to spin up a full state machine-ish thing, because BIND zone files are all about context 171 # see ch4, p56-72 in the grasshopper book 172 my $prevlabel = ''; 173 my $curlabel = ''; 174 175 my $i = 0; 176 177 open ZONEDATA, "<$zonefile"; 178 179 while (my $rec = <ZONEDATA>) { 180 chomp $rec; 181 next if $rec =~ /^\s*$/; 182 next if $rec =~ /^\s*;/; # comments 183 next if $rec =~ /^\s*\)/; # SOA closing (possibly other records too?) 103 184 # arguably should do some more targeted voodoo when parsing the SOA details 104 185 … … 108 189 next if /ip.add.re.\d+\s*$/; 109 190 110 $i++;111 #last if $i > 4;191 $i++; 192 last if $i > 7; 112 193 #print "line $i: ($rec)\n"; 113 if (my ($macro,$mdetail) = ($rec =~ /^\s*\$(TTL|ORIGIN|INCLUDE|GENERATE)\s+(.+)/) ) {114 # macro sort of thing; $TTL and $ORIGIN most common. $INCLUDE is a thing, expect it to be rare in live use tho115 if ($macro eq 'TTL') {116 $mdetail =~ s/\s*;.+$//;117 if ($mdetail =~ /^\d+$/) {118 $defttl = $mdetail;119 } else {120 warn "invalid \$TTL: $rec\n";121 }122 } elsif ($macro eq 'ORIGIN') {194 if (my ($macro,$mdetail) = ($rec =~ /^\s*\$(TTL|ORIGIN|INCLUDE|GENERATE)\s+(.+)/) ) { 195 # macro sort of thing; $TTL and $ORIGIN most common. $INCLUDE is a thing, expect it to be rare in live use tho 196 if ($macro eq 'TTL') { 197 $mdetail =~ s/\s*;.+$//; 198 if ($mdetail =~ /^\d+$/) { 199 $defttl = $mdetail; 200 } else { 201 warn "invalid \$TTL: $rec\n"; 202 } 203 } elsif ($macro eq 'ORIGIN') { 123 204 ##fixme: going to skip the stupid case of "$ORIGIN com." and the like that lie 124 205 # between . and the root domain we were told we're importing; anyone using such … … 128 209 129 210 print "origin ($mdetail)\n"; 130 if ($mdetail =~ /\.$/) {131 $origin = $mdetail;132 } else {133 # append current origin to unqualified origin134 $origin = "$mdetail.$origin";135 }211 if ($mdetail =~ /\.$/) { 212 $origin = $mdetail; 213 } else { 214 # append current origin to unqualified origin 215 $origin = "$mdetail.$origin"; 216 } 136 217 137 218 # if ($mdetail eq '.' || $mdetail =~ /$zname\.$/ || $zname =~ /$mdetail\.$/) { … … 142 223 # } 143 224 144 }145 elsif ($macro eq 'GENERATE') {225 } 226 elsif ($macro eq 'GENERATE') { 146 227 # needs to generate CIDR range(s) as needed to match the start/stop points 147 }228 } 148 229 # not handling $INCLUDE or $GENERATE (altho the latter seems to be mostly a less-flexible version of the template types) 149 next;150 }151 152 my $origrec = $rec;230 next; 231 } 232 233 my $origrec = $rec; 153 234 154 235 # leading whitespace indicates "same label as last record" 155 if ($rec =~ /^\s/) {156 $curlabel = $prevlabel;236 if ($rec =~ /^\s/) { 237 $curlabel = $prevlabel; 157 238 print " found empty label, using previous label\n"; 158 } else {159 ($curlabel) = ($rec =~ /^([\w\@_.-]+)\s/);160 }239 } else { 240 ($curlabel) = ($rec =~ /^([\w\@_.-]+)\s/); 241 } 161 242 162 243 print " found '$curlabel'\n"; 163 244 164 # magic name!165 $curlabel = "$zname." if $curlabel eq '@';166 167 # append $ORIGIN if name is not fully qualified.168 if ($curlabel !~ /\.$/) {169 $curlabel .= ($origin eq '.' ? '.' : ".$origin");170 }245 # magic name! 246 $curlabel = "$zname." if $curlabel eq '@'; 247 248 # append $ORIGIN if name is not fully qualified. 249 if ($curlabel !~ /\.$/) { 250 $curlabel .= ($origin eq '.' ? '.' : ".$origin"); 251 } 171 252 print " expanded '$curlabel'\n"; 172 253 173 254 # hack pthbptt 174 255 #$curlabel =~ s/\.\.$/./; 175 # check for zone scope. skip bad records. 176 if ($curlabel !~ /$zname.$/) { 177 warn "bad record $origrec, maybe bad \$ORIGIN?\n"; 256 # check for zone scope. skip bad records. 257 if ($curlabel !~ /$zname.$/) { 258 warn "bad record $origrec, maybe bad \$ORIGIN?\n"; 259 # bweh? maybe this should die()? 178 260 last; 179 next;180 }181 182 # trim the label, if any183 $rec =~ s/^([\w\@_.-]*)\s+//;261 next; 262 } 263 264 # trim the label, if any 265 $rec =~ s/^([\w\@_.-]*)\s+//; 184 266 185 267 # # records must begin in the first column, no leading whitespace … … 219 301 220 302 221 my $nc = 0; 222 my $class = 'IN'; 223 my $type; 224 my $ttl; 225 my $distance; 226 my $weight; 227 my $port; 228 my $badrec; 229 my $curatom = 'class'; 230 231 eval { 232 for (; $nc < 3; $nc++) { 233 my ($atom) = ($rec =~ /^([\w\d.]+)\s/); 234 # should be safe? 235 last if !$atom; 236 last if $type; 303 my $nc = 0; 304 my $class = 'IN'; 305 my $type; 306 my $ttl; 307 my $distance; 308 my $weight; 309 my $port; 310 my $badrec; 311 my $curatom = 'class'; 312 313 # unpack the class, TTL, and type 314 eval { 315 for (; $nc < 3; $nc++) { 316 my ($atom) = ($rec =~ /^([\w\d.]+)\s/); 317 # should be safe? 318 last if !$atom; 319 last if $type; 237 320 #print "nc:$nc: $atom\n"; 238 if ($atom =~ /^\d+$/) { 239 if (defined($ttl)) { 240 die "bad record ($origrec)\n"; 241 # warn "bad record ($origrec)\n"; 242 # $badrec = 1; 243 # last; 244 } else { 245 if ($curatom ne 'class' && $curatom ne 'ttl') { 321 if ($atom =~ /^\d+$/) { 322 if (defined($ttl)) { 246 323 die "bad record ($origrec)\n"; 247 324 # warn "bad record ($origrec)\n"; 248 325 # $badrec = 1; 249 326 # last; 327 } else { 328 if ($curatom ne 'class' && $curatom ne 'ttl') { 329 die "bad record ($origrec)\n"; 330 # warn "bad record ($origrec)\n"; 331 # $badrec = 1; 332 # last; 333 } 334 $curatom = 'ttl'; 335 $ttl = $atom; 250 336 } 251 $curatom = 'ttl';252 $ttl = $atom;253 337 } 254 } 255 256 elsif ($atom =~ /^IN|CS|CH|HS$/) { 338 339 elsif ($atom =~ /^IN|CS|CH|HS$/) { 257 340 #print "a$nc: d2: atom [$atom]\n $rec\n" if $i == $debugid; 258 if ($atom =~ /CS|CH|HS/) { 259 die "unsupported class $atom in record ($origrec)\n"; 260 # warn "unsupported class $atom in record ($origrec)\n"; 261 # $badrec = 1; 262 # last; 341 if ($atom =~ /CS|CH|HS/) { 342 die "unsupported class $atom in record ($origrec)\n"; 343 # warn "unsupported class $atom in record ($origrec)\n"; 344 # $badrec = 1; 345 # last; 346 } 347 $curatom = 'class'; 348 $class = $atom; 263 349 } 264 $curatom = 'class'; 265 $class = $atom; 266 } 267 268 elsif ($atom =~ /^[A-Z]+/) { 350 351 elsif ($atom =~ /^[A-Z]+/) { 269 352 # print "dbg: type $atom\n"; 270 if ($reverse_typemap{$atom}) { 271 $type = $atom; 272 } else { 273 die "unknown type $atom in record ($origrec)\n"; 353 if ($reverse_typemap{$atom}) { 354 $type = $atom; 355 } else { 356 die "unknown type $atom in record ($origrec)\n"; 357 } 274 358 } 275 } 276 $rec =~ s/^$atom\s*//; 277 } 278 }; 279 if ($@) { 280 warn $@; 281 next; 282 } 359 $rec =~ s/^$atom\s*//; 360 } 361 }; # record class/type/TTL parse 362 if ($@) { 363 warn $@; 364 next; 365 } 283 366 284 367 ##todo: BIND conflates a repeated label with repeating the TTL too. Matter of opinion whether that's really correct or not. 285 # set default TTL here so we can detect a TTL in the loop above286 $ttl = $defttl if !defined($ttl);368 # set default TTL here so we can detect a TTL in the loop above 369 $ttl = $defttl if !defined($ttl); 287 370 288 371 #next if $badrec; 289 372 290 291 ##fixme: drop curlabel? not sure it's needed 292 #$curlabel = $name; 293 $prevlabel = $curlabel; 294 373 $prevlabel = $curlabel; 295 374 296 375 … … 326 405 327 406 328 my $itype = $reverse_typemap{$type};329 my $rdata = $rec;407 my $itype = $reverse_typemap{$type}; 408 my $rdata = $rec; 330 409 331 410 # SOA is the only type that may span multiple lines. Probably. Note even AXFRed zones write multiline SOA records: … … 348 427 #$ORIGIN example.invalid. 349 428 #foo A 192.168.16.45 350 $foundtypes{$type}++;429 $foundtypes{$type}++; 351 430 352 431 ##fixme: strip trailing . here? dnsadmin's normalized internal format omits it, some validation fails or may go funky 353 432 354 if ($type eq 'SOA') { 355 my ($ns, $adminmail) = ($rdata =~ /([\w.]+)\s+([\w.]+)\s+\(/); 356 die "Can't parse gibberish SOAish record: $rec\n" if !$ns; 357 $rdata =~ s/([\w.]+)\s+([\w.]+)\s+\(\s*//; 358 359 # There are probably more efficient ways to do this but the SOA record 360 # format is essentially character based, not line-based. 361 # In theory the SOA serial etc may be spread over up to 5 lines, in any combination. 362 363 # Parse fields from $rdata if present 364 my @soabits; 365 my @soafirst = split /\s+/, $rdata; 366 while (my $f = shift @soafirst) { 367 last if $f !~ /^\d/; 368 push @soabits, $f; 369 } 370 371 # Read more lines if we don't have enough SOA fields filled 372 while (scalar(@soabits) < 5) { 373 my $tmp = <>; 374 $tmp =~ s/^\s*//; 375 my @tmpsoa = split /\s+/, $tmp; 376 while (my $f = shift @tmpsoa) { 433 if ($type eq 'SOA') { 434 my ($ns, $adminmail) = ($rdata =~ /([\w.]+)\s+([\w.]+)\s+\(/); 435 die "Can't parse gibberish SOAish record: $rec\n" if !$ns; 436 $rdata =~ s/([\w.]+)\s+([\w.]+)\s+\(\s*//; 437 438 # There are probably more efficient ways to do this but the SOA record 439 # format is essentially character based, not line-based. 440 # In theory the SOA serial etc may be spread over up to 5 lines, in any combination. 441 442 # Parse fields from $rdata if present 443 my @soabits; 444 my @soafirst = split /\s+/, $rdata; 445 while (my $f = shift @soafirst) { 377 446 last if $f !~ /^\d/; 378 push @soabits, $f; 379 } 380 if (scalar(@soabits) == 5) { 381 last; 382 } 383 } 384 # $dnsdb->{dbh}->do("UPDATE [zonetable] SET serial = ? WHERE [idfield] = ?"); 447 push @soabits, $f; 448 } 449 450 # Read more lines if we don't have enough SOA fields filled 451 while (scalar(@soabits) < 5) { 452 my $tmp = <ZONEDATA>; 453 $tmp =~ s/^\s*//; 454 my @tmpsoa = split /\s+/, $tmp; 455 while (my $f = shift @tmpsoa) { 456 last if $f !~ /^\d/; 457 push @soabits, $f; 458 } 459 if (scalar(@soabits) == 5) { 460 last; 461 } 462 } 463 my @soavals = ($zid, "$adminmail:$ns", 6, join(':', @soabits), $ttl, $location); 464 # host = $adminmail:$ns 465 # val = join(':', @soabits); 466 467 if ($rev eq 'y') { 468 $dnsdb->{dbh}->do("UPDATE revzones SET zserial = ? WHERE rdns_id = ?", undef, $soabits[0], $zid); 469 $dnsdb->{dbh}->do("INSERT INTO records (rdns_id,host,type,val,ttl,location) VALUES (?,?,?,?,?,?)", undef, @soavals); 470 } else { 471 $dnsdb->{dbh}->do("UPDATE domains SET zserial = ? WHERE domain_id = ?", undef, $soabits[0], $zid); 472 $dnsdb->{dbh}->do("INSERT INTO records (domain_id,host,type,val,ttl,location) VALUES (?,?,?,?,?,?)", undef, @soavals); 473 } 385 474 # $dnsdb->{dbh}->do("INSERT INTO records () VALUES ()"); 386 475 # next; 387 476 #Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:timestamp:lo 388 477 #print "Z$zname:$ns:$adminmail:$soabits[0]:$soabits[1]:$soabits[2]:$soabits[3]:$soabits[4]:$ttl\n"; 389 } # SOA390 391 392 # we're using DNSDB::addrec(), so we'll skip detailed validation of other records. Most won't need further breakdown393 394 elsif ($type eq 'A') {478 } # SOA 479 480 481 # we're using DNSDB::addrec(), so we'll skip detailed validation of other records. Most won't need further breakdown 482 483 elsif ($type eq 'A') { 395 484 #print "+$curlabel:$rdata:$ttl\n"; 396 }397 398 elsif ($type eq 'NS') {485 } 486 487 elsif ($type eq 'NS') { 399 488 #print "\&$curlabel::$rdata:$ttl\n"; 400 }401 402 elsif ($type eq 'CNAME') {489 } 490 491 elsif ($type eq 'CNAME') { 403 492 #print "C$curlabel:$rdata:$ttl\n"; 404 }405 406 elsif ($type eq 'PTR') {407 }408 409 elsif ($type eq 'MX') {410 ($distance) = ($rdata =~ /^(\d+)\s+/);411 if (!defined($distance)) {412 warn "malformed MX record: $origrec, skipping\n";413 next;414 }415 $rdata =~ s/^\d+\s+//;416 }417 418 elsif ($type eq 'TXT') {419 # Quotes may arguably be syntactically required, but they're not actually part of the record data420 $rdata =~ s/^"//;421 $rdata =~ s/"$//;493 } 494 495 elsif ($type eq 'PTR') { 496 } 497 498 elsif ($type eq 'MX') { 499 ($distance) = ($rdata =~ /^(\d+)\s+/); 500 if (!defined($distance)) { 501 warn "malformed MX record: $origrec, skipping\n"; 502 next; 503 } 504 $rdata =~ s/^\d+\s+//; 505 } 506 507 elsif ($type eq 'TXT') { 508 # Quotes may arguably be syntactically required, but they're not actually part of the record data 509 $rdata =~ s/^"//; 510 $rdata =~ s/"$//; 422 511 #print "'$curlabel:$rdata:$ttl\n"; 423 }424 425 elsif ($type eq 'RP') {426 }427 428 elsif ($type eq 'AAAA') {429 }430 431 elsif ($type eq 'SRV') {432 ($distance, $weight, $port) = ($rdata =~ /^(\d+)\s+(\d+)\s+(\d+)\s+/);433 if ( !defined($distance) || !defined($weight) || !defined($port) ) {434 warn "malformed SRV record: $origrec, skipping\n";435 next;436 }437 $rdata =~ s/^\d+\s+\d+\s+\d+\s+//;438 }439 440 # basically a dedicated clone of TXT, not sure anything actually looks up type SPF.441 # BIND autogenerates them from SPF TXT records.442 elsif ($type eq 'SPF') {443 # Quotes may arguably be syntactically required, but they're not actually part of the record data444 $rdata =~ s/^"//;445 $rdata =~ s/"$//;446 }512 } 513 514 elsif ($type eq 'RP') { 515 } 516 517 elsif ($type eq 'AAAA') { 518 } 519 520 elsif ($type eq 'SRV') { 521 ($distance, $weight, $port) = ($rdata =~ /^(\d+)\s+(\d+)\s+(\d+)\s+/); 522 if ( !defined($distance) || !defined($weight) || !defined($port) ) { 523 warn "malformed SRV record: $origrec, skipping\n"; 524 next; 525 } 526 $rdata =~ s/^\d+\s+\d+\s+\d+\s+//; 527 } 528 529 # basically a dedicated clone of TXT, not sure anything actually looks up type SPF. 530 # BIND autogenerates them from SPF TXT records. 531 elsif ($type eq 'SPF') { 532 # Quotes may arguably be syntactically required, but they're not actually part of the record data 533 $rdata =~ s/^"//; 534 $rdata =~ s/"$//; 535 } 447 536 448 537 # elsif ($type eq 'TXT') { 449 538 # elsif ($type eq 'TXT') { 450 539 451 else {452 warn "unsupported type $type, may not import correctly\n";453 }540 else { 541 warn "unsupported type $type, may not import correctly\n"; 542 } 454 543 455 544 no warnings qw(uninitialized); … … 458 547 #;imap IN 900 CNAME deepnet.cx. 459 548 ##fixme: not sure how to handle the case where someone leaves off the class. 460 if ($doimport) { 461 my ($code, $msg); 462 if ($rev eq 'n') { 463 ($code,$msg) = $dnsdb->addRec('n', $rev, $zid, \$curlabel, \$itype, \$rdata, $ttl, 464 $location, undef, undef, $distance, $weight, $port); 465 } else { 466 ($code,$msg) = $dnsdb->addRec('y', $rev, $zid, \$rdata, \$itype, \$curlabel, $ttl, 467 $location, undef, undef, $distance, $weight, $port); 468 } 469 print "$code: $msg\n"; 549 if ($doimport) { 550 my ($code, $msg); 551 if ($rev eq 'n') { 552 ($code,$msg) = $dnsdb->addRec('n', $rev, $zid, \$curlabel, \$itype, \$rdata, $ttl, 553 $location, undef, undef, $distance, $weight, $port); 554 } else { 555 ($code,$msg) = $dnsdb->addRec('y', $rev, $zid, \$rdata, \$itype, \$curlabel, $ttl, 556 $location, undef, undef, $distance, $weight, $port); 557 } 558 print "$code: $msg\n"; 559 } 560 # $i++; 470 561 } 471 # $i++; 562 563 }; 564 if ($@) { 565 warn "Error parsing zonefile: $@\n"; 566 $dnsdb->{dbh}->rollback; 567 exit; 472 568 } 473 474 569 475 570 #print Dumper \%amap; … … 497 592 #} 498 593 499 $dnsdb->{dbh}->rollback; 594 ##fixme: might not be sane, addRec() above does a commit() internally. 595 #$dnsdb->{dbh}->rollback; 596 $dnsdb->{dbh}->commit; 500 597 501 598 foreach my $t (keys %foundtypes) {
Note:
See TracChangeset
for help on using the changeset viewer.