Index: trunk/DNSDB.pm
===================================================================
--- trunk/DNSDB.pm	(revision 306)
+++ trunk/DNSDB.pm	(revision 307)
@@ -877,13 +877,13 @@
     # Alternate form:  The second number is actually the real netmask, not the end of the range.
     my $masklen = 0;
-    if ($octs[0] =~ /(\d+)-(\d+)/) {	# take the range...
-      if (24 < $2 && $2 < 31) {
+    if ($octs[0] =~ /^((\d+)-(\d+))$/) {	# take the range...
+      if (24 < $3 && $3 < 31) {
 	# we have a real netmask
-	$masklen = -$maskmap{$2};
+	$masklen = -$maskmap{$3};
       } else {
 	# we have a range.  NB:  only real CIDR ranges are supported
-	$masklen -= $maskmap{-(eval $octs[0])};	# find the mask base...
+	$masklen -= $maskmap{-(eval $1)};	# find the mask base...
       }
-      $octs[0] = $1;	# set the base octet of the range...
+      $octs[0] = $2;	# set the base octet of the range...
     }
     @octs = reverse @octs;	# We can reverse the octet pieces now that we've extracted and munged any ranges
@@ -3326,6 +3326,9 @@
         $rechost .= ":" if ++$nc % 4 == 0 && $nc < 32;
       }
-$rechost .= ":" if $nc < 32 && $rechost !~ /\*$/;	# close netblock records?
-print "$rechost\n";
+      $rechost .= ":" if $nc < 32 && $rechost !~ /\*$/;	# close netblock records?
+##fixme:  there's a case that ends up with a partial entry here:
+# ip:add:re:ss::
+# can't reproduce after letting it sit overnight after discovery.  :(
+#print "$rechost\n";
       # canonicalize with NetAddr::IP
       $rechost = NetAddr::IP->new($rechost)->addr unless $rechost =~ /\*$/;
@@ -3375,4 +3378,12 @@
 	" VALUES (?,?,?,?,?,?,?,?,?)");
 
