Changeset 307


Ignore:
Timestamp:
04/17/12 18:09:44 (12 years ago)
Author:
Kris Deugau
Message:

/trunk

Fix a taint mode gotcha in _zone2cidr(), introduced with the
extension in r304 for supporting both range and netmask-based
sub-octet reverse zone names

Finalize updates to importAXFR() for reverse zones (see #26) and
action logging (see #35).
Includes some commented code and stubbery to do more complex handling
of NS and CNAME records for sub-octet subzones in revzones, probably
hinging on introducing a new pseudotype "DELEGATE"

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB.pm

    r304 r307  
    877877    # Alternate form:  The second number is actually the real netmask, not the end of the range.
    878878    my $masklen = 0;
    879     if ($octs[0] =~ /(\d+)-(\d+)/) {    # take the range...
    880       if (24 < $2 && $2 < 31) {
     879    if ($octs[0] =~ /^((\d+)-(\d+))$/) {        # take the range...
     880      if (24 < $3 && $3 < 31) {
    881881        # we have a real netmask
    882         $masklen = -$maskmap{$2};
     882        $masklen = -$maskmap{$3};
    883883      } else {
    884884        # we have a range.  NB:  only real CIDR ranges are supported
    885         $masklen -= $maskmap{-(eval $octs[0])}; # find the mask base...
     885        $masklen -= $maskmap{-(eval $1)};       # find the mask base...
    886886      }
    887       $octs[0] = $1;    # set the base octet of the range...
     887      $octs[0] = $2;    # set the base octet of the range...
    888888    }
    889889    @octs = reverse @octs;      # We can reverse the octet pieces now that we've extracted and munged any ranges
     
    33263326        $rechost .= ":" if ++$nc % 4 == 0 && $nc < 32;
    33273327      }
    3328 $rechost .= ":" if $nc < 32 && $rechost !~ /\*$/;       # close netblock records?
    3329 print "$rechost\n";
     3328      $rechost .= ":" if $nc < 32 && $rechost !~ /\*$/; # close netblock records?
     3329##fixme:  there's a case that ends up with a partial entry here:
     3330# ip:add:re:ss::
     3331# can't reproduce after letting it sit overnight after discovery.  :(
     3332#print "$rechost\n";
    33303333      # canonicalize with NetAddr::IP
    33313334      $rechost = NetAddr::IP->new($rechost)->addr unless $rechost =~ /\*$/;
     
    33753378        " VALUES (?,?,?,?,?,?,?,?,?)");
    33763379
     3380    # Stash info about sub-octet v4 revzones here so we don't have
     3381    # to store the CNAMEs used to delegate a suboctet zone
     3382    # $suboct{zone}{ns}[] -> array of nameservers
     3383    # $suboct{zone}{cname}[] -> array of extant CNAMEs (Just In Case someone did something bizarre)
     3384## commented pending actual use of this data.  for now, we'll just
     3385## auto-(re)create the CNAMEs in revzones on export
     3386#    my %suboct;
     3387
    33773388    while (my $rr = $res->axfr_next()) {
    33783389
     
    34233434          $host = $rr->nsdname;
    34243435          $logfrag = "Added record '$val $type $host', TTL $ttl";
     3436# Tag and preserve.  For now this is commented for a no-op, but we have Ideas for
     3437# another custom storage type ("DELEGATE") that will use these subzone-delegation records
     3438#if ($val ne "$cidr") {
     3439#  push @{$suboct{$val}{ns}}, $host;
     3440#}
    34253441        } else {
    34263442          $val = $rr->nsdname;
     
    34343450          ($host,$val) = _revswap($host,$rr->cname);
    34353451          $logfrag = "Added record '$val $type $host', TTL $ttl";
     3452# Tag and preserve in case we want to commit them as-is later, but mostly we don't care.
     3453# Commented pending actually doing something with possibly new type DELEGATE
     3454#my $tmprev = $host;
     3455#$tmprev =~ s/^\d+\.//;
     3456#($code,$tmprev) = _zone2cidr($tmprev);
     3457#push @{$suboct{"$tmprev"}{cname}}, $val;
     3458          # Silently skip CNAMEs in revzones.
     3459          next;
    34363460        } else {
    34373461          $val = $rr->cname;
     
    34393463      } elsif ($type eq 'SOA') {
    34403464        next if $rwsoa;
    3441         $host = $rr->mname.":".$rr->rname;
     3465        $host = $rr->rname.":".$rr->mname;
    34423466        $val = $rr->refresh.":".$rr->retry.":".$rr->expire.":".$rr->minimum;
    34433467        $soaflag = 1;
     
    34553479# rdatastr returns a BIND-targetted logical string, including opening and closing quotes
    34563480# char_str_list returns a list of the individual string fragments in the record
    3457 # txtdata returns the more useful all-in-one form.
     3481# txtdata returns the more useful all-in-one form (since we want to push such protocol
     3482# details as far down the stack as we can)
    34583483# NB:  this may turn out to be more troublesome if we ever have need of >512-byte TXT records.
    34593484        if ($rev eq 'y') {
     
    34853510      my $logentry = "[AXFR ".($rev eq 'n' ? $zone : $cidr)."] ";
    34863511
    3487 $merge = 1;
    3488 if ($merge) {
    3489   if ($rev eq 'n') {
    3490     # importing a domain;  we have A and AAAA records that could be merged with matching PTR records
    3491     my $etype;
    3492     my ($erdns,$erid,$ettl) = $dbh->selectrow_array("SELECT rdns_id,record_id,ttl FROM records ".
    3493         "WHERE host=? AND val=? AND type=12",
    3494         undef, ($host, $val) );
    3495     if ($erid) {
    3496       if ($type eq 'A') {       # PTR -> A+PTR
    3497         $etype = 65280;
    3498         $logentry .= "Merged A record with existing PTR record '$host A+PTR $val', TTL $ettl";
    3499       }
    3500       if ($type eq 'AAAA') {    # PTR -> AAAA+PTR
    3501         $etype = 65281;
    3502         $logentry .= "Merged AAAA record with existing PTR record '$host AAAA+PTR $val', TTL $ettl";
    3503       }
    3504       $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
    3505       $dbh->do("UPDATE records SET domain_id=?,ttl=?,type=? WHERE record_id=?", undef,
    3506         ($domain_id, $ettl, $etype, $erid));
    3507       $nrecs++;
    3508       _log($dbh, (group_id => $group, domain_id => $domain_id, rdns_id => $erdns, entry => $logentry) );
    3509       next;     # while axfr_next
    3510     }
    3511   } else {
    3512     # importing a revzone, we have PTR records that could be merged with matching A/AAAA records
    3513     my ($domid,$erid,$ettl,$etype) = $dbh->selectrow_array("SELECT domain_id,record_id,ttl,type FROM records ".
    3514         "WHERE host=? AND val=? AND (type=1 OR type=28)",
    3515         undef, ($host, $val) );
    3516     if ($erid) {
    3517       if ($etype == 1) {        # A -> A+PTR
    3518         $etype = 65280;
    3519         $logentry .= "Merged PTR record with existing matching A record '$host A+PTR $val', TTL $ettl";
    3520       }
    3521       if ($etype == 28) {       # AAAA -> AAAA+PTR
    3522         $etype = 65281;
    3523         $logentry .= "Merged PTR record with existing matching AAAA record '$host AAAA+PTR $val', TTL $ettl";
    3524       }
    3525       $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
    3526       $dbh->do("UPDATE records SET rdns_id=?,ttl=?,type=? WHERE record_id=?", undef,
    3527         ($rdns_id, $ettl, $etype, $erid));
    3528       $nrecs++;
    3529       _log($dbh, (group_id => $group, domain_id => $domid, rdns_id => $rdns_id, entry => $logentry) );
    3530       next;     # while axfr_next
    3531     }
    3532   }
    3533 }
     3512      if ($merge) {
     3513        if ($rev eq 'n') {
     3514          # importing a domain;  we have A and AAAA records that could be merged with matching PTR records
     3515          my $etype;
     3516          my ($erdns,$erid,$ettl) = $dbh->selectrow_array("SELECT rdns_id,record_id,ttl FROM records ".
     3517                "WHERE host=? AND val=? AND type=12",
     3518                undef, ($host, $val) );
     3519          if ($erid) {
     3520            if ($type eq 'A') { # PTR -> A+PTR
     3521              $etype = 65280;
     3522              $logentry .= "Merged A record with existing PTR record '$host A+PTR $val', TTL $ettl";
     3523            }
     3524            if ($type eq 'AAAA') {      # PTR -> AAAA+PTR
     3525              $etype = 65281;
     3526              $logentry .= "Merged AAAA record with existing PTR record '$host AAAA+PTR $val', TTL $ettl";
     3527            }
     3528            $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
     3529            $dbh->do("UPDATE records SET domain_id=?,ttl=?,type=? WHERE record_id=?", undef,
     3530                ($domain_id, $ettl, $etype, $erid));
     3531            $nrecs++;
     3532            _log($dbh, (group_id => $group, domain_id => $domain_id, rdns_id => $erdns, entry => $logentry) );
     3533            next;       # while axfr_next
     3534          }
     3535        } # $rev eq 'n'
     3536        else {
     3537          # importing a revzone, we have PTR records that could be merged with matching A/AAAA records
     3538          my ($domid,$erid,$ettl,$etype) = $dbh->selectrow_array("SELECT domain_id,record_id,ttl,type FROM records ".
     3539                "WHERE host=? AND val=? AND (type=1 OR type=28)",
     3540                undef, ($host, $val) );
     3541          if ($erid) {
     3542            if ($etype == 1) {  # A -> A+PTR
     3543              $etype = 65280;
     3544              $logentry .= "Merged PTR record with existing matching A record '$host A+PTR $val', TTL $ettl";
     3545            }
     3546            if ($etype == 28) { # AAAA -> AAAA+PTR
     3547              $etype = 65281;
     3548              $logentry .= "Merged PTR record with existing matching AAAA record '$host AAAA+PTR $val', TTL $ettl";
     3549            }
     3550            $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
     3551            $dbh->do("UPDATE records SET rdns_id=?,ttl=?,type=? WHERE record_id=?", undef,
     3552                ($rdns_id, $ettl, $etype, $erid));
     3553            $nrecs++;
     3554            _log($dbh, (group_id => $group, domain_id => $domid, rdns_id => $rdns_id, entry => $logentry) );
     3555            next;       # while axfr_next
     3556          }
     3557        } # $rev eq 'y'
     3558      } # if $merge
    35343559
    35353560      # Insert the new record
     
    35583583    } # while axfr_next
    35593584
     3585# Detect and handle delegated subzones
     3586# Placeholder for when we decide what to actually do with this, see previous comments in NS and CNAME handling.
     3587#foreach (keys %suboct) {
     3588#  print "found ".($suboct{$_}{ns} ? @{$suboct{$_}{ns}} : '0')." NS records and ".
     3589#       ($suboct{$_}{cname} ? @{$suboct{$_}{cname}} : '0')." CNAMEs for $_\n";
     3590#}
     3591
    35603592    # Overwrite SOA record
    35613593    if ($rwsoa) {
     
    35883620    die "Bad zone:  No NS records!\n" if !$nsflag;
    35893621
    3590 #die "horribly\n";
    35913622    $dbh->commit;
    35923623
Note: See TracChangeset for help on using the changeset viewer.