Ignore:
Timestamp:
06/20/16 13:18:07 (9 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Merge /trunk through r721; minor tweaks and updates required for RPC
from IPDB

Location:
branches/stable
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/stable

  • branches/stable/dns-rpc.cgi

    r690 r725  
    137137##
    138138
     139##
     140## Internal utility subs
     141##
     142
    139143# Check RPC ACL
    140144sub _aclcheck {
     
    174178}
    175179
    176 # set ttl to zone defailt minttl if none is specified
     180# set ttl to zone default minttl if none is specified
    177181sub _ttlcheck {
    178182  my $argref = shift;
     
    182186  }
    183187}
     188
     189# Check if the hashrefs passed in refer to identical record data, so we can skip
     190# the actual update if nothing has actually changed.  This is mainly useful for
     191# reducing log noise due to chained calls orginating with updateRevSet() since
     192# "many" records could be sent for update but only one or two have actually changed.
     193sub _checkRecMod {
     194  my $oldrec = shift;
     195  my $newrec = shift;
     196
     197  # Because we don't know which fields we've even been passed
     198  no warnings qw(uninitialized);
     199
     200  my $modflag = 0;
     201  # order by most common change.  host should be first, due to rDNS RPC calls
     202  for my $field qw(host type val) {
     203    return 1 if (
     204        defined($newrec->{$field}) &&
     205        $oldrec->{$field} ne $newrec->{$field} );
     206  }
     207
     208  return 0;
     209} # _checRecMod
     210
     211
     212##
     213## Shims for DNSDB core subs
     214##
    184215
    185216#sub connectDB {
     
    215246    ($code,$msg) = $dnsdb->delZone($args{zone}, $args{revrec});
    216247  } else {
     248    die "Need zone location\n" if !defined($args{location});
    217249    my $zoneid;
    218     $zoneid = $dnsdb->domainID($args{zone}) if $args{revrec} eq 'n';
    219     $zoneid = $dnsdb->revID($args{zone}) if $args{revrec} eq 'y';
     250    $zoneid = $dnsdb->domainID($args{zone}, $args{location}) if $args{revrec} eq 'n';
     251    $zoneid = $dnsdb->revID($args{zone}, $args{location}) if $args{revrec} eq 'y';
    220252    die "Can't find zone: ".$dnsdb->errstr."\n" if !$zoneid;
    221253    ($code,$msg) = $dnsdb->delZone($zoneid, $args{revrec});
     
    233265  _commoncheck(\%args, 'y');
    234266
    235   my $domid = $dnsdb->domainID($args{domain});
     267  my $domid = $dnsdb->domainID($args{domain}, $args{location});
    236268  die $dnsdb->errstr."\n" if !$domid;
    237269  return $domid;
     
    419451  die "Missing zone ID\n" if !$args{id};
    420452
     453  # caller may not know about zone IDs.  accept the zone name, but require a location if so
     454  if ($args{id} !~ /^\d+$/) {
     455    die "Location required to use the zone name\n" if !defined($args{location});
     456  }
     457
    421458  # set some optional args
    422459  $args{offset} = 0 if !$args{offset};
     
    430467  if ($args{defrec} eq 'n') {
    431468    if ($args{revrec} eq 'n') {
    432       $args{id} = $dnsdb->domainID($args{id}) if $args{id} !~ /^\d+$/;
     469      $args{id} = $dnsdb->domainID($args{id}, $args{location}) if $args{id} !~ /^\d+$/;
    433470    } else {
    434       $args{id} = $dnsdb->revID($args{id}) if $args{id} !~ /^\d+$/
     471      $args{id} = $dnsdb->revID($args{id}, $args{location}) if $args{id} !~ /^\d+$/
    435472    }
    436473  }
     
    454491
    455492  _reccheck(\%args);
     493
     494  # caller may not know about zone IDs.  accept the zone name, but require a location if so
     495  if ($args{id} !~ /^\d+$/) {
     496    die "Location required to use the zone name\n" if !defined($args{location});
     497  }
    456498
    457499  # set some optional args
     
    462504  $args{direction} = 'ASC' if !$args{direction};
    463505
     506  # convert zone name to zone ID, if needed
     507  if ($args{defrec} eq 'n') {
     508    if ($args{revrec} eq 'n') {
     509      $args{id} = $dnsdb->domainID($args{id}, $args{location}) if $args{id} !~ /^\d+$/;
     510    } else {
     511      $args{id} = $dnsdb->revID($args{id}, $args{location}) if $args{id} !~ /^\d+$/
     512    }
     513  }
     514
     515  # fail if we *still* don't have a valid zone ID
     516  die $dnsdb->errstr."\n" if !$args{id};
     517
    464518  my $ret = $dnsdb->getRecCount(defrec => $args{defrec}, revrec => $args{revrec},
    465519        id => $args{id}, filter => $args{filter});
     
    468522
    469523  return $ret;
    470 }
     524} # getRecCount()
    471525
    472526# The core sub uses references for some arguments to allow limited modification for
     
    534588} # rpc_updateRec
    535589
     590
    536591# Takes a passed CIDR block and DNS pattern;  adds a new record or updates the record(s) affected
    537592sub addOrUpdateRevRec {
     
    541596  my $cidr = new NetAddr::IP $args{cidr};
    542597
    543 ##fixme:  Minor edge case; if we receive calls one after the other to update
    544 # to the same thing, we bulk out the log with useless notices.  Leaving this
    545 # for future development since this should be rare in practice.
     598  # Location required so we don't turn up unrelated zones in getZonesByCIDR().
     599  # Caller should generally have some knowledge of this.
     600  die "Need location\n" if !defined($args{location});
    546601
    547602  my $zonelist = $dnsdb->getZonesByCIDR(%args);
     
    552607    my $zone = new NetAddr::IP $zonelist->[0]->{revnet};
    553608    if ($zone->contains($cidr)) {
    554       # We need to strip the CIDR mask on IPv4 /32 assignments, or we just add a new record all the time.
    555       my $filt = ($cidr->{isv6} || $cidr->masklen != 32 ? "$cidr" : $cidr->addr);
    556       my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y',
     609      # We need to strip the CIDR mask on IPv4 /32 or v6 /128 assignments, or we just add a new record all the time.
     610      my $filt = ( $cidr->{isv6} ? ($cidr->masklen != 128 ? "$cidr" : $cidr->addr) :
     611                   ($cidr->masklen != 32 ? "$cidr" : $cidr->addr) );
     612      my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y',
    557613        id => $zonelist->[0]->{rdns_id}, filter => $filt);
    558614##fixme: Figure some new magic to automerge new incoming A(AAA)+PTR requests
     
    570626                || $rec->{type} == 65282 || $rec->{type} == 65283 || $rec->{type} == 65284;
    571627          next unless $rec->{val} eq $filt;     # make sure we really update the record we want to update.
     628          # canonicalize the IP values so funny IPv6 short forms don't
     629          # cause non-updates by not being literally string-equal
     630          $rec->{val} = new NetAddr::IP $rec->{val};
     631          my $tmpcidr = new NetAddr::IP $args{cidr};
     632          my %newrec = (host => $args{name}, val => $tmpcidr, type => $args{type});
    572633          rpc_updateRec(defrec =>'n', revrec => 'y', id => $rec->{record_id},
    573             parent_id => $zonelist->[0]->{rdns_id}, address => "$cidr", %args);
     634                parent_id => $zonelist->[0]->{rdns_id}, address => "$cidr", %args)
     635                if _checkRecMod($rec, \%newrec);        # and only do the update if there really is something to change
    574636          $flag = 1;
    575637          last; # only do one record.
     
    590652    # that spans multiple reverse zones (eg, /23 CIDR -> 2 /24 rzones)
    591653    foreach my $zdata (@$zonelist) {
    592       my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y',
     654      my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y',
    593655        id => $zdata->{rdns_id}, filter => $zdata->{revnet});
    594656      if (scalar(@$reclist) == 0) {
     
    597659          address => "$args{cidr}", %args);
    598660      } else {
     661        my $updflag = 0;
    599662        foreach my $rec (@$reclist) {
    600663          # only the composite and/or template types;  pure PTR or nontemplate composite
    601664          # types are nominally impossible here.
    602665          next unless $rec->{type} == 65282 || $rec->{type} == 65283 || $rec->{type} == 65284;
     666          my %newrec = (host => $args{name}, val => $zdata->{revnet}, type => $args{type});
    603667          rpc_updateRec(defrec => 'n', revrec => 'y', id => $rec->{record_id},
    604             parent_id => $zdata->{rdns_id}, %args);
     668            parent_id => $zdata->{rdns_id}, %args)
     669            if _checkRecMod($rec, \%newrec);    # and only do the update if there really is something to change
     670          $updflag = 1;
    605671          last; # only do one record.
    606672        }
    607       }
     673        # catch the case of "oops, no zone-sized template record and need to add a new one",
     674        # because the SOA and NS records will be returned from the getRecList() call above
     675        unless ($updflag) {
     676          my $type = ($cidr->{isv6} ? 65284 : 65283);
     677          rpc_addRec(defrec => 'n', revrec => 'y', parent_id => $zdata->{rdns_id}, type => $type,
     678            address => $zdata->{revnet}, %args);
     679        }
     680      } # scalar(@$reclist) != 0
    608681    } # iterate zones within $cidr
    609682  } # done $cidr-contains-zones
     
    623696    next unless $key =~ m{^host_((?:[\d.]+|[\da-f:]+)(?:/\d+)?)$};
    624697    my $ip = $1;
    625     push @ret, addOrUpdateRevRec(cidr => $ip, name => $args{$key}, %args);
    626   }
     698    push @ret, addOrUpdateRevRec(%args, cidr => $ip, name => $args{$key});
     699  }
     700
     701  # now we check the parts of the block that didn't get passed to see if they should be deleted
     702  my $block = new NetAddr::IP $args{cidr};
     703  if (!$block->{isv6}) {
     704    foreach my $ip (@{$block->splitref(32)}) {
     705      my $bare = $ip->addr;
     706      next if $args{"host_$bare"};
     707      delByCIDR(delforward => 1, delsubs => 0, cidr => $bare, location => $args{location},
     708        rpcuser => $args{rpcuser}, rpcsystem => $args{rpcsystem});
     709    }
     710  }
     711
    627712##fixme:  what about errors?  what about warnings?
    628713  return \@ret;
     
    637722
    638723  my $cidr = new NetAddr::IP $args{cidr};
     724
     725  # Location required so we don't turn up unrelated zones in getZonesByCIDR().
     726  # Caller should generally have some knowledge of this.
     727  die "Need location\n" if !defined($args{location});
    639728
    640729  my $zonelist = $dnsdb->getZonesByCIDR(%args);
     
    647736    if ($zone->contains($cidr)) {
    648737      # Find the first record in the reverse zone that matches the CIDR we're splitting...
    649       my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y',
     738      my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y',
    650739        id => $zonelist->[0]->{rdns_id}, filter => $cidr, sortby => 'val', sortorder => 'DESC');
    651740      my $oldrec;
     
    706795
    707796  my $up_res;
     797
     798  # Location required so we don't turn up unrelated zones in getZonesByCIDR().
     799  # Caller should generally have some knowledge of this.
     800  die "Need location\n" if !defined($args{location});
    708801
    709802  my $zonelist = $dnsdb->getZonesByCIDR(%args);
     
    769862  my @retlist;
    770863
    771   my $zsth = $dnsdb->{dbh}->prepare("SELECT rdns_id,group_id FROM revzones WHERE revnet >>= ?");
     864  # Location required so we don't turn up unrelated zones
     865  die "Need location\n" if !defined($args{location});
     866
     867  my $zsth = $dnsdb->{dbh}->prepare("SELECT rdns_id,group_id FROM revzones WHERE revnet >>= ? AND location = ?");
    772868  # Going to assume template records with no expiry
    773869  # Also note IPv6 template records don't expand sanely the way v4 records do
     
    792888  eval {
    793889    foreach my $template (@{$args{templates}}) {
    794       $zsth->execute($template);
     890      $zsth->execute($template, $args{location});
    795891      my ($zid,$zgrp) = $zsth->fetchrow_array;
    796892      if (!$zid) {
     
    851947  # Caller may pass 'n' in delsubs.  Assume it should be false/undefined
    852948  # unless the caller explicitly requested 'yes'
    853   $args{delsubs} = 0 if $args{delsubs} ne 'y';
     949  $args{delsubs} = 0 if !$args{delsubs} || $args{delsubs} ne 'y';
    854950
    855951  # Don't delete the A component of an A+PTR by default
    856952  $args{delforward} = 0 if !$args{delforward};
     953
     954  # Location required so we don't turn up unrelated zones in getZonesByCIDR().
     955  die "Need location\n" if !defined($args{location});
    857956
    858957  # much like addOrUpdateRevRec()
     
    869968      if ($args{delsubs}) {
    870969        # Delete ALL EVARYTHING!!one11!! in $args{cidr}
    871         my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y', id => $zonelist->[0]->{rdns_id});
     970        my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y', id => $zonelist->[0]->{rdns_id});
    872971        foreach my $rec (@$reclist) {
    873972          my $reccidr = new NetAddr::IP $rec->{val};
     
    895994        # Selectively delete only exact matches on $args{cidr}
    896995        # We need to strip the CIDR mask on IPv4 /32 assignments, or we can't find single-IP records
    897         my $filt = ($cidr->{isv6} || $cidr->masklen != 32 ? "$cidr" : $cidr->addr);
    898         my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y',
     996        my $filt = ( $cidr->{isv6} ? ($cidr->masklen != 128 ? "$cidr" : $cidr->addr) :
     997                     ($cidr->masklen != 32 ? "$cidr" : $cidr->addr) );
     998        my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y', location => $args{location},
    899999          id => $zonelist->[0]->{rdns_id}, filter => $filt, sortby => 'val', sortorder => 'DESC');
    9001000        foreach my $rec (@$reclist) {
     
    9241024    # that spans multiple reverse zones (eg, /23 CIDR -> 2 /24 rzones)
    9251025    foreach my $zdata (@$zonelist) {
    926       my $reclist = $dnsdb->getRecList(defrec => 'n', revrec => 'y', id => $zdata->{rdns_id});
     1026      my $reclist = $dnsdb->getRecList(rpc => 1, defrec => 'n', revrec => 'y', id => $zdata->{rdns_id});
    9271027      if (scalar(@$reclist) == 0) {
    9281028# nothing to do?  or do we (re)add a record based on the parent?
     
    9811081  _commoncheck(\%args, 'y');
    9821082
    983   return $dnsdb->getRevPattern($args{cidr}, $args{group});
     1083  return $dnsdb->getRevPattern($args{cidr}, location => $args{location}, group => $args{group});
    9841084}
    9851085
     
    9891089  _commoncheck(\%args, 'y');
    9901090
    991   return $dnsdb->getRevSet($args{cidr}, $args{group});
     1091  return $dnsdb->getRevSet($args{cidr}, location => $args{location}, group => $args{group});
    9921092}
    9931093
Note: See TracChangeset for help on using the changeset viewer.