Ignore:
Timestamp:
12/10/13 17:47:44 (10 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Merge reverse DNS and location work; 2 of mumble

Numerous conflicts due to hand-copy or partial merges

Location:
branches/stable
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/stable

  • branches/stable/tiny-import.pl

    r348 r545  
    1919##
    2020
     21# WARNING:  This is NOT a heavy-duty validator;  it is assumed that the data
     22# being imported is more or less sane.  Only minor structural validation will
     23# be done to weed out the most broken records.
     24
    2125use strict;
    2226use warnings;
     
    2933}
    3034
     35usage() if !@ARGV;
     36
     37my %importcfg = (
     38        rw      => 0,
     39        conv    => 0,
     40        trial   => 0,
     41        );
     42# Handle some command-line arguments
     43while ($ARGV[0] =~ /^-/) {
     44  my $arg = shift @ARGV;
     45  usage() if $arg !~ /^-[rct]+$/;
     46  # -r  rewrite imported files to comment imported records
     47  # -c  coerce/downconvert A+PTR = records to PTR
     48  # -t  trial mode;  don't commit to DB or actually rewrite flatfile (disables -r)
     49  $arg =~ s/^-//;
     50  my @tmp = split //, $arg;
     51  foreach (@tmp) {
     52    $importcfg{rw} = 1 if $_ eq 'r';
     53    $importcfg{conv} = 1 if $_ eq 'c';
     54    $importcfg{trial} = 1 if $_ eq 't';
     55  }
     56}
     57$importcfg{rw} = 0 if $importcfg{trial};
     58
     59sub usage {
     60  die q(usage:  tiny-import.pl [-r] [-c] datafile1 datafile2 ... datafileN ...
     61        -r  Rewrite all specified data files with a warning header indicating the
     62            records are now managed by web, and commenting out all imported records.
     63            The directory containing any given datafile must be writable.
     64        -c  Convert any A+PTR (=) record to a bare PTR if the forward domain is
     65            not present in the database.  Note this does NOT look forward through
     66            a single file, nor across multiple files handled in the same run.
     67            Multiple passes may be necessary if SOA and = records are heavily
     68            intermixed and not clustered together.
     69        -t  Trial run mode;  spits out records that would be left unimported.
     70            Disables -r if set.
     71
     72        -r and -c may be combined (-rc)
     73
     74        datafileN is any tinydns record data file.
     75);
     76}
     77
    3178my $code;
    3279my ($dbh,$msg) = connectDB($config{dbname}, $config{dbuser}, $config{dbpass}, $config{dbhost});
     
    3885my %cnt;
    3986my @deferred;
     87my $errstr = '';
    4088
    4189foreach my $file (@ARGV) {
     
    4391    import(file => $file);
    4492#    import(file => $file, nosoa => 1);
    45     $dbh->rollback;
    46 #    $dbh->commit;
     93    $dbh->rollback if $importcfg{trial};
     94    $dbh->commit unless $importcfg{trial};
    4795  };
    4896  if ($@) {
    49     print "bleh: $@\n";
    50 die "die harder\n";
     97    print "Failure trying to import $file: $@\n $errstr\n";
     98    unlink ".$file.$$" if $importcfg{rw};       # cleanup
     99    $dbh->rollback;
    51100  }
    52101}
    53102
    54   foreach (keys %cnt) {
    55     print " $_  $cnt{$_}\n";
    56   }
     103# print summary count of record types encountered
     104foreach (keys %cnt) {
     105  print " $_    $cnt{$_}\n";
     106}
    57107
    58108exit 0;
     
    61111  our %args = @_;
    62112  my $flatfile = $args{file};
     113  my @fpath = split '/', $flatfile;
     114  $fpath[$#fpath] = ".$fpath[$#fpath]";
     115  my $rwfile = join('/', @fpath);#.".$$";
     116
    63117  open FLAT, "<$flatfile";
    64118
    65   our $recsth = $dbh->prepare("INSERT INTO records (domain_id,rdns_id,host,type,val,distance,weight,port,ttl) ".
    66         " VALUES (?,?,?,?,?,?,?,?,?)");
    67 
     119  if ($importcfg{rw}) {
     120    open RWFLAT, ">$rwfile" or die "Couldn't open tempfile $rwfile for rewriting: $!\n";
     121    print RWFLAT "# WARNING:  Records in this file have been imported to the web UI.\n#\n";
     122  }
     123
     124  our $recsth = $dbh->prepare("INSERT INTO records (domain_id,rdns_id,host,type,val,distance,weight,port,ttl,location) ".
     125        " VALUES (?,?,?,?,?,?,?,?,?,?)");
     126
     127  my %deleg;
     128
     129  my $ok = 0;
    68130  while (<FLAT>) {
    69     next if /^#/;
    70     next if /^\s*$/;
     131    if (/^#/ || /^\s*$/) {
     132      print RWFLAT "#$_" if $importcfg{rw};
     133      next;
     134    }
    71135    chomp;
    72     recslurp($_);
    73   }
    74 
    75   # Try the deferred records again, once.
     136    s/\s*$//;
     137    my $recstat = recslurp($_);
     138    $ok++ if $recstat;
     139    if ($importcfg{rw}) {
     140      if ($recstat) {
     141        print RWFLAT "#$_\n";
     142      } else {
     143        print RWFLAT "$_\n";
     144      }
     145    }
     146  }
     147
     148  # Move the rewritten flatfile in place of the original, so that any
     149  # external export processing will pick up any remaining records.
     150  if ($importcfg{rw}) {
     151    close RWFLAT;
     152    rename "$rwfile", $flatfile;
     153  }
     154
     155  # Show the failed records
    76156  foreach (@deferred) {
    77   #  print "trying $_ again\n";
    78     recslurp($_, 1);
    79   }
     157    print "failed to import $_\n";
     158  }
     159
     160##fixme:  hmm.  can't write the record back to the flatfile in the
     161# main while above, then come down here and import it anyway, can we?
     162#   # Try the deferred records again, once.
     163#  foreach (@deferred) {
     164#    print "trying $_ again\n";
     165#    recslurp($_, 1);
     166#  }
     167
     168  # .. but we can at least say how many records weren't imported.
     169  print "$ok OK, ".scalar(@deferred)." deferred records in $flatfile\n";
     170  $#deferred = -1;
     171
    80172
    81173  # Sub for various nonstandard types with lots of pure bytes expressed in octal
    82   # Takes a tinydns rdata string and count, returns a lis of $count bytes as well
     174  # Takes a tinydns rdata string and count, returns a list of $count bytes as well
    83175  # as trimming those logical bytes off the front of the rdata string.
    84176  sub _byteparse {
     
    103195  }
    104196
     197  # Convert octal-coded bytes back to something resembling normal characters, general case
     198  sub _deoctal {
     199    my $targ = shift;
     200    while ($$targ =~ /\\(\d{3})/) {
     201      my $sub = chr(oct($1));
     202      $$targ =~ s/\\$1/$sub/g;
     203    }
     204  }
     205
     206  sub _rdata2string {
     207    my $rdata = shift;
     208    my $tmpout = '';
     209    while ($rdata) {
     210      my $bytecount = 0;
     211      if ($rdata =~ /^\\/) {
     212        ($bytecount) = ($rdata =~ /^(\\\d{3})/);
     213        $bytecount =~ s/\\/0/;
     214        $bytecount = oct($bytecount);
     215        $rdata =~ s/^\\\d{3}//;
     216      } else {
     217        ($bytecount) = ($rdata =~ /^(.)/);
     218        $bytecount = ord($bytecount);
     219        $rdata =~ s/^.//;
     220      }
     221      my @tmp = _byteparse(\$rdata, $bytecount);
     222      foreach (@tmp) { $tmpout .= chr($_); }
     223##fixme:  warn or fail on long (>256?  >512?  >321?) strings
     224    }
     225    return $tmpout;
     226  }
     227
     228  sub _rdata2hex {
     229    my $rdata = shift;
     230    my $tmpout = '';
     231    while ($rdata) {
     232      my $byte = '';
     233      if ($rdata =~ /^\\/) {
     234        ($byte) = ($rdata =~ /^(\\\d{3})/);
     235        $byte =~ s/\\/0/;
     236        $tmpout .= sprintf("%0.2x", oct($byte));
     237        $rdata =~ s/^\\\d{3}//;
     238      } else {
     239        ($byte) = ($rdata =~ /^(.)/);
     240        $tmpout .= sprintf("%0.2x", ord($byte));
     241        $rdata =~ s/^.//;
     242      }
     243    }
     244    return $tmpout;
     245  }
     246
     247
    105248  sub recslurp {
    106249    my $rec = shift;
    107250    my $nodefer = shift || 0;
     251    my $impok = 1;
     252
     253    $errstr = $rec;  # this way at least we have some idea what went <splat>
    108254
    109255    if ($rec =~ /^=/) {
    110256      $cnt{APTR}++;
    111 if ($rec !~ /^=(?:\*|\\052)?[a-z0-9\._-]+:[\d\.]+:\d*/i) {
    112   print "bad A+PTR $rec\n";
    113   return;
    114 #=sud-rr-iGi0-1_sud-gw1-iGi4-2.vianet.ca::10.10.10.13:900::in
    115 }
    116       my ($host,$ip,$ttl,$time,$loc) = split /:/, $rec;
     257
     258##fixme:  do checks like this for all types
     259      if ($rec !~ /^=(?:\*|\\052)?[a-z0-9\._-]+:[\d\.]+:\d*/i) {
     260        print "bad A+PTR $rec\n";
     261        return;
     262      }
     263      my ($host,$ip,$ttl,$stamp,$loc) = split /:/, $rec, 5;
    117264      $host =~ s/^=//;
    118265      $host =~ s/\.$//;
    119       $time = '' if !$time;
    120       $loc = '' if !$loc;
    121       print "bleh, bad A+PTR!  $rec\n" if $loc =~ /:/;
     266      $ttl = 0 if !$ttl;
     267      $stamp = '' if !$stamp;
     268      $loc = '' if !$loc;
     269      $loc = '' if $loc =~ /^:+$/;
    122270      my $fparent = DNSDB::_hostparent($dbh, $host);
    123271      my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($ip));
    124272      if ($fparent && $rparent) {
    125         $dbh->do("INSERT INTO records (domain_id,rdns_id,host,type,val,ttl) VALUES (?,?,?,?,?,?)", undef,
    126                 ($fparent, $rparent, $host, 65280, $ip, $ttl));
     273        $recsth->execute($fparent, $rparent, $host, 65280, $ip, 0, 0, 0, $ttl, $loc);
    127274      } else {
    128275        push @deferred, $rec unless $nodefer;
     276        $impok = 0;
    129277        #  print "$tmporig deferred;  can't find both forward and reverse zone parents\n";
    130278      }
     
    132280    } elsif ($rec =~ /^C/) {
    133281      $cnt{CNAME}++;
    134       my ($host,$targ,$ttl,$time,$loc) = split /:/, $rec;
     282
     283      my ($host,$targ,$ttl,$stamp,$loc) = split /:/, $rec, 5;
    135284      $host =~ s/^C//;
    136285      $host =~ s/\.$//;
    137       $time = '' if !$time;
    138       $loc = '' if !$loc;
    139       my $fparent = DNSDB::_hostparent($dbh, $host);
    140       if ($fparent) {
    141 
    142       } else {
    143         push @deferred, $rec unless $nodefer;
    144         #  print "$tmporig deferred;  can't find parent zone\n";
     286      $host =~ s/^\\052/*/;
     287      $ttl = 0 if !$ttl;
     288      $stamp = '' if !$stamp;
     289      $loc = '' if !$loc;
     290      $loc = '' if $loc =~ /^:+$/;
     291      if ($host =~ /\.arpa$/) {
     292        ($code,$msg) = DNSDB::_zone2cidr($host);
     293        my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
     294        $recsth->execute(0, $rparent, $targ, 5, $msg->addr, 0, 0, 0, $ttl, $loc);
     295
     296##fixme:  automagically convert manually maintained sub-/24 delegations
     297#       my ($subip, $zone) = split /\./, $targ, 2;
     298#       ($code, $msg) = DNSDB::_zone2cidr($zone);
     299#       push @{$deleg{"$msg"}{iplist}}, $subip;
     300#print "$msg $subip\n";
     301
     302      } else {
     303        my $fparent = DNSDB::_hostparent($dbh, $host);
     304        if ($fparent) {
     305          $recsth->execute($fparent, 0, $host, 5, $targ, 0, 0, 0, $ttl, $loc);
     306        } else {
     307          push @deferred, $rec unless $nodefer;
     308          $impok = 0;
     309          #  print "$tmporig deferred;  can't find parent zone\n";
     310        }
    145311      }
    146312
    147313    } elsif ($rec =~ /^\&/) {
    148314      $cnt{NS}++;
     315
     316      my ($zone,$ip,$ns,$ttl,$stamp,$loc) = split /:/, $rec, 6;
     317      $zone =~ s/^\&//;
     318      $zone =~ s/\.$//;
     319      $ns =~ s/\.$//;
     320      $ns = "$ns.ns.$zone" if $ns !~ /\./;
     321      $ttl = 0 if !$ttl;
     322      $stamp = '' if !$stamp;
     323      $loc = '' if !$loc;
     324      $loc = '' if $loc =~ /^:+$/;
     325      if ($zone =~ /\.arpa$/) {
     326        ($code,$msg) = DNSDB::_zone2cidr($zone);
     327        my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >>= ?", undef, ("$msg"));
     328##fixme, in concert with the CNAME check for same;  automagically
     329# create "delegate" record instead for subzone NSes:  convert above to use = instead of >>=
     330#  ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ("$msg"))
     331#       if !$rparent;
     332        if ($rparent) {
     333          $recsth->execute(0, $rparent, $ns, 2, $msg, 0, 0, 0, $ttl, $loc);
     334        } else {
     335          push @deferred, $rec unless $nodefer;
     336          $impok = 0;
     337        }
     338      } else {
     339        my $fparent = DNSDB::_hostparent($dbh, $zone);
     340        if ($fparent) {
     341          $recsth->execute($fparent, 0, $zone, 2, $ns, 0, 0, 0, $ttl, $loc);
     342          $recsth->execute($fparent, 0, $ns, 2, $ip, 0, 0, 0, $ttl, $loc) if $ip;
     343        } else {
     344          push @deferred, $rec unless $nodefer;
     345          $impok = 0;
     346        }
     347      }
     348
    149349    } elsif ($rec =~ /^\^/) {
    150350      $cnt{PTR}++;
     351
     352      my ($rip,$host,$ttl,$stamp,$loc) = split /:/, $rec, 5;
     353      $rip =~ s/^\^//;
     354      $rip =~ s/\.$//;
     355      $ttl = 0 if !$ttl;
     356      $stamp = '' if !$stamp;
     357      $loc = '' if !$loc;
     358      $loc = '' if $loc =~ /^:+$/;
     359      my $rparent;
     360      if (my ($i, $z) = ($rip =~ /^(\d+)\.(\d+-(?:\d+\.){4}in-addr.arpa)$/) ) {
     361        ($code,$msg) = DNSDB::_zone2cidr($z);
     362        # Exact matches only, because we're in a sub-/24 delegation
     363##fixme:  flag the type of delegation (range, subnet-with-dash, subnet-with-slash)
     364# somewhere so we can recover it on export.  probably best to do that in the revzone data.
     365        ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet = ?", undef, ("$msg"));
     366        $z =~ s/^[\d-]+//;
     367        ($code,$msg) = DNSDB::_zone2cidr("$i.$z");      # Get the actual IP and normalize
     368      } else {
     369        ($code,$msg) = DNSDB::_zone2cidr($rip);
     370        ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ("$msg"));
     371      }
     372      if ($rparent) {
     373        $recsth->execute(0, $rparent, $host, 12, $msg->addr, 0, 0, 0, $ttl, $loc);
     374      } else {
     375        push @deferred, $rec unless $nodefer;
     376        $impok = 0;
     377      }
     378
    151379    } elsif ($rec =~ /^\+/) {
    152380      $cnt{A}++;
     381
     382      my ($host,$ip,$ttl,$stamp,$loc) = split /:/, $rec, 5;
     383      $host =~ s/^\+//;
     384      $host =~ s/\.$//;
     385      $host =~ s/^\\052/*/;
     386      $ttl = 0 if !$ttl;
     387      $stamp = '' if !$stamp;
     388      $loc = '' if !$loc;
     389      $loc = '' if $loc =~ /^:+$/;
     390
     391      my $domid = DNSDB::_hostparent($dbh, $host);
     392      if ($domid) {
     393        $recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc);
     394      } else {
     395        push @deferred, $rec unless $nodefer;
     396        $impok = 0;
     397      }
     398
    153399    } elsif ($rec =~ /^Z/) {
    154400      $cnt{SOA}++;
    155 #Z128.91.209.in-addr.arpa:ns1.vianet.ca.:dnsadmin.vianet.ca.::1209600:1209600:900:900:900:
    156       my ($zone,$master,$contact,$serial,$refresh,$retry,$expire,$minttl,$ttl,$time,$loc) = split /:/, $rec;
     401
     402      my ($zone,$master,$contact,$serial,$refresh,$retry,$expire,$minttl,$ttl,$stamp,$loc) = split /:/, $rec, 11;
    157403      $zone =~ s/^Z//;
    158404      $zone =~ s/\.$//;
    159405      $master =~ s/\.$//;
    160406      $contact =~ s/\.$//;
    161       $time = '' if !$time;
    162       $loc = '' if !$loc;
     407      $ttl = 0 if !$ttl;
     408      $stamp = '' if !$stamp;
     409      $loc = '' if !$loc;
     410      $loc = '' if $loc =~ /^:+$/;
    163411      if ($zone =~ /\.arpa$/) {
    164412        ($code,$msg) = DNSDB::_zone2cidr($zone);
    165         $dbh->do("INSERT INTO revzones (revnet,group_id,status) VALUES (?,1,1)", undef, ($msg));
     413        $dbh->do("INSERT INTO revzones (revnet,group_id,status,default_location) VALUES (?,1,1,?)",
     414                undef, ($msg, $loc));
    166415        my ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
    167         $dbh->do("INSERT INTO records (rdns_id,host,type,val,ttl) VALUES (?,?,6,?,?)", undef,
    168                 ($rdns, "$contact:$master", "$refresh:$retry:$expire:$minttl", $ttl));
    169       } else {
    170         $dbh->do("INSERT INTO domains (domain,group_id,status) VALUES (?,1,1)", undef, ($zone));
     416        $recsth->execute(0, $rdns, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
     417      } else {
     418        $dbh->do("INSERT INTO domains (domain,group_id,status,default_location) VALUES (?,1,1,?)",
     419                undef, ($zone, $loc));
    171420        my ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
    172         $dbh->do("INSERT INTO records (rdns_id,host,type,val,ttl) VALUES (?,?,6,?,?)", undef,
    173                 ($domid, "$contact:$master", "$refresh:$retry:$expire:$minttl", $ttl));
     421        $recsth->execute($domid, 0, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
    174422      }
    175423
    176424    } elsif ($rec =~ /^\@/) {
    177425      $cnt{MX}++;
     426
     427      my ($zone,$ip,$host,$dist,$ttl,$stamp,$loc) = split /:/, $rec, 7;
     428      $zone =~ s/^\@//;
     429      $zone =~ s/\.$//;
     430      $zone =~ s/^\\052/*/;
     431      $host =~ s/\.$//;
     432      $host = "$host.mx.$zone" if $host !~ /\./;
     433      $ttl = 0 if !$ttl;
     434      $stamp = '' if !$stamp;
     435      $loc = '' if !$loc;
     436      $loc = '' if $loc =~ /^:+$/;
     437
     438# note we don't check for reverse domains here, because MX records don't make any sense in reverse zones.
     439# if this really ever becomes an issue for someone it can be expanded to handle those weirdos
     440
     441      # allow for subzone MXes, since it's perfectly legitimate to simply stuff it all in a single parent zone
     442      my $domid = DNSDB::_hostparent($dbh, $zone);
     443      if ($domid) {
     444        $recsth->execute($domid, 0, $zone, 15, $host, $dist, 0, 0, $ttl, $loc);
     445        $recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
     446      } else {
     447        push @deferred, $rec unless $nodefer;
     448        $impok = 0;
     449      }
     450
    178451    } elsif ($rec =~ /^'/) {
    179452      $cnt{TXT}++;
    180453
    181 sub _deoctal {
    182   my $targ = shift;
    183   while ($$targ =~ /\\(\d{3})/) {
    184     my $sub = chr(oct($1));
    185     $$targ =~ s/\\$1/$sub/g;
    186   }
    187 }
    188 
    189       my ($fqdn, $rdata, $ttl, $time, $loc) = split /:/, $rec;
     454      my ($fqdn, $rdata, $ttl, $stamp, $loc) = split /:/, $rec, 5;
    190455      $fqdn =~ s/^'//;
     456      $fqdn =~ s/^\\052/*/;
    191457      _deoctal(\$rdata);
    192 
    193 print "$fqdn TXT '$rdata'\n" if $fqdn =~ /^\*/;
    194       my $domid = DNSDB::_hostparent($dbh, $fqdn);
    195       if ($domid) {
    196         $recsth->execute($domid, 0, $fqdn, 16, $rdata, 0, 0, 0, $ttl);
    197       } else {
    198         push @deferred, $rec unless $nodefer;
     458      $ttl = 0 if !$ttl;
     459      $stamp = '' if !$stamp;
     460      $loc = '' if !$loc;
     461      $loc = '' if $loc =~ /^:+$/;
     462
     463      if ($fqdn =~ /\.arpa$/) {
     464        ($code,$msg) = DNSDB::_zone2cidr($fqdn);
     465        my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
     466        $recsth->execute(0, $rparent, $rdata, 16, "$msg", 0, 0, 0, $ttl, $loc);
     467      } else {
     468        my $domid = DNSDB::_hostparent($dbh, $fqdn);
     469        if ($domid) {
     470          $recsth->execute($domid, 0, $fqdn, 16, $rdata, 0, 0, 0, $ttl, $loc);
     471        } else {
     472          push @deferred, $rec unless $nodefer;
     473          $impok = 0;
     474        }
    199475      }
    200476
    201477    } elsif ($rec =~ /^\./) {
    202478      $cnt{NSASOA}++;
     479
     480      my ($fqdn, $ip, $ns, $ttl, $stamp, $loc) = split /:/, $rec, 6;
     481      $fqdn =~ s/^\.//;
     482      $fqdn =~ s/\.$//;
     483      $ns =~ s/\.$//;
     484      $ns = "$ns.ns.$fqdn" if $ns !~ /\./;
     485      $ttl = 0 if !$ttl;
     486      $stamp = '' if !$stamp;
     487      $loc = '' if !$loc;
     488      $loc = '' if $loc =~ /^:+$/;
     489
     490      if ($fqdn =~ /\.arpa$/) {
     491        ($code,$msg) = DNSDB::_zone2cidr($fqdn);
     492        my ($rdns) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet = ?", undef, ($msg));
     493        if (!$rdns) {
     494          $errstr = "adding revzone $msg";
     495          $dbh->do("INSERT INTO revzones (revnet,group_id,status,default_location) VALUES (?,1,1,?)",
     496                undef, ($msg, $loc));
     497          ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
     498# this would probably make a lot more sense to do hostmaster.$config{admindomain}
     499          $recsth->execute(0, $rdns, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
     500        }
     501        $recsth->execute(0, $rdns, $ns, 2, "$msg", 0, 0, 0, $ttl, $loc);
     502##fixme:  (?)  implement full conversion of tinydns . records?
     503# -> problem:  A record for NS must be added to the appropriate *forward* zone, not the reverse
     504#$recsth->execute(0, $rdns, $ns, 1, $ip, 0, 0, 0, $ttl)
     505# ...  auto-A-record simply does not make sense in reverse zones.  Functionally
     506# I think it would work, sort of, but it's a nasty mess and anyone hosting reverse
     507# zones has names for their nameservers already.
     508# Even the auto-nameserver-fqdn comes out...  ugly.
     509
     510      } else {
     511        my ($domid) = $dbh->selectrow_array("SELECT domain_id FROM domains WHERE lower(domain) = lower(?)",
     512                undef, ($fqdn));
     513        if (!$domid) {
     514          $errstr = "adding domain $fqdn";
     515          $dbh->do("INSERT INTO domains (domain,group_id,status,default_location) VALUES (?,1,1,?)",
     516                undef, ($fqdn, $loc));
     517          ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
     518          $recsth->execute($domid, 0, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
     519        }
     520        $recsth->execute($domid, 0, $fqdn, 2, $ns, 0, 0, 0, $ttl, $loc);
     521        $recsth->execute($domid, 0, $ns, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
     522      }
     523
     524
     525    } elsif ($rec =~ /^\%/) {
     526      $cnt{VIEWS}++;
     527
     528      # unfortunate that we don't have a guaranteed way to get a description on these.  :/
     529      my ($loc,$cnet) = split /:/, $rec, 2;
     530      $loc =~ s/^\%//;
     531      if (my ($iplist) = $dbh->selectrow_array("SELECT iplist FROM locations WHERE location = ?", undef, ($loc))) {
     532        if ($cnet) {
     533          $iplist .= ", $cnet";
     534          $dbh->do("UPDATE locations SET iplist = ? WHERE location = ?", undef, ($iplist, $loc));
     535        } else {
     536          # hmm.  spit out a warning?  if we already have entries for $loc, adding a null
     537          # entry will almost certainly Do The Wrong Thing(TM)
     538        }
     539      } else {
     540        $cnet = '' if !$cnet;   # de-nullify
     541        $dbh->do("INSERT INTO locations (location,iplist,description) VALUES (?,?,?)", undef, ($loc, $cnet, $loc));
     542      }
     543
    203544    } elsif ($rec =~ /^:/) {
    204545      $cnt{NCUST}++;
     
    206547# recognition and handling for the core common types, this must deal with the leftovers.
    207548# :fqdn:type:rdata:ttl:time:loc
    208 #:mx2.sys.vianet.ca:44:\001\001\215\272\152\152\123\142\120\071\320\106\160\364\107\372\153\116\036\111\247\135:900::sys
    209 #:_sipfederationtls._tcp.ncstechnology.com:33:\000\144\000\001\023\305\006sipfed\006online\004lync\003com\000:3600::
    210 
    211 my (undef, $fqdn, $type, $rdata, $ttl, $time, $loc) = split /:/, $rec;
    212 
    213 if ($type == 33) {
    214   # SRV
    215   my ($prio, $weight, $port, $target) = (0,0,0,0);
    216 
    217   my @tmp = _byteparse(\$rdata, 2);
    218   $prio = $tmp[0] * 256 + $tmp[1];
    219   @tmp = _byteparse(\$rdata, 2);
    220   $weight = $tmp[0] * 256 + $tmp[1];
    221   @tmp = _byteparse(\$rdata, 2);
    222   $port = $tmp[0] * 256 + $tmp[1];
    223 
    224   $rdata =~ s/\\\d{3}/./g;
    225   ($target) = ($rdata =~ /^\.(.+)\.$/);
     549
     550      my (undef, $fqdn, $type, $rdata, $ttl, $stamp, $loc) = split /:/, $rec, 7;
     551      $fqdn =~ s/\.$//;
     552      $fqdn =~ s/^\\052/*/;
     553      $ttl = 0 if !$ttl;
     554      $stamp = '' if !$stamp;
     555      $loc = '' if !$loc;
     556      $loc = '' if $loc =~ /^:+$/;
     557
     558      if ($type == 33) {
     559        # SRV
     560        my ($prio, $weight, $port, $target) = (0,0,0,0);
     561
     562        my @tmp = _byteparse(\$rdata, 2);
     563        $prio = $tmp[0] * 256 + $tmp[1];
     564        @tmp = _byteparse(\$rdata, 2);
     565        $weight = $tmp[0] * 256 + $tmp[1];
     566        @tmp = _byteparse(\$rdata, 2);
     567        $port = $tmp[0] * 256 + $tmp[1];
     568
     569        $rdata =~ s/\\\d{3}/./g;
     570        ($target) = ($rdata =~ /^\.(.+)\.$/);
    226571# hmm.  the above *should* work, but What If(TM) we have ASCII-range bytes
    227572# representing the target's fqdn part length(s)?  axfr-get doesn't seem to,
     
    236581#  }
    237582
    238   my $domid = DNSDB::_hostparent($dbh, $fqdn);
    239   if ($domid) {
    240     $recsth->execute($domid, 0, $fqdn, $type, $target, $prio, $weight, $port, $ttl) if $domid;
    241   } else {
    242     push @deferred, $rec unless $nodefer;
    243   }
    244 
    245 } elsif ($type == 28) {
    246   # AAAA
    247 
    248   my @v6;
    249 
    250   for (my $i=0; $i < 8; $i++) {
    251     my @tmp = _byteparse(\$rdata, 2);
    252     push @v6, sprintf("%0.4x", $tmp[0] * 256 + $tmp[1]);
    253   }
    254   my $val = NetAddr::IP->new(join(':', @v6));
    255 
    256   my $domid = DNSDB::_hostparent($dbh, $fqdn);
    257   if ($domid) {
    258     $recsth->execute($domid, 0, $fqdn, $type, $val->addr, 0, 0, 0, $ttl) if $domid;
    259   } else {
    260     push @deferred, $rec unless $nodefer;
    261   }
    262 
    263 } else {
    264   # ... uhhh, dunno
    265 }
     583        my $domid = DNSDB::_hostparent($dbh, $fqdn);
     584        if ($domid) {
     585          $recsth->execute($domid, 0, $fqdn, 33, $target, $prio, $weight, $port, $ttl, $loc) if $domid;
     586        } else {
     587          push @deferred, $rec unless $nodefer;
     588          $impok = 0;
     589        }
     590
     591      } elsif ($type == 28) {
     592        # AAAA
     593        my @v6;
     594
     595        for (my $i=0; $i < 8; $i++) {
     596          my @tmp = _byteparse(\$rdata, 2);
     597          push @v6, sprintf("%0.4x", $tmp[0] * 256 + $tmp[1]);
     598        }
     599        my $val = NetAddr::IP->new(join(':', @v6));
     600
     601        my $fparent = DNSDB::_hostparent($dbh, $fqdn);
     602        if ($fparent) {
     603          $recsth->execute($fparent, 0, $fqdn, 28, $val->addr, 0, 0, 0, $ttl, $loc);
     604        } else {
     605          push @deferred, $rec unless $nodefer;
     606          $impok = 0;
     607        }
     608
     609      } elsif ($type == 16) {
     610        # TXT
     611        my $txtstring = _rdata2string($rdata);
     612
     613        if ($fqdn =~ /\.arpa$/) {
     614          ($code,$msg) = DNSDB::_zone2cidr($fqdn);
     615          my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
     616          if ($rparent) {
     617            $recsth->execute(0, $rparent, $txtstring, 16, "$msg", 0, 0, 0, $ttl, $loc);
     618          } else {
     619            push @deferred, $rec unless $nodefer;
     620            $impok = 0;
     621          }
     622        } else {
     623          my $domid = DNSDB::_hostparent($dbh, $fqdn);
     624          if ($domid) {
     625            $recsth->execute($domid, 0, $fqdn, 16, $txtstring, 0, 0, 0, $ttl, $loc);
     626          } else {
     627            push @deferred, $rec unless $nodefer;
     628            $impok = 0;
     629          }
     630        }
     631
     632      } elsif ($type == 17) {
     633        # RP
     634        my ($email, $txtrec) = split /\\000/, $rdata;
     635        $email =~ s/\\\d{3}/./g;
     636        $email =~ s/^\.//;
     637        $txtrec =~ s/\\\d{3}/./g;
     638        $txtrec =~ s/^\.//;
     639
     640        # these might actually make sense in a reverse zone...  sort of.
     641        if ($fqdn =~ /\.arpa$/) {
     642          ($code,$msg) = DNSDB::_zone2cidr($fqdn);
     643          my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
     644          if ($rparent) {
     645            $recsth->execute(0, $rparent, "$email $txtrec", 17, "$msg", 0, 0, 0, $ttl, $loc);
     646          } else {
     647            push @deferred, $rec unless $nodefer;
     648            $impok = 0;
     649          }
     650        } else {
     651          my $domid = DNSDB::_hostparent($dbh, $fqdn);
     652          if ($domid) {
     653            $recsth->execute($domid, 0, $fqdn, 17, "$email $txtrec", 0, 0, 0, $ttl, $loc);
     654          } else {
     655            push @deferred, $rec unless $nodefer;
     656            $impok = 0;
     657          }
     658        }
     659
     660      } elsif ($type == 44) {
     661        # SSHFP
     662        my $sshfp = _byteparse(\$rdata, 1);
     663        $sshfp .= " "._byteparse(\$rdata, 1);
     664        $sshfp .= " "._rdata2hex($rdata);
     665
     666        # these do not make sense in a reverse zone, since they're logically attached to an A record
     667        my $domid = DNSDB::_hostparent($dbh, $fqdn);
     668        if ($domid) {
     669          $recsth->execute($domid, 0, $fqdn, 44, $sshfp, 0, 0, 0, $ttl, $loc);
     670        } else {
     671          push @deferred, $rec unless $nodefer;
     672          $impok = 0;
     673        }
     674
     675      } else {
     676        print "unhandled rec $rec\n";
     677        $impok = 0;
     678        # ... uhhh, dunno
     679      }
    266680
    267681    } else {
    268682      $cnt{other}++;
    269   print " $_\n";
     683      print " $_\n";
    270684    }
    271   }
     685
     686    return $impok;      # just to make sure
     687  } # recslurp()
    272688
    273689  close FLAT;
Note: See TracChangeset for help on using the changeset viewer.