Index: /trunk/DNSDB/ExportBIND.pm
===================================================================
--- /trunk/DNSDB/ExportBIND.pm	(revision 874)
+++ /trunk/DNSDB/ExportBIND.pm	(revision 875)
@@ -203,11 +203,14 @@
   $soasth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".
 	"FROM records WHERE domain_id=? AND type=6");
-  # record order doesn't strictly matter, but ordering by conventional zone
-  # file order doesn't really have a lever without tweaking the table structure.
+  # record order needs to match reverse zone ordering for IP values, or A+PTR
+  # template records don't cascade/expand correctly to match the reverse zones.
+  # order by record_id at least makes the zone consistent from export to export,
+  # otherwise the records could (theoretically) be returned in any old order by
+  # the DB engine
   # ordering by nominal parent-child label hierarchy (as actually found live
-  # in some AXFRed zone files) would be even hairier.
-  # ordering by record_id has the advantage of consistent order export to export
+  # in some AXFRed zone files) would take a lot of chewing on data
   $recsth = $dnsdb->{dbh}->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location,extract(epoch from stamp),expires,stampactive ".
-	"FROM records WHERE domain_id=? AND NOT type=6 ORDER BY record_id");
+	"FROM records WHERE domain_id=? AND NOT type=6 ".
+	"ORDER BY masklen(inetlazy(val)) DESC, inetlazy(val), record_id");
 #      "FROM records WHERE domain_id=? AND type < 65280");     # Just exclude all types relating to rDNS
 
@@ -303,5 +306,7 @@
       $recsth->execute($domid);
       while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc,$stamp,$expires,$stampactive) = $recsth->fetchrow_array) {
+##work  need more subtle check - $recflags{$val} eq 'ptr' maybe?
         next if $recflags{$recid};
+#next if $recflags{$val} && $type == 65280;# && !$dnsdb->{template_always_publish_a};
 
         # Spaces are evil.
@@ -533,5 +538,8 @@
 
   elsif ($typemap{$type} eq 'PTR') {
-    $$recflags{$val}++;
+#    $$recflags{$val}++;
+       # maybe track exclusions like this?  so we can publish "all
+       # A and/or PTR records" irrespective of template records
+    $$recflags{$val} = 'ptr';
     if ($revrec eq 'y') {
 
@@ -576,8 +584,11 @@
     # Recurse to PTR or A as appropriate because BIND et al don't share
     # the tinydns concept of merged forward/reverse records
-    $$recflags{$val}++;
+# %recflags gets updated in the PTR branch just above
+#    $$recflags{$val}++;
     if ($revrec eq 'y') {
       publishrec_bind($zonefiles, $loclist, $recid, $revrec, $recflags, $zone, $host, 12, $val, $distance, $weight, $port, $ttl,
        $loc, $stamp, $expires, $stampactive);
+# ... but we need to tweak it for this case?  so the A record gets published...
+#$$recflags{$val} = 'a+ptr';
 #print {$zonefiles->{$loc}} "=$host:$val:$ttl:$stamp:$loc\n" or die $!;
 #          publishrec_bind(\%zonefiles, $recid, 'y', \@loclist, $revzone,
@@ -587,5 +598,7 @@
     } else {
       publishrec_bind($zonefiles, $loclist, $recid, $revrec, $recflags, $zone, $host, 1, $val, $distance, $weight, $port, $ttl,
-       $loc, $stamp, $expires, $stampactive);
+        $loc, $stamp, $expires, $stampactive);
+      # set a unique flag to skip template expansion for this IP in forward zones
+      $$recflags{$val} = 'a';
     }
   } # A+PTR
@@ -638,5 +651,7 @@
   my $stamp = shift;
   my $loc = shift;
-  my $zone = new NetAddr::IP shift;
+  my $zpass = shift;
+  my $zone = new NetAddr::IP $zpass;
+#  my $zone = new NetAddr::IP shift;
   my $revrec = shift || 'y';
 #  my $ptrflag = shift || 0;    ##fixme:  default to PTR instead of A record for the BIND variant of this sub?
@@ -657,6 +672,23 @@
     # %blank% also needs to be per-IP here to properly cascade overrides with
     # multiple nested templates
-    next if $$recflags{$ip}; # && $self->{skip_bcast_255}
-    $$recflags{$ip}++;
+#    next if $$recflags{$ip}; # && $self->{skip_bcast_255}
+
+#    next if $$recflags{$ip} && ($$recflags{$ip} eq 'ptr' || $$recflags{$ip} eq 'a+ptr');
+
+    if ($revrec eq 'y') {
+      next if $$recflags{$ip};  # blanket exclusion;  we do reverse records first
+    } else {
+##fixme:  A record side templates not cascading correctly
+      # excluding ptr does NOT work, as it excludes ALL previously covered A+PTR template entries.
+      # we only want to exclude the singleton (A+)PTR ones
+      #if ($$recflags{$ip} && ($$recflags{$ip} eq 'a' || $$recflags{$ip} eq 'ptr')) {
+      if ($$recflags{$ip} && ($$recflags{$ip} eq 'a' || $$recflags{$ip} eq 'atemplate' || $$recflags{$ip} eq 'ptr')) {
+        # default skip case
+        next;
+      }
+    } # revrec branch for skipping template member expansion
+
+    # set a forward/reverse-unique flag in %recflags
+    $$recflags{$ip} = ($revrec eq 'y' ? 'ptrtemplate' : 'atemplate');
     next if $hpat eq '%blank%';
 
