Changeset 337


Ignore:
Timestamp:
05/25/12 17:31:09 (13 years ago)
Author:
Kris Deugau
Message:

/trunk

Checkpoint updating export for reverse DNS. See #26.

  • _template4_expand moved up to join its relatives _ZONE and _zone2cidr
  • SOA export updated to properly output multiple real SOA records if a logical v4 reverse zone is not octet-aligned
  • PTR template and A+PTR template should now be complete
  • Zone and record SELECTs updated so that records are retrieved in an order that lets us export the more specific records first so we can exclude those IPs from the 1->many template record expansion

SOA and (A+)PTR template changes should probably be tested
further for odd edge cases

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB.pm

    r336 r337  
    957957  return ('OK', $cidr);
    958958} # done _zone2cidr()
     959
     960# Record template %-parameter expansion, IPv4.  Note that IPv6 doesn't
     961# really have a sane way to handle this type of expansion at the moment
     962# due to the size of the address space.
     963# Takes a reference to a template string to be expanded, and an IP to use in the replacement.
     964sub _template4_expand {
     965  my $tmpl = shift;
     966  my $ip = shift;
     967
     968  my @ipparts = split /\./, $ip;
     969  my @iphex;
     970  my @ippad;
     971  for (@ipparts) {
     972    push @iphex, sprintf("%x", $_);
     973    push @ippad, sprintf("%u.3", $_);
     974  }
     975
     976  # IP substitutions in template records:
     977  #major patterns:
     978  #dashed IP, forward and reverse
     979  #dotted IP, forward and reverse (even if forward is... dumb)
     980  # -> %r for reverse, %i for forward, leading - or . to indicate separator, defaults to -
     981  # %r or %-r   => %4d-%3d-%2d-%1d
     982  # %.r         => %4d.%3d.%2d.%1d
     983  # %i or %-i   => %1d-%2d-%3d-%4d
     984  # %.i         => %1d.%2d.%3d.%4d
     985  $$tmpl =~ s/\%r/\%4d-\%3d-\%2d-\%1d/g;
     986  $$tmpl =~ s/\%([-.])r/\%4d$1\%3d$1\%2d$1\%1d/g;
     987  $$tmpl =~ s/\%i/\%1d-\%2d-\%3d-\%4d/g;
     988  $$tmpl =~ s/\%([-.])i/\%1d$1\%2d$1\%3d$1\%4d/g;
     989
     990  #hex-coded IP
     991  # %h
     992  $$tmpl =~ s/\%h/$iphex[0]$iphex[1]$iphex[2]$iphex[3]/g;
     993
     994  #IP as decimal-coded 32-bit value
     995  # %d
     996  my $iptmp = $ipparts[0]*256*256*256 + $ipparts[1]*256*256 + $ipparts[2]*256 + $ipparts[3];
     997  $$tmpl =~ s/\%d/$iptmp/g;
     998
     999  #minor patterns (per-octet)
     1000  # %[1234][dh0]
     1001  #octet
     1002  #hex-coded octet
     1003  #0-padded octet
     1004  $$tmpl =~ s/\%([1234])d/$ipparts[$1-1]/g;
     1005  $$tmpl =~ s/\%([1234])h/$iphex[$1-1]/g;
     1006  $$tmpl =~ s/\%([1234])h/$ippad[$1-1]/g;
     1007} # _template4_expand()
    9591008
    9601009
     
    39964045  } # while ($domsth)
    39974046
    3998   my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status FROM revzones WHERE status=1");
     4047  my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status FROM revzones WHERE status=1 ".
     4048        "ORDER BY masklen(revnet) DESC");
    39994049  $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id ".
    4000         "FROM records WHERE rdns_id=?");
     4050        "FROM records WHERE rdns_id=? AND type=6 UNION ".
     4051        "(SELECT host,type,val,distance,weight,port,ttl,record_id ".
     4052        "FROM records WHERE rdns_id=? AND not type=6 ".
     4053        "ORDER BY masklen(CAST(val AS inet)) DESC, CAST(val AS inet))");
    40014054  $revsth->execute();
    40024055  while (my ($revid,$revzone,$revstat) = $revsth->fetchrow_array) {
    4003     $recsth->execute($revid);
     4056    $recsth->execute($revid, $revid);
    40044057    while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid) = $recsth->fetchrow_array) {
    40054058      next if $recflags{$recid};
     
    40484101        my ($refresh, $retry, $expire, $min_ttl) = (split /:/, $val)[0,1,2,3];
    40494102        if ($revrec eq 'y') {
     4103##fixme:  have to publish SOA records for each v4 /24 in sub-/16, and each /16 in sub-/8
     4104# what about v6?
     4105# -> only need SOA for local chunks offset from reverse delegation boundaries, so v6 is fine
    40504106          $zone = NetAddr::IP->new($zone);
     4107          # handle split-n-multiply SOA for off-octet (8 < mask < 16) or (16 < mask < 24) v4 zones
     4108          if (!$zone->{isv6} && ($zone->masklen < 24) && ($zone->masklen % 8 != 0)) {
     4109            foreach my $szone ($zone->split($zone->masklen + (8 - $zone->masklen % 8))) {
     4110              $szone = _ZONE($szone, 'ZONE.in-addr.arpa', 'r', '.');
     4111              print $datafile "Z$szone:$primary:$email"."::$refresh:$retry:$expire:$min_ttl:$ttl:$stamp:$loc\n";
     4112            }
     4113            return; # skips "default" bits just below
     4114          }
    40514115          $zone = _ZONE($zone, 'ZONE', 'r', '.').($zone->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
    40524116        }
     
    41534217
    41544218        $zone = NetAddr::IP->new($zone);
     4219        $$recflags{$val}++;
    41554220        if (!$zone->{isv6} && $zone->masklen > 24) {
    41564221          ($val) = ($val =~ /\.(\d+)$/);
     
    41664231      } elsif ($type == 65280) { # A+PTR
    41674232
     4233        $$recflags{$val}++;
    41684234        print $datafile "=$host:$val:$ttl:$stamp:$loc\n";
    41694235
    41704236      } elsif ($type == 65281) { # AAAA+PTR
    41714237
     4238#$$recflags{$val}++;
    41724239        # treat these as two separate records.  since tinydns doesn't have
    41734240        # a native combined type, we have to create them separately anyway.
     
    41834250      } elsif ($type == 65282) { # PTR template
    41844251
     4252##work
    41854253        # only useful for v4 with standard DNS software, since this expands all
    41864254        # IPs in $zone (or possibly $val?) with autogenerated records
    4187 
    4188 ##work
    4189 use Data::Dumper;
    4190 $zone = NetAddr::IP->new($zone);
    4191 if (!$zone->{isv6}) {
    4192   $val = NetAddr::IP->new($val);
    4193   if ($zone == $val) {
    4194     my $iplist = $zone->hostenumref;
    4195     foreach (@$iplist) {
    4196       my $rec = $host;
    4197       _template4_expand(\$rec, $_->addr);
    4198       print "$_ ptr $rec\n";
    4199     }
    4200   } else {
    4201   }
    4202 }
    4203 
    4204 sub _template4_expand {
    4205   my $tmpl = shift;
    4206   my $ip = shift;
    4207 
    4208   my @ipparts = split /\./, $ip;
    4209   my @iphex;
    4210   my @ippad;
    4211   for (@ipparts) {
    4212     push @iphex, sprintf("%x", $_);
    4213     push @ippad, sprintf("%u.3", $_);
    4214   }
    4215 
    4216 # IP substitutions in template records:
    4217 #major patterns:
    4218 #dashed IP, forward and reverse
    4219 #dotted IP, forward and reverse (even if forward is... dumb)
    4220 # -> %r for reverse, %i for forward, leading - or . to indicate separator, defaults to -
    4221 # %r or %-r     => %4d-%3d-%2d-%1d
    4222 # %.r           => %4d.%3d.%2d.%1d
    4223 # %i or %-i     => %1d-%2d-%3d-%4d
    4224 # %.i           => %1d.%2d.%3d.%4d
    4225 
    4226   $$tmpl =~ s/\%r/\%4d-\%3d-\%2d-\%1d/g;
    4227   $$tmpl =~ s/\%([-.])r/\%4d$1\%3d$1\%2d$1\%1d/g;
    4228   $$tmpl =~ s/\%i/\%1d-\%2d-\%3d-\%4d/g;
    4229   $$tmpl =~ s/\%([-.])i/\%1d$1\%2d$1\%3d$1\%4d/g;
    4230 
    4231 #hex-coded IP
    4232 # %h
    4233   $$tmpl =~ s/\%h/$iphex[0]$iphex[1]$iphex[2]$iphex[3]/g;
    4234 
    4235 #IP as decimal-coded 32-bit value
    4236 # %d
    4237   my $iptmp = $ipparts[0]*256*256*256 + $ipparts[1]*256*256 + $ipparts[2]*256 + $ipparts[3];
    4238   $$tmpl =~ s/\%d/$iptmp/g;
    4239 
    4240 #minor patterns (per-octet)
    4241 # %[1234][dh0]
    4242 #octet
    4243 #hex-coded octet
    4244 #0-padded octet
    4245   $$tmpl =~ s/\%([1234])d/$ipparts[$1-1]/g;
    4246   $$tmpl =~ s/\%([1234])h/$iphex[$1-1]/g;
    4247   $$tmpl =~ s/\%([1234])h/$ippad[$1-1]/g;
    4248 
    4249 } # _template4_expand()
     4255        $val = NetAddr::IP->new($val);
     4256        return if $val->{isv6};
     4257
     4258        my $iplist = $val->hostenumref;
     4259        foreach (@$iplist) {
     4260          my $ip = $_->addr;
     4261          # make as if we split the non-octet-aligned block into octet-aligned blocks as with SOA
     4262          next if $ip =~ /\.(0|255)$/;
     4263          next if $$recflags{$ip};
     4264          $$recflags{$ip}++;
     4265          my $rec = $host;      # start fresh with the template for each IP
     4266          _template4_expand(\$rec, $ip);
     4267          print $datafile "^"._ZONE($_, 'ZONE.in-addr.arpa', 'r', '.').":$rec:$ttl:$stamp:$loc\n";
     4268        }
    42504269
    42514270      } elsif ($type == 65283) { # A+PTR template
    42524271
    4253 if (!$zone->{isv6}) {   # Just In Case.  An A+PTR should be impossible to add to a v6 revzone via API.
    4254 }
     4272        $val = NetAddr::IP->new($val);
     4273        # Just In Case.  An A+PTR should be impossible to add to a v6 revzone via API.
     4274        return if $val->{isv6};
     4275        my $iplist = $val->hostenumref;
     4276        foreach (@$iplist) {
     4277          my $ip = $_->addr;
     4278          # make as if we split the non-octet-aligned block into octet-aligned blocks as with SOA
     4279          next if $ip =~ /\.(0|255)$/;
     4280          next if $$recflags{$ip};
     4281          $$recflags{$ip}++;
     4282          my $rec = $host;      # start fresh with the template for each IP
     4283          _template4_expand(\$rec, $ip);
     4284          print $datafile "=$rec:$ip:$ttl:$stamp:$loc\n";
     4285        }
    42554286
    42564287      } elsif ($type == 65284) { # AAAA+PTR template
Note: See TracChangeset for help on using the changeset viewer.