+    # Stash info about sub-octet v4 revzones here so we don't have
+    # to store the CNAMEs used to delegate a suboctet zone
+    # $suboct{zone}{ns}[] -> array of nameservers
+    # $suboct{zone}{cname}[] -> array of extant CNAMEs (Just In Case someone did something bizarre)
+## commented pending actual use of this data.  for now, we'll just
+## auto-(re)create the CNAMEs in revzones on export
+#    my %suboct;
+
     while (my $rr = $res->axfr_next()) {
 
@@ -3423,4 +3434,9 @@
 	  $host = $rr->nsdname;
 	  $logfrag = "Added record '$val $type $host', TTL $ttl";
+# Tag and preserve.  For now this is commented for a no-op, but we have Ideas for
+# another custom storage type ("DELEGATE") that will use these subzone-delegation records
+#if ($val ne "$cidr") {
+#  push @{$suboct{$val}{ns}}, $host;
+#}
 	} else {
 	  $val = $rr->nsdname;
@@ -3434,4 +3450,12 @@
 	  ($host,$val) = _revswap($host,$rr->cname);
 	  $logfrag = "Added record '$val $type $host', TTL $ttl";
+# Tag and preserve in case we want to commit them as-is later, but mostly we don't care.
+# Commented pending actually doing something with possibly new type DELEGATE
+#my $tmprev = $host;
+#$tmprev =~ s/^\d+\.//;
+#($code,$tmprev) = _zone2cidr($tmprev);
+#push @{$suboct{"$tmprev"}{cname}}, $val;
+	  # Silently skip CNAMEs in revzones.
+	  next;
 	} else {
 	  $val = $rr->cname;
@@ -3439,5 +3463,5 @@
       } elsif ($type eq 'SOA') {
 	next if $rwsoa;
-	$host = $rr->mname.":".$rr->rname;
+	$host = $rr->rname.":".$rr->mname;
 	$val = $rr->refresh.":".$rr->retry.":".$rr->expire.":".$rr->minimum;
 	$soaflag = 1;
@@ -3455,5 +3479,6 @@
 # rdatastr returns a BIND-targetted logical string, including opening and closing quotes
 # char_str_list returns a list of the individual string fragments in the record
-# txtdata returns the more useful all-in-one form.
+# txtdata returns the more useful all-in-one form (since we want to push such protocol
+# details as far down the stack as we can)
 # NB:  this may turn out to be more troublesome if we ever have need of >512-byte TXT records.
 	if ($rev eq 'y') {
@@ -3485,51 +3510,51 @@
       my $logentry = "[AXFR ".($rev eq 'n' ? $zone : $cidr)."] ";
 
-$merge = 1;
-if ($merge) {
-  if ($rev eq 'n') {
-    # importing a domain;  we have A and AAAA records that could be merged with matching PTR records
-    my $etype;
-    my ($erdns,$erid,$ettl) = $dbh->selectrow_array("SELECT rdns_id,record_id,ttl FROM records ".
-	"WHERE host=? AND val=? AND type=12",
-        undef, ($host, $val) );
-    if ($erid) {
-      if ($type eq 'A') {	# PTR -> A+PTR
-	$etype = 65280;
-	$logentry .= "Merged A record with existing PTR record '$host A+PTR $val', TTL $ettl";
-      }
-      if ($type eq 'AAAA') {	# PTR -> AAAA+PTR
-	$etype = 65281;
-	$logentry .= "Merged AAAA record with existing PTR record '$host AAAA+PTR $val', TTL $ettl";
-      }
-      $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
-      $dbh->do("UPDATE records SET domain_id=?,ttl=?,type=? WHERE record_id=?", undef,
-	($domain_id, $ettl, $etype, $erid));
-      $nrecs++;
-      _log($dbh, (group_id => $group, domain_id => $domain_id, rdns_id => $erdns, entry => $logentry) );
-      next;	# while axfr_next
-    }
-  } else {
-    # importing a revzone, we have PTR records that could be merged with matching A/AAAA records
-    my ($domid,$erid,$ettl,$etype) = $dbh->selectrow_array("SELECT domain_id,record_id,ttl,type FROM records ".
-	"WHERE host=? AND val=? AND (type=1 OR type=28)",
-        undef, ($host, $val) );
-    if ($erid) {
-      if ($etype == 1) {	# A -> A+PTR
-	$etype = 65280;
-	$logentry .= "Merged PTR record with existing matching A record '$host A+PTR $val', TTL $ettl";
-      }
-      if ($etype == 28) {	# AAAA -> AAAA+PTR
-	$etype = 65281;
-	$logentry .= "Merged PTR record with existing matching AAAA record '$host AAAA+PTR $val', TTL $ettl";
-      }
-      $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
-      $dbh->do("UPDATE records SET rdns_id=?,ttl=?,type=? WHERE record_id=?", undef,
-	($rdns_id, $ettl, $etype, $erid));
-      $nrecs++;
-      _log($dbh, (group_id => $group, domain_id => $domid, rdns_id => $rdns_id, entry => $logentry) );
-      next;	# while axfr_next
-    }
-  }
-}
+      if ($merge) {
+	if ($rev eq 'n') {
+	  # importing a domain;  we have A and AAAA records that could be merged with matching PTR records
+	  my $etype;
+	  my ($erdns,$erid,$ettl) = $dbh->selectrow_array("SELECT rdns_id,record_id,ttl FROM records ".
+		"WHERE host=? AND val=? AND type=12",
+		undef, ($host, $val) );
+	  if ($erid) {
+	    if ($type eq 'A') {	# PTR -> A+PTR
+	      $etype = 65280;
+	      $logentry .= "Merged A record with existing PTR record '$host A+PTR $val', TTL $ettl";
+	    }
+	    if ($type eq 'AAAA') {	# PTR -> AAAA+PTR
+	      $etype = 65281;
+	      $logentry .= "Merged AAAA record with existing PTR record '$host AAAA+PTR $val', TTL $ettl";
+	    }
+	    $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
+	    $dbh->do("UPDATE records SET domain_id=?,ttl=?,type=? WHERE record_id=?", undef,
+		($domain_id, $ettl, $etype, $erid));
+	    $nrecs++;
+	    _log($dbh, (group_id => $group, domain_id => $domain_id, rdns_id => $erdns, entry => $logentry) );
+	    next;	# while axfr_next
+	  }
+	} # $rev eq 'n'
+	else {
+	  # importing a revzone, we have PTR records that could be merged with matching A/AAAA records
+	  my ($domid,$erid,$ettl,$etype) = $dbh->selectrow_array("SELECT domain_id,record_id,ttl,type FROM records ".
+		"WHERE host=? AND val=? AND (type=1 OR type=28)",
+		undef, ($host, $val) );
+	  if ($erid) {
+	    if ($etype == 1) {	# A -> A+PTR
+	      $etype = 65280;
+	      $logentry .= "Merged PTR record with existing matching A record '$host A+PTR $val', TTL $ettl";
+	    }
+	    if ($etype == 28) {	# AAAA -> AAAA+PTR
+	      $etype = 65281;
+	      $logentry .= "Merged PTR record with existing matching AAAA record '$host AAAA+PTR $val', TTL $ettl";
+	    }
+	    $ettl = ($ettl < $ttl ? $ettl : $ttl);    # use lower TTL
+	    $dbh->do("UPDATE records SET rdns_id=?,ttl=?,type=? WHERE record_id=?", undef,
+		($rdns_id, $ettl, $etype, $erid));
+	    $nrecs++;
+	    _log($dbh, (group_id => $group, domain_id => $domid, rdns_id => $rdns_id, entry => $logentry) );
+	    next;	# while axfr_next
+	  }
+	} # $rev eq 'y'
+      } # if $merge
 
       # Insert the new record
@@ -3558,4 +3583,11 @@
     } # while axfr_next
 
+# Detect and handle delegated subzones
+# Placeholder for when we decide what to actually do with this, see previous comments in NS and CNAME handling.
+#foreach (keys %suboct) {
+#  print "found ".($suboct{$_}{ns} ? @{$suboct{$_}{ns}} : '0')." NS records and ".
+#	($suboct{$_}{cname} ? @{$suboct{$_}{cname}} : '0')." CNAMEs for $_\n";
+#}
+
     # Overwrite SOA record
     if ($rwsoa) {
@@ -3588,5 +3620,4 @@
     die "Bad zone:  No NS records!\n" if !$nsflag;
 
-#die "horribly\n";
     $dbh->commit;
 
