Changeset 459


Ignore:
Timestamp:
01/22/13 17:24:43 (12 years ago)
Author:
Kris Deugau
Message:

/trunk

Flesh out last known subcases of record update/delete required
for IPDB RPC service. See #43.

  • Add new sub delByCIDR(). Requires new DNSDB::downconvert utility sub.
  • Use a new variable instead of overwriting $args{cidr} in addOrUpdateRevRec()
  • Catch and another special case - adding a /32 ("netblock" or static IP) at the very beginning of a larger block in addOrUpdateRevRec()
Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB.pm

    r457 r459  
    37963796  return ($retcode, $retmsg);
    37973797} # end updateRec()
     3798
     3799
     3800## DNSDB::downconvert()
     3801# A mostly internal (not exported) semiutilty sub to downconvert from pseudotype <x>
     3802# to a compatible component type.  Only a handful of operations are valid, anything
     3803# else is a null-op.
     3804# Takes the record ID and the new type.  Returns boolean.
     3805sub downconvert {
     3806  my $dbh = shift;
     3807  my $recid = shift;
     3808  my $newtype = shift;
     3809
     3810  # also, only work on live records;  little to no value trying to do this on default records.
     3811  my $rec = getRecLine($dbh, 'n', 'y', $recid);
     3812
     3813  # hm?
     3814  #return 1 if !$rec;
     3815
     3816  return 1 if $rec->{type} < 65000;     # Only the reverse-record pseudotypes can be downconverted
     3817  return 1 if $rec->{type} == 65282;    # Nowhere to go
     3818
     3819  my $delpar;
     3820  my @sqlargs;
     3821  if ($rec->{type} == 65280) {
     3822    return 1 if $newtype != 1 && $newtype != 12;
     3823    $delpar = ($newtype == 1 ? 'rdns_id' : 'domain_id');
     3824    push @sqlargs, 0, $newtype, $recid;
     3825  } elsif ($rec->{type} == 65281) {
     3826    return 1 if $newtype != 28 && $newtype != 12;
     3827    $delpar = ($newtype == 28 ? 'rdns_id' : 'domain_id');
     3828    push @sqlargs, 0, $newtype, $recid;
     3829  } elsif ($rec->{type} == 65283) {
     3830    return 1 if $newtype != 65282;
     3831    $delpar = 'rdns_id';
     3832  } elsif ($rec->{type} == 65284) {
     3833    return 1 if $newtype != 65282;
     3834    $delpar = 'rdns_id';
     3835  } else {
     3836    # Your llama is on fire.
     3837  }
     3838
     3839  local $dbh->{AutoCommit} = 0;
     3840  local $dbh->{RaiseError} = 1;
     3841
     3842  eval {
     3843    $dbh->do("UPDATE records SET $delpar = ?, type = ? WHERE record_id = ?", undef, @sqlargs);
     3844    $dbh->commit;
     3845  };
     3846  if ($@) {
     3847    $errstr = $@;
     3848    eval { $dbh->rollback; };
     3849    return 0;
     3850  }
     3851  return 1;
     3852} # end downconvert()
    37983853
    37993854
  • trunk/dns-rpc.cgi

    r454 r459  
    6565        'dnsdb.addOrUpdateRevRec'       => \&addOrUpdateRevRec,
    6666        'dnsdb.delRec'          => \&delRec,
     67        'dnsdb.delByCIDR'       => \&delByCIDR,
    6768#sub getLogCount {}
    6869#sub getLogEntries {}
     
    434435
    435436  _commoncheck(\%args, 'y');
    436   $args{cidr} = new NetAddr::IP $args{cidr};
     437  my $cidr = new NetAddr::IP $args{cidr};
    437438
    438439  my $zonelist = DNSDB::getZonesByCIDR($dbh, %args);
     
    442443    # check if the single zone returned is bigger than the CIDR.  if so, we can just add a record
    443444    my $zone = new NetAddr::IP $zonelist->[0]->{revnet};
    444     if ($zone->contains($args{cidr})) {
     445    if ($zone->contains($cidr)) {
    445446      # We need to strip the CIDR mask on IPv4 /32 assignments, or we just add a new record all the time.
    446       my $filt = ($args{cidr}->{isv6} || $args{cidr}->masklen != 32 ? "$args{cidr}" : $args{cidr}->addr);
     447      my $filt = ($cidr->{isv6} || $cidr->masklen != 32 ? "$cidr" : $cidr->addr);
    447448      my $reclist = DNSDB::getDomRecs($dbh, defrec => 'n', revrec => 'y',
    448449        id => $zonelist->[0]->{rdns_id}, filter => $filt);
    449450      if (scalar(@$reclist) == 0) {
    450451        # Aren't Magic Numbers Fun?  See pseudotype list in dnsadmin.
    451         my $type = ($args{cidr}->{isv6} ? 65282 : ($args{cidr}->masklen == 32 ? 65280 : 65283) );
     452        my $type = ($cidr->{isv6} ? 65282 : ($cidr->masklen == 32 ? 65280 : 65283) );
    452453        addRec(defrec =>'n', revrec => 'y', parent_id => $zonelist->[0]->{rdns_id}, type => $type,
    453           address => "$args{cidr}", %args);
     454          address => "$cidr", %args);
    454455      } else {
     456        my $flag = 0;
    455457        foreach my $rec (@$reclist) {
    456458          # pure PTR plus composite types
     
    460462          updateRec(defrec =>'n', revrec => 'y', id => $rec->{record_id},
    461463            parent_id => $zonelist->[0]->{rdns_id}, %args);
     464          $flag = 1;
    462465          last; # only do one record.
     466        }
     467        unless ($flag) {
     468          # Nothing was updated, so we didn't really have a match.  Add as per @$reclist==0
     469          # Aren't Magic Numbers Fun?  See pseudotype list in dnsadmin.
     470          my $type = ($cidr->{isv6} ? 65282 : ($cidr->masklen == 32 ? 65280 : 65283) );
     471          addRec(defrec =>'n', revrec => 'y', parent_id => $zonelist->[0]->{rdns_id}, type => $type,
     472            address => "$cidr", %args);
    463473        }
    464474      }
     
    501511}
    502512
     513sub delByCIDR {
     514  my %args = @_;
     515
     516  _commoncheck(\%args, 'y');
     517
     518  # much like addOrUpdateRevRec()
     519  my $zonelist = DNSDB::getZonesByCIDR($dbh, %args);
     520  my $cidr = new NetAddr::IP $args{cidr};
     521
     522  if (scalar(@$zonelist) == 0) {
     523    # enhh....  WTF?
     524  } elsif (scalar(@$zonelist) == 1) {
     525
     526    # check if the single zone returned is bigger than the CIDR
     527    my $zone = new NetAddr::IP $zonelist->[0]->{revnet};
     528    if ($zone->contains($cidr)) {
     529
     530      if ($args{delsubs}) {
     531        # Delete ALL EVARYTHING!!one11!! in $args{cidr}
     532        my $reclist = DNSDB::getDomRecs($dbh, defrec => 'n', revrec => 'y', id => $zonelist->[0]->{rdns_id});
     533        foreach my $rec (@$reclist) {
     534          my $reccidr = new NetAddr::IP $rec->{val};
     535          next unless $cidr->contains($reccidr);
     536          ##fixme:  multiple records, wanna wax'em all, how to report errors?
     537          if ($args{delforward} ||
     538              $rec->{type} == 12 || $rec->{type} == 65282 ||
     539              $rec->{type} == 65283 || $rec->{type} == 65284) {
     540            my ($code,$msg) = DNSDB::delRec($dbh, 'n', 'y', $rec->{record_id});
     541          } else {
     542            my $ret = DNSDB::downconvert($dbh, $rec->{record_id}, $DNSDB::reverse_typemap{A});
     543          }
     544        }
     545
     546      } else {
     547        # Selectively delete only exact matches on $args{cidr}
     548
     549        # We need to strip the CIDR mask on IPv4 /32 assignments, or we can't find single-IP records
     550        my $filt = ($cidr->{isv6} || $cidr->masklen != 32 ? "$cidr" : $cidr->addr);
     551        my $reclist = DNSDB::getDomRecs($dbh, defrec => 'n', revrec => 'y',
     552          id => $zonelist->[0]->{rdns_id}, filter => $filt, sortby => 'val', sortorder => 'DESC');
     553        foreach my $rec (@$reclist) {
     554          my $reccidr = new NetAddr::IP $rec->{val};
     555          next unless $cidr == $reccidr;
     556          if ($args{delforward} || $rec->{type} == 12) {
     557            my ($code,$msg) = DNSDB::delRec($dbh, 'n', 'y', $rec->{record_id});
     558            die $msg if $code eq 'FAIL';
     559            return $msg;
     560          } else {
     561            my $ret = DNSDB::downconvert($dbh, $rec->{record_id}, $DNSDB::reverse_typemap{A});
     562            die $DNSDB::errstr if !$ret;
     563            return "A+PTR for $args{cidr} split and PTR removed";
     564          }
     565        } # foreach @$reclist
     566      }
     567
     568    } else {  # $cidr > $zone but we only have one zone
     569      # ebbeh?  CIDR is only partly represented in DNS.  This needs manual intervention.
     570      return "Warning:  $args{cidr} is only partly represented in DNS.  Check and remove DNS records manually.";
     571    } # done single-zone-contains-$cidr
     572
     573  } else {  # multiple zones nominally "contain" $cidr
     574    # Overlapping reverse zones shouldn't be possible, so if we're here we've got a CIDR
     575    # that spans multiple reverse zones (eg, /23 CIDR -> 2 /24 rzones)
     576    foreach my $zdata (@$zonelist) {
     577      my $reclist = DNSDB::getDomRecs($dbh, defrec => 'n', revrec => 'y',
     578        id => $zdata->{rdns_id}, filter => $zdata->{revnet});
     579      if (scalar(@$reclist) == 0) {
     580        my $type = ($args{cidr}->{isv6} ? 65282 : ($args{cidr}->masklen == 32 ? 65280 : 65283) );
     581        addRec(defrec =>'n', revrec => 'y', parent_id => $zdata->{rdns_id}, type => $type,
     582          address => "$args{cidr}", %args);
     583      } else {
     584        foreach my $rec (@$reclist) {
     585          # only the composite and/or template types;  pure PTR or nontemplate composite
     586          # types are nominally impossible here.
     587          next unless $rec->{type} == 65282 || $rec->{type} == 65283 || $rec->{type} == 65284;
     588          updateRec(defrec =>'n', revrec => 'y', id => $rec->{record_id},
     589            parent_id => $zdata->{rdns_id}, %args);
     590          last; # only do one record.
     591        } # foreach @$reclist
     592      }
     593    } # iterate zones within $cidr
     594  } # done $cidr-contains-zones
     595
     596} # end delByCIDR()
     597
    503598#sub getLogCount {}
    504599#sub getLogEntries {}
Note: See TracChangeset for help on using the changeset viewer.