- Timestamp:
- 01/22/26 18:21:37 (6 days ago)
- Location:
- branches/cname-collision
- Files:
-
- 1 added
- 1 edited
-
DNSDB.pm (modified) (2 diffs)
-
collision-truth-table.ods (added)
Legend:
- Unmodified
- Added
- Removed
-
branches/cname-collision/DNSDB.pm
r995 r996 645 645 foreach my $tcompare ('<>', '=') { 646 646 next if $tcompare eq '<>' && ${$args{rectype}} != 5; 647 648 # Merging these sets of SQL statements is far too messy and doesn't reasonably 649 # allow for more fine-grained error/warning messages to be returned 650 651 # First lookup fails out collisions with records without timestamps or default records (which can not have timestamps) 647 652 my $sql = "SELECT count(*) FROM "._rectable($args{defrec}, $args{revrec}). 648 653 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?"; 649 if ($args{defrec} eq 'n') {650 # Expired records651 $sql .= " AND (stampactive = 'f' OR (stampactive = 't' AND (expires = 't' AND stamp >= now())))";652 }653 654 my @lookupargs = ($args{id}, $hcheck); 655 $sql .= " AND stampactive = 'f'" if $args{defrec} eq 'n'; 654 656 if ($args{update}) { 655 657 $sql .= " AND record_id <> ?"; … … 667 669 } 668 670 669 # Check timestamps of pending active-after records. Coerce expires-at timestamp down to soonest match if overlapping. 670 if ($args{defrec} eq 'n') { 671 $sql = "SELECT extract(epoch from stamp),stamp < now() FROM "._rectable($args{defrec}, $args{revrec}). 671 # By this point, all failure cases for default records have been checked. 672 # Default records cannot carry timestamps, so cannot have timestamp-based collisions 673 return ('OK','OK') if $args{defrec} ne 'n'; 674 675 # Second lookup fails out various timestamp-exists collision cases when adding/updating with a timestamp 676 $sql = "SELECT count(*) FROM "._rectable($args{defrec}, $args{revrec}). 672 677 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?". 673 " AND stampactive = 't' AND expires = 'f'"; 674 my @lookupargs = ($args{id}, $hcheck); 675 if ($args{update}) { 676 $sql .= " AND record_id <> ?"; 677 push @lookupargs, $args{update}; 678 " AND stampactive = 't'"; 679 @lookupargs = ($args{id}, $hcheck); 680 if (${$args{stamp}} && ${$args{expires}}) { 681 $sql .= " AND expires = ?"; 682 push @lookupargs, ${$args{expires}}; 683 if ($self->{coerce_cname_timestamp} eq 'none') { 684 # no coercion means new valid-after < existing expires or new expires > existing valid-after will fail 685 $sql .= " AND ". (${$args{expires}} eq 'f' ? "expires = 't' AND stamp <= ?)" : "expires = 'f' AND stamp >= ?"); 686 push @lookupargs, ${$args{stamp}}; 678 687 } 688 } 689 if ($args{update}) { 690 $sql .= " AND record_id <> ?"; 691 push @lookupargs, $args{update}; 692 } 693 @t = $dbh->selectrow_array($sql, undef, @lookupargs); 694 if ($t[0] > 0) { 695 if ($tcompare eq '<>') { 696 return ('FAIL', "One or more non-CNAME records with timestamps already exist for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 697 ". CNAME records must expire before or become valid after any records with the same name."); 698 } else { 699 return ('FAIL', "There is already a CNAME with a timestamp present for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 700 ". Records with a matching name must expire before or become valid after this CNAME."); 701 } 702 } 703 704 # Third check starts retrieving actual timestamps to see if we need to, 705 # and then if we can, coerce the new/updated record's timestamp to match 706 $sql = "SELECT extract(epoch from stamp),expires,stamp < now() FROM "._rectable($args{defrec}, $args{revrec}). 707 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?". 708 " AND stampactive = 't'"; 709 @lookupargs = ($args{id}, $hcheck); 710 if ($args{update}) { 711 $sql .= " AND record_id <> ?"; 712 push @lookupargs, $args{update}; 713 } 714 if (${$args{stamp}}) { 715 $sql .= " ORDER BY stamp ".(${$args{expires}} eq 'f' ? 'ASC' : 'DESC' )." LIMIT 1"; 716 } else { 679 717 $sql .= " ORDER BY stamp LIMIT 1"; 680 my @t = $dbh->selectrow_array($sql, undef, @lookupargs); 681 if (@t) { 682 # existing record with valid-after stamp is present 683 if (${$args{stamp}}) { 684 # caller requested an expiry time 685 if (${$args{expires}} eq 'f') { 686 # valid-after can't be used together with expires-at, so we can't coerce 687 # the new record to expire as well as keeping valid-after 688 return ('FAIL', "Cannot add CNAME, another record with a later valid-after time already exists"); 689 } 690 my $reqstamp = str2time(${$args{stamp}}); 691 if ($reqstamp < $t[0]) { 692 # do nothing, new record will expire before the one we found 693 } else { 718 } 719 @t = $dbh->selectrow_array($sql, undef, @lookupargs); 720 if (@t) { 721 # caller requested an expiry time 722 if (${$args{expires}} eq 'f') { 723 # valid-after can't be used together with expires-at on one record, so we can't 724 # coerce the new record to expire as well as keeping valid-after 725 if ($tcompare eq '<>') { 726 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add')." CNAME, another record". 727 " with a valid-after time already exists for this name"); 728 } else { 729 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add')." ".$typemap{${$args{rectype}}}. 730 ", a CNAME with a valid-after time already exists for this name"); 731 } 732 } else { 733 my $reqstamp = str2time(${$args{stamp}}); 734 if ($reqstamp < $t[0]) { 735 # do nothing, new record will expire before the one we found 736 } else { 737 if ($self->{coerce_cname_timestamp} eq 'adjust') { 694 738 # coerce the expiry timestamp 695 739 ${$args{stamp}} = strftime('%Y-%m-%d %H:%M:%S', localtime($t[0])); 696 return ('WARN', "CNAME added with modified expiry time; conflicting valid-after record found"); 697 } 698 } else { 699 if ($t[1]) { 700 return('FAIL', "Cannot add CNAME, a record with a valid-after time in the past is already present"); 740 return ('WARN', $typemap{${$args{rectype}}}." ".($args{update} ? 'updated' : 'added'). 741 " with modified expiry time; conflicting valid-after record found"); 701 742 } else { 702 # no expiry requested, but we found a valid-after, so coerce the new record down to expiring at that time 703 ${$args{stamp}} = strftime('%Y-%m-%d %H:%M:%S', localtime($t[0])); 704 ${$args{expires}} = 't'; 705 return ('WARN', "CNAME added with expiry time; conflicting valid-after record found"); 743 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add')." ".$typemap{${$args{rectype}}}. 744 ", another record with an overlapping valid-after timestamp already exists for this name"); 706 745 } 707 746 } 708 } 709 } # args{defrecs} eq 'n' 747 } # args{expires} ne 'f' 748 } # if @t 749 710 750 } # each $tcompare 711 751
Note:
See TracChangeset
for help on using the changeset viewer.
![[ DNS Administrator ]](/fx/dnsadmin-logo.png)