- Timestamp:
- 03/06/26 11:33:19 (3 days ago)
- Location:
- trunk
- Files:
-
- 5 edited
- 3 copied
-
. (modified) (1 prop)
-
DNSDB.pm (modified) (15 diffs)
-
collision-truth-table.ods (copied) (copied from branches/cname-collision/collision-truth-table.ods )
-
dnsdb.conf (modified) (1 diff)
-
t/DNSTest.pm (modified) (5 diffs)
-
t/cname.t (copied) (copied from branches/cname-collision/t/cname.t )
-
t/dns-unitbase.sql (modified) (6 diffs)
-
t/test-cname-timestamps.sql (copied) (copied from branches/cname-collision/t/test-cname-timestamps.sql )
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/cname-collision (added) merged: 936-942,949-956,958-960,962-964,967-970,972-984,986-1001,1003-1006,1008-1031,1038-1046
- Property svn:mergeinfo changed
-
trunk/DNSDB.pm
r1036 r1051 33 33 use Fcntl qw(:flock); 34 34 use Time::TAI64 qw(:tai64); 35 use Date::Parse; 35 36 36 37 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); … … 222 223 force_refresh => 1, 223 224 lowercase => 0, # mangle as little as possible by default 225 # tinker with timestamps if adding or updating a record would 226 # cause overlapping CNAME and other in some way 227 coerce_cname_timestamp => 'none', 224 228 # show IPs and CIDR blocks as-is for reverse zones. valid values are 225 229 # 'none' (default, show natural IP or CIDR) … … 283 287 warn "Bad showrev_arpa setting $self->{showrev_arpa}, using default\n"; 284 288 $self->{showrev_arpa} = 'none'; 289 } 290 if (!grep /$self->{coerce_cname_timestamp}/, ('none','adjust','full')) { 291 warn "Bad coerce_cname_timestamp setting $self->{coerce_cname_timestamp}, using default\n"; 292 $self->{coerce_cname_timestamp} = 'none'; 285 293 } 286 294 … … 612 620 ## 613 621 622 # Check for name collisions relating to CNAMEs. Needs to be called from all other validators. 623 sub _cname_collision { 624 my $self = shift; 625 my $dbh = $self->{dbh}; 626 627 my %args = @_; 628 629 my $hcheck = ($args{revrec} eq 'y' ? ${$args{val}} : ${$args{host}}); 630 my $hfield = ($args{revrec} eq 'y' ? 'val' : 'host'); 631 632 # $hcheck should be normalized by the time this sub is called. Convert to the formal .arpa name for error reporting in reverse zones. 633 my $arpaname = ''; 634 if ($args{revrec} eq 'y') { 635 $arpaname = NetAddr::IP->new($hcheck); 636 ##fixme: more voodoo if global and/or per-user ARPA display mode flag set this way or that 637 $arpaname = _ZONE($arpaname, 'ZONE', 'r', '.').($arpaname->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 638 } 639 640 # The record type comparison is the only difference between two passes through this chunk of code. 641 # CNAME records require both passes, where other records only need the second one. Downside is 642 # that returning error messages needs to check the loop variable on top of whatever else it references. 643 foreach my $tcompare ('<>', '=') { 644 next if $tcompare eq '<>' && ${$args{rectype}} != 5; 645 646 # Merging these sets of SQL statements is far too messy and doesn't reasonably 647 # allow for more fine-grained error/warning messages to be returned 648 649 # First lookup fails out collisions with records without timestamps or default records (which can not have timestamps) 650 my $sql = "SELECT count(*) FROM "._rectable($args{defrec}, $args{revrec}). 651 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?"; 652 my @lookupargs = ($args{id}, $hcheck); 653 $sql .= " AND stampactive = 'f'" if $args{defrec} eq 'n'; 654 if ($args{update}) { 655 $sql .= " AND record_id <> ?"; 656 push @lookupargs, $args{update}; 657 } 658 my @t = $dbh->selectrow_array($sql, undef, @lookupargs); 659 if ($t[0] > 0) { 660 if ($tcompare eq '<>') { 661 return ('FAIL', "One or more non-CNAME records already exist for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 662 ". CNAME records cannot use the same name as other records."); 663 } else { 664 return ('FAIL', "There is already a CNAME present for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 665 ". Only one CNAME may be present for a given name."); 666 } 667 } 668 669 # By this point, all failure cases for default records have been checked. 670 # Default records cannot carry timestamps, so cannot have timestamp-based collisions 671 return ('OK','OK') if $args{defrec} ne 'n'; 672 673 # Second lookup fails out various timestamp-exists collision cases when adding/updating with a timestamp 674 $sql = "SELECT count(*) FROM "._rectable($args{defrec}, $args{revrec}). 675 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?". 676 " AND stampactive = 't'"; 677 @lookupargs = ($args{id}, $hcheck); 678 if (${$args{stamp}} && ${$args{expires}}) { 679 $sql .= " AND expires = ?"; 680 push @lookupargs, ${$args{expires}}; 681 if ($self->{coerce_cname_timestamp} eq 'none') { 682 # no coercion means new valid-after < existing expires or new expires > existing valid-after will fail 683 $sql .= " AND ". (${$args{expires}} eq 'f' ? "expires = 't' AND stamp <= ?)" : "expires = 'f' AND stamp >= ?"); 684 push @lookupargs, ${$args{stamp}}; 685 } 686 } 687 if ($args{update}) { 688 $sql .= " AND record_id <> ?"; 689 push @lookupargs, $args{update}; 690 } 691 @t = $dbh->selectrow_array($sql, undef, @lookupargs); 692 if ($t[0] > 0) { 693 if ($tcompare eq '<>') { 694 return ('FAIL', "One or more non-CNAME records with timestamps already exist for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 695 ". CNAME records must expire before or become valid after any records with the same name."); 696 } else { 697 return ('FAIL', "There is already a CNAME with a timestamp present for ".($args{revrec} eq 'y' ? $arpaname : $hcheck). 698 ". Records with a matching name must expire before or become valid after this CNAME."); 699 } 700 } 701 702 # Third check starts retrieving actual timestamps to see if we need to, 703 # and then if we can, coerce the new/updated record's timestamp to match 704 $sql = "SELECT extract(epoch from stamp),expires,stamp < now() FROM "._rectable($args{defrec}, $args{revrec}). 705 " WHERE "._recparent($args{defrec}, $args{revrec})." = ? AND type $tcompare 5 AND $hfield = ?". 706 " AND stampactive = 't'"; 707 @lookupargs = ($args{id}, $hcheck); 708 if ($args{update}) { 709 $sql .= " AND record_id <> ?"; 710 push @lookupargs, $args{update}; 711 } 712 if (${$args{stamp}}) { 713 $sql .= " ORDER BY stamp ".(${$args{expires}} eq 'f' ? 'ASC' : 'DESC' )." LIMIT 1"; 714 } else { 715 $sql .= " ORDER BY stamp LIMIT 1"; 716 } 717 @t = $dbh->selectrow_array($sql, undef, @lookupargs); 718 if (@t) { 719 # caller requested an expiry time 720 my $reqstamp = str2time(${$args{stamp}}); 721 if (${$args{expires}} eq 'f') { 722 if ($reqstamp > $t[0]) { 723 # do nothing, new record goes valid after the expiring record we found 724 } else { 725 if ($self->{coerce_cname_timestamp} eq 'adjust') { 726 # coerce the valid-after timestamp 727 ${$args{stamp}} = strftime('%Y-%m-%d %H:%M:%S', localtime($t[0])); 728 return ('WARN', $typemap{${$args{rectype}}}." ".($args{update} ? 'updated' : 'added'). 729 " with modified valid-after time; conflicting expiring record found"); 730 } else { 731 # New valid-after overlaps existing expiry, and not configured to adjust it 732 my $fill = ($tcompare eq '<>' ? ' CNAME, another record' : $typemap{${$args{rectype}}}.', a CNAME'); 733 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add').$fill. 734 " with a valid-after time already exists for this name"); 735 } 736 } # else ($reqstamp < $t[0]) 737 } else { 738 if ($reqstamp < $t[0]) { 739 # do nothing, new record will expire before the one we found 740 } else { 741 if ($self->{coerce_cname_timestamp} eq 'adjust') { 742 if ($t[2] == 1) { 743 # found a valid-after, but it's in the past, so adding an expiring record to match doesn't make 744 # sense since it's effectively expired. 745 ##fixme: should probably remove this case once we get around to stripping valid-after timestamps once exported as active 746 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add')." ".$typemap{${$args{rectype}}}. 747 ", an existing valid-after record is already active for this name"); 748 } else { 749 # coerce the expiry timestamp 750 ${$args{stamp}} = strftime('%Y-%m-%d %H:%M:%S', localtime($t[0])); 751 return ('WARN', $typemap{${$args{rectype}}}." ".($args{update} ? 'updated' : 'added'). 752 " with modified expiry time; conflicting valid-after record found"); 753 } 754 } else { 755 return ('FAIL', "Cannot ".($args{update} ? 'update' : 'add')." ".$typemap{${$args{rectype}}}. 756 ", another record with an overlapping valid-after timestamp already exists for this name"); 757 } 758 } 759 } # args{expires} ne 'f' 760 } # if @t 761 762 } # each $tcompare 763 764 return ('OK', 'OK'); 765 } # _cname_collision() 766 614 767 ## All of these subs take substantially the same arguments: 615 768 # a hash containing at least the following keys: … … 808 961 return ('FAIL', "The bare zone name may not be a CNAME") if ${$args{host}} eq $pname || ${$args{host}} =~ /^\@/; 809 962 810 ##enhance: Look up the passed value to see if it exists. Ooo, fancy.811 963 return ('FAIL', $errstr) if ! _check_hostname_form(${$args{val}}, ${$args{rectype}}, $args{defrec}, $args{revrec}); 964 812 965 } # $zname !~ .rpz 813 966 } # revzone eq 'n' … … 1666 1819 1667 1820 return ('WARN', join("\n", $errstr, $warnmsg) ) if $warnmsg; 1668 1821 1669 1822 return ('OK','OK'); 1670 1823 } # done ALIAS record … … 2222 2375 $cfg->{lowercase} = $1 if /^lowercase\s*=\s*([a-z01]+)/i; 2223 2376 $cfg->{showrev_arpa} = $1 if /^showrev_arpa\s*=\s*([a-z]+)/i; 2377 $cfg->{coerce_cname_timestamp} = $1 if /^coerce_cname_timestamp\s*=\s*([a-z]+)/i; 2224 2378 $cfg->{template_skip_0} = $1 if /^template_skip_0\s*=\s*([a-z01]+)/i; 2225 2379 $cfg->{template_skip_255} = $1 if /^template_skip_255\s*=\s*([a-z01]+)/i; … … 4761 4915 4762 4916 my $expires = shift || ''; 4763 $expires = 1 if $expires eq 'until'; # Turn some special values into the appropriate booleans. 4764 $expires = 0 if $expires eq 'after'; 4917 $expires = 't' if $expires eq 'until'; # Turn some special values into the appropriate booleans. 4918 $expires = 'f' if $expires eq 'after'; 4919 $expires = 't' if $expires eq '1'; 4920 $expires = 'f' if $expires eq '0'; 4765 4921 my $stamp = shift; 4766 4922 $stamp = '' if !$stamp; # Timestamp should be a string at this point. … … 4772 4928 return ('FAIL', "expires must be 1, 't', or 'until', or 0, 'f', or 'after'") 4773 4929 if ($stamp && !defined($expires)) 4774 || ($stamp && $expires ne ' 0' && $expires ne '1' && $expires ne 't' && $expires ne 'f');4930 || ($stamp && $expires ne 't' && $expires ne 'f'); 4775 4931 4776 4932 # Spaces are evil. … … 4812 4968 host => $host, rectype => $rectype, val => $val, addr => $addr, 4813 4969 dist => \$dist, port => \$port, weight => \$weight, 4970 stamp => \$stamp, expires => \$expires, 4814 4971 fields => \$fields, vallist => \@vallist); 4815 4972 4816 4973 return ($retcode,$retmsg) if $retcode eq 'FAIL'; 4974 4975 # Check for CNAME collisions. 4976 ##fixme: should trim the list of arguments, not all of these should be required for CNAME collision checking 4977 my ($ccode,$cmsg) = _cname_collision($self, defrec => $defrec, revrec => $revrec, id => $id, 4978 host => $host, rectype => $rectype, val => $val, addr => $addr, 4979 dist => \$dist, port => \$port, weight => \$weight, 4980 stamp => \$stamp, expires => \$expires, 4981 fields => \$fields, vallist => \@vallist); 4982 4983 return ($ccode,$cmsg) if $ccode eq 'FAIL'; 4984 4985 # If both the validator and CNAME collision check return warnings, glue them together 4986 if ($ccode eq 'WARN') { 4987 if ($retcode eq 'WARN') { 4988 $retmsg .= "<br>\n$cmsg"; 4989 } else { 4990 $retmsg = $cmsg; 4991 } 4992 $retcode = 'WARN'; 4993 } 4817 4994 4818 4995 # Minor cleanup of invalid DNS labels … … 4873 5050 $logdata{entry} .= "', TTL $ttl"; 4874 5051 $logdata{entry} .= ", location ".$self->getLoc($location)->{description} if $location; 4875 $logdata{entry} .= ($expires ? ', expires at ' : ', valid after ').$stamp if $stamp;5052 $logdata{entry} .= ($expires eq 't' ? ', expires at ' : ', valid after ').$stamp if $stamp; 4876 5053 4877 5054 # Allow transactions, and raise an exception on errors so we can catch it later. … … 4933 5110 4934 5111 my $expires = shift || ''; 4935 $expires = 1 if $expires eq 'until'; # Turn some special values into the appropriate booleans. 4936 $expires = 0 if $expires eq 'after'; 5112 $expires = 't' if $expires eq 'until'; # Turn some special values into the appropriate booleans. 5113 $expires = 'f' if $expires eq 'after'; 5114 $expires = 't' if $expires eq '1'; 5115 $expires = 'f' if $expires eq '0'; 4937 5116 my $stamp = shift; 4938 5117 $stamp = '' if !$stamp; # Timestamp should be a string at this point. … … 4943 5122 return ('FAIL', "expires must be 1, 't', or 'until', or 0, 'f', or 'after'") 4944 5123 if ($stamp && !defined($expires)) 4945 || ($stamp && $expires ne ' 0' && $expires ne '1' && $expires ne 't' && $expires ne 'f');5124 || ($stamp && $expires ne 't' && $expires ne 'f'); 4946 5125 4947 5126 # Spaces are evil. … … 4989 5168 host => $host, rectype => $rectype, val => $val, addr => $addr, 4990 5169 dist => \$dist, port => \$port, weight => \$weight, 5170 stamp => \$stamp, expires => \$expires, 4991 5171 fields => \$fields, vallist => \@vallist, 4992 5172 update => $id); 4993 5173 4994 5174 return ($retcode,$retmsg) if $retcode eq 'FAIL'; 5175 5176 # Check for CNAME collisions. 5177 ##fixme: should trim the list of arguments, not all of these should be required for CNAME collision checking 5178 my ($ccode,$cmsg) = _cname_collision($self, defrec => $defrec, revrec => $revrec, 5179 id => ($defrec eq 'y' ? $oldrec->{group_id} : ($revrec eq 'n' ? $oldrec->{domain_id} : $oldrec->{rdns_id})), 5180 host => $host, rectype => $rectype, val => $val, addr => $addr, 5181 dist => \$dist, port => \$port, weight => \$weight, 5182 stamp => \$stamp, expires => \$expires, 5183 fields => \$fields, vallist => \@vallist, 5184 update => $id); 5185 5186 return ($ccode,$cmsg) if $ccode eq 'FAIL'; 5187 5188 # If both the validator and CNAME collision check return warnings, glue them together 5189 if ($ccode eq 'WARN') { 5190 if ($retcode eq 'WARN') { 5191 $retmsg .= "<br>\n$cmsg"; 5192 } else { 5193 $retmsg = $cmsg; 5194 } 5195 $retcode = 'WARN'; 5196 } 4995 5197 4996 5198 # Minor cleanup of invalid DNS labels … … 5091 5293 $logdata{entry} .= "', TTL $ttl"; 5092 5294 $logdata{entry} .= ", location ".$self->getLoc($location)->{description} if $location; 5093 $logdata{entry} .= ($expires ? ', expires at ' : ', valid after ').$stamp if $stamp;5295 $logdata{entry} .= ($expires eq 't' ? ', expires at ' : ', valid after ').$stamp if $stamp; 5094 5296 5095 5297 local $dbh->{AutoCommit} = 0; -
trunk/dnsdb.conf
r901 r1051 60 60 #lowercase = 0 61 61 62 # Variously coerce timestamp and valid-after/expiry flags onto a new/updated record if the 63 # record as requested would cause a CNAME to overlap with another record. 64 # adjust: Adjust the timestamp where an expiry+valid-after would overlap 65 # - existing record expires, new record has valid-after before expiry => adjust timestamp to match existing record 66 # - existing record is valid-after, new record has expiry after valid-after => adjust timestamp to match existing record 67 # none: (default) Do not make changes to timestamps to avoid overlap 68 #coerce_cname_timestamp = none 69 62 70 # Show formal .arpa zone name instead of the natural IP or CIDR for reverse zone names and records? 63 71 # Valid values are none, zone, record, or all -
trunk/t/DNSTest.pm
r985 r1051 5 5 ## 6 6 # $Id$ 7 # Copyright 2025 Kris Deugau <kdeugau@deepnet.cx>7 # Copyright 2025,2026 Kris Deugau <kdeugau@deepnet.cx> 8 8 # 9 9 # This program is free software: you can redistribute it and/or modify … … 48 48 dbuser => 'dnstest', 49 49 dbpass => 'dnstestpwd', 50 51 # This exercises more branches of the CNAME collision check with more fine-grained results. 52 coerce_cname_timestamp => 'adjust', 50 53 ); 51 54 ok( defined $dnsdb ); … … 61 64 62 65 my ($dcount) = $dbh->selectrow_array("SELECT count(*) FROM domains WHERE NOT domain IN ". 63 "('example.com','example.net','example.org','expiry1.test','expiry2.test' )");66 "('example.com','example.net','example.org','expiry1.test','expiry2.test','expiry3.test','cname-blocks1.test')"); 64 67 BAIL_OUT("# DB looks like it may not be a test DB, found $dcount > 0 non-test domains!\n") 65 68 if $dcount > 0; … … 68 71 my ($rcount) = $dbh->selectrow_array(qq{SELECT count(*) FROM records WHERE NOT ( 69 72 host like '%example.com' or host like '%example.net' or host like '%example.org' or 70 host like '%expiry1.test' or host like '%expiry2.test' or inetlazy(val) << '192.168.2.0/27' 73 host like '%expiry_.test' or host like '%cname-blocks_.test' or 74 inetlazy(val) << '192.168.2.0/27' 71 75 )}); 72 76 my $maxrecs = 0; 73 BAIL_OUT("# DB looks like it may not be a test DB, found $rcount > $maxrecs records!\n")77 BAIL_OUT("# DB looks like it may not be a test DB, found $rcount > $maxrecs non-test records!\n") 74 78 if $rcount > $maxrecs; 75 79 cmp_ok( $rcount, '<=', $maxrecs, "non-test record ($rcount): looks like a test DB" ); … … 83 87 my $reload = qx( psql -h $dnsdb->{dbhost} -U $dnsdb->{dbuser} $dnsdb->{dbname} 2>&1 < t/dns-unitbase.sql ); 84 88 diag( $reload ) if $debug; 89 # Set timestamps to a sliding window 90 my $stampwindow = qx( psql -h $dnsdb->{dbhost} -U $dnsdb->{dbuser} $dnsdb->{dbname} 2>&1 < t/test-cname-timestamps.sql ); 91 diag( $stampwindow ) if $debug; 85 92 undef $ENV{PGPASSWORD}; 86 93 } # new() -
trunk/t/dns-unitbase.sql
r965 r1051 657 657 2 example.org 1 1 2025121800 D f ac 658 658 3 example.net 1 1 2025121800 D f ab 659 4 expiry1.test 1 1 1765992407 D f 659 4 expiry1.test 1 1 2026011400 D t 660 5 expiry2.test 1 1 2026011901 D t 661 6 expiry3.test 1 1 2026020509 D t 662 7 cname-blocks1.test 1 1 2026021811 D t 660 663 \. 661 664 … … 665 668 -- 666 669 667 SELECT pg_catalog.setval('public.domains_domain_id_seq', 4, true);670 SELECT pg_catalog.setval('public.domains_domain_id_seq', 7, true); 668 671 669 672 … … 761 764 53 0 1 1 admin Initial User Added record '192.168.2.17 TXT imma blocker!', TTL 2560 2025-12-23 13:06:20.492137-05 1 0 762 765 55 0 1 1 admin Initial User Added record '192.168.2.18 CNAME 18-2.arpa.example.com', TTL 2560 2026-01-07 16:37:03.094557-05 1 0 766 56 4 1 1 admin Initial User Added record 'expired1.expiry1.test A 192.168.2.23', TTL 5400, expires at 2025-12-24 18:30 2026-01-07 17:55:46.022401-05 0 0 767 57 4 1 1 admin Initial User Added record 'expired2.expiry1.test TXT imma expire soon', TTL 5400, expires at 2026-01-10 07:00 2026-01-07 17:57:07.015962-05 0 0 768 58 4 1 1 admin Initial User Added record 'active-after1.expiry1.test TXT not active yet', TTL 5400, valid after 2026-01-11 11:30 2026-01-07 18:12:57.491476-05 0 0 769 59 4 1 1 admin Initial User Added record 'active-after2.expiry1.test TXT I'm done waiting', TTL 5400, expires at 2025-12-31 14:00 2026-01-14 18:02:13.876839-05 0 0 770 60 5 1 1 admin Initial User Added active domain expiry2.test 2026-01-15 12:08:59.951774-05 0 0 771 61 5 1 1 admin Initial User [new expiry2.test] Added SOA record [contact ns1.example.com] [master hostmaster.expiry2.test] [refresh 10800] [retry 3600] [expire 604800] [minttl 5400], TTL 86400 2026-01-15 12:08:59.951774-05 0 60 772 62 5 1 1 admin Initial User [new expiry2.test] Added record 'expiry2.test NS ns2.example.com', TTL 7200 2026-01-15 12:08:59.951774-05 0 60 773 63 5 1 1 admin Initial User [new expiry2.test] Added record 'expiry2.test NS ns1.example.com', TTL 7200 2026-01-15 12:08:59.951774-05 0 60 774 64 5 1 1 admin Initial User [new expiry2.test] Added record 'expiry2.test A 10.0.0.4', TTL 7200 2026-01-15 12:08:59.951774-05 0 60 775 65 5 1 1 admin Initial User [new expiry2.test] Added record 'expiry2.test MX [distance 10] mx1.example.com', TTL 7200 2026-01-15 12:08:59.951774-05 0 60 776 66 5 1 1 admin Initial User [new expiry2.test] Added record 'www.expiry2.test CNAME expiry2.test', TTL 10800 2026-01-15 12:08:59.951774-05 0 60 777 67 5 1 1 admin Initial User [new expiry2.test] Added record 'expiry2.test TXT "v=spf1 a mx -all"', TTL 10800 2026-01-15 12:08:59.951774-05 0 60 778 68 5 1 1 admin Initial User Added record 'expires-at1.expiry2.test TXT Hanging around', TTL 5400 2026-01-15 12:57:28.411931-05 0 0 779 69 5 1 1 admin Initial User Added record 'expires-at2.expiry2.test TXT imma expire soon', TTL 5400, expires at 2026-01-15 18:00 2026-01-15 12:58:51.09629-05 0 0 780 70 5 1 1 admin Initial User Added record 'expires-at3.expiry2.test TXT active after pending expiry', TTL 5400, expires at 2026-01-15 18:00 2026-01-15 13:21:31.833257-05 0 0 781 71 5 1 1 admin Initial User Added record 'expires-at4.expiry2.test TXT active before pending expiry', TTL 5400, expires at 2026-01-15 18:00 2026-01-15 17:59:01.61806-05 0 0 782 72 5 1 1 admin Initial User Added record 'expires-at5.expiry2.test TXT expired before now', TTL 5400, expires at 2026-01-15 18:00 2026-01-16 11:50:43.678446-05 0 0 783 73 5 1 1 admin Initial User Added record 'valid-after1.expiry2.test TXT always here', TTL 5400 2026-01-16 13:36:36.066418-05 0 0 784 74 5 1 1 admin Initial User Added record 'valid-after2.expiry2.test TXT valid soon', TTL 5400, expires at 2026-01-15 18:00 2026-01-16 13:38:57.274666-05 0 0 785 75 5 1 1 admin Initial User Added record 'valid-after3.expiry2.test TXT valid days ago', TTL 5400, expires at 2026-01-15 18:00 2026-01-16 13:45:27.179614-05 0 0 786 76 5 1 1 admin Initial User Added record 'valid-after4.expiry2.test TXT valid quite soon', TTL 5400, expires at 2026-01-15 18:00 2026-01-19 11:40:07.438603-05 0 0 787 77 5 1 1 admin Initial User Added record 'valid-after5.expiry2.test TXT expires before pending valid', TTL 5400, expires at 2026-01-15 18:00 2026-01-19 11:40:55.325144-05 0 0 788 78 6 1 1 admin Initial User Added active domain expiry3.test 2026-01-29 18:05:53.678277-05 0 0 789 79 6 1 1 admin Initial User [new expiry3.test] Added SOA record [contact ns1.example.com] [master hostmaster.expiry3.test] [refresh 10800] [retry 3600] [expire 604800] [minttl 5400], TTL 86400 2026-01-29 18:05:53.678277-05 0 78 790 80 6 1 1 admin Initial User [new expiry3.test] Added record 'expiry3.test NS ns2.example.com', TTL 7200 2026-01-29 18:05:53.678277-05 0 78 791 81 6 1 1 admin Initial User [new expiry3.test] Added record 'expiry3.test NS ns1.example.com', TTL 7200 2026-01-29 18:05:53.678277-05 0 78 792 82 6 1 1 admin Initial User [new expiry3.test] Added record 'expiry3.test A 10.0.0.4', TTL 7200 2026-01-29 18:05:53.678277-05 0 78 793 83 6 1 1 admin Initial User [new expiry3.test] Added record 'expiry3.test MX [distance 10] mx1.example.com', TTL 7200 2026-01-29 18:05:53.678277-05 0 78 794 84 6 1 1 admin Initial User [new expiry3.test] Added record 'www.expiry3.test CNAME expiry3.test', TTL 10800 2026-01-29 18:05:53.678277-05 0 78 795 85 6 1 1 admin Initial User [new expiry3.test] Added record 'expiry3.test TXT "v=spf1 a mx -all"', TTL 10800 2026-01-29 18:05:53.678277-05 0 78 796 86 6 1 1 admin Initial User Added record 'nostamp1a.expiry3.test TXT target - expired', TTL 5400, expires at 2026-01-29 14:00 2026-01-30 15:07:08.695134-05 0 0 797 87 6 1 1 admin Initial User Added record 'nostamp2a.expiry3.test TXT target - soon to expire', TTL 5400, expires at 2026-01-31 14:00 2026-01-30 15:07:34.780671-05 0 0 798 88 6 1 1 admin Initial User Added record 'nostamp3a.expiry3.test TXT target - valid soon', TTL 5400, valid after 2026-01-31 14:00 2026-01-30 15:07:53.379107-05 0 0 799 89 6 1 1 admin Initial User Added record 'nostamp4a.expiry3.test TXT target - already valid', TTL 5400, valid after 2026-01-29 14:00 2026-01-30 15:08:15.4399-05 0 0 800 90 6 1 1 admin Initial User Added record 'nostamp1b.expiry3.test TXT to change', TTL 5400 2026-01-30 15:29:48.433198-05 0 0 801 91 6 1 1 admin Initial User Added record 'nostamp2b.expiry3.test TXT to change', TTL 5400 2026-01-30 15:29:53.902318-05 0 0 802 92 6 1 1 admin Initial User Added record 'nostamp3b.expiry3.test TXT to change', TTL 5400 2026-01-30 15:29:57.875273-05 0 0 803 93 6 1 1 admin Initial User Added record 'nostamp4b.expiry3.test TXT to change', TTL 5400 2026-01-30 15:30:01.924263-05 0 0 804 94 6 1 1 admin Initial User Added record 'expires1a.expiry3.test TXT target - no timestamp', TTL 5400 2026-02-03 12:02:32.883354-05 0 0 805 95 6 1 1 admin Initial User Added record 'expires2a.expiry3.test TXT target - expired', TTL 5400, expires at 2026-01-29 14:00 2026-02-03 12:03:09.031474-05 0 0 806 96 6 1 1 admin Initial User Added record 'expires3a.expiry3.test TXT target - expires soon', TTL 5400, expires at 2026-01-31 14:00 2026-02-03 12:04:30.954558-05 0 0 807 97 6 1 1 admin Initial User Added record 'expires4a.expiry3.test TXT target - valid soon', TTL 5400, valid after 2026-01-31 14:00 2026-02-03 12:04:52.864866-05 0 0 808 98 6 1 1 admin Initial User Added record 'expires5a.expiry3.test TXT target - already valid', TTL 5400, valid after 2026-01-29 14:00 2026-02-03 12:05:10.629373-05 0 0 809 99 6 1 1 admin Initial User Added record 'expires6a.expiry3.test TXT target - valid less soon', TTL 5400, valid after 2026-01-15 18:00 2026-02-03 12:05:31.096289-05 0 0 810 100 6 1 1 admin Initial User Added record 'expires1b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:05:33.779645-05 0 0 811 101 6 1 1 admin Initial User Added record 'expires2b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:05:44.12329-05 0 0 812 102 6 1 1 admin Initial User Added record 'expires3b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:05:50.968888-05 0 0 813 103 6 1 1 admin Initial User Added record 'expires4b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:05:56.415551-05 0 0 814 104 6 1 1 admin Initial User Added record 'expires5b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:06:01.591204-05 0 0 815 105 6 1 1 admin Initial User Added record 'expires6b.expiry3.test TXT to change', TTL 5400 2026-02-03 12:06:34.192183-05 0 0 816 106 6 1 1 admin Initial User Added record 'validafter1a.expiry3.test TXT target - no timestamp', TTL 5400 2026-02-05 17:06:17.118891-05 0 0 817 107 6 1 1 admin Initial User Added record 'validafter2a.expiry3.test TXT target - expires in the future', TTL 5400, expires at 2026-02-05 17:30 2026-02-05 17:07:12.29965-05 0 0 818 108 6 1 1 admin Initial User Added record 'validafter3a.expiry3.test TXT target - expires soon', TTL 5400, expires at 2026-02-05 17:30 2026-02-05 17:07:49.064852-05 0 0 819 109 6 1 1 admin Initial User Added record 'validafter4a.expiry3.test TXT target - valid less soon', TTL 5400, valid after 2026-02-05 17:30 2026-02-05 17:14:01.474778-05 0 0 820 110 6 1 1 admin Initial User Added record 'validafter5a.expiry3.test TXT target - valid soon', TTL 5400, valid after 2026-02-05 17:30 2026-02-05 17:14:25.354496-05 0 0 821 111 6 1 1 admin Initial User Added record 'validafter1b.expiry3.test TXT to change', TTL 5400 2026-02-05 17:16:49.945082-05 0 0 822 112 6 1 1 admin Initial User Added record 'validafter2b.expiry3.test TXT to change', TTL 5400 2026-02-05 17:16:59.246035-05 0 0 823 113 6 1 1 admin Initial User Added record 'validafter3b.expiry3.test TXT to change', TTL 5400 2026-02-05 17:17:04.371248-05 0 0 824 114 6 1 1 admin Initial User Added record 'validafter4b.expiry3.test TXT to change', TTL 5400 2026-02-05 17:17:09.60198-05 0 0 825 115 6 1 1 admin Initial User Added record 'validafter5b.expiry3.test TXT to change', TTL 5400 2026-02-05 17:17:15.012334-05 0 0 826 116 7 1 1 admin Initial User Added active domain cname-blocks1.test 2026-02-18 18:00:14.727439-05 0 0 827 117 7 1 1 admin Initial User [new cname-blocks1.test] Added SOA record [contact ns1.example.com] [master hostmaster.cname-blocks1.test] [refresh 10800] [retry 3600] [expire 604800] [minttl 5400], TTL 86400 2026-02-18 18:00:14.727439-05 0 116 828 118 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'cname-blocks1.test NS ns2.example.com', TTL 7200 2026-02-18 18:00:14.727439-05 0 116 829 119 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'cname-blocks1.test NS ns1.example.com', TTL 7200 2026-02-18 18:00:14.727439-05 0 116 830 120 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'cname-blocks1.test A 10.0.0.4', TTL 7200 2026-02-18 18:00:14.727439-05 0 116 831 121 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'cname-blocks1.test MX [distance 10] mx1.example.com', TTL 7200 2026-02-18 18:00:14.727439-05 0 116 832 122 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'www.cname-blocks1.test CNAME cname-blocks1.test', TTL 10800 2026-02-18 18:00:14.727439-05 0 116 833 123 7 1 1 admin Initial User [new cname-blocks1.test] Added record 'cname-blocks1.test TXT "v=spf1 a mx -all"', TTL 10800 2026-02-18 18:00:14.727439-05 0 116 834 124 7 1 1 admin Initial User Added record 'blocker01.cname-blocks1.test TXT I do not collide', TTL 5400 2026-02-18 18:00:35.918847-05 0 0 835 125 7 1 1 admin Initial User Added record 'blocker02.cname-blocks1.test CNAME target.example.com', TTL 5400 2026-02-18 18:00:54.003589-05 0 0 836 126 7 1 1 admin Initial User Added record 'blocker03.cname-blocks1.test CNAME target.example.com', TTL 5400, expires at 2026-02-20 20:20:00-05 2026-02-18 18:01:13.009519-05 0 0 837 127 7 1 1 admin Initial User Added record 'blocker04.cname-blocks1.test CNAME target.example.com', TTL 5400, valid after 2026-02-20 20:20:00-05 2026-02-18 18:01:24.142491-05 0 0 838 128 7 1 1 admin Initial User Added record 'blocker05.cname-blocks1.test CNAME target.example.com', TTL 5400 2026-02-18 18:02:22.263541-05 0 0 839 129 7 1 1 admin Initial User Added record 'blocker06.cname-blocks1.test CNAME target.example.com', TTL 5400, expires at 2026-02-20 20:20:00-05 2026-02-18 18:02:37.418389-05 0 0 840 130 7 1 1 admin Initial User Added record 'blocker07.cname-blocks1.test CNAME target.example.com', TTL 5400, valid after 2026-02-20 20:20:00-05 2026-02-18 18:02:47.023266-05 0 0 841 131 7 1 1 admin Initial User Added record 'blocker08.cname-blocks1.test CNAME target.example.com', TTL 5400, valid after 2026-02-20 20:20:00-05 2026-02-18 18:02:52.405397-05 0 0 842 132 7 1 1 admin Initial User Added record 'blocker09.cname-blocks1.test CNAME target.example.com', TTL 5400 2026-02-18 18:03:11.617403-05 0 0 843 133 7 1 1 admin Initial User Added record 'blocker10.cname-blocks1.test CNAME target.example.com', TTL 5400, expires at 2026-02-20 20:20:00-05 2026-02-18 18:03:25.888935-05 0 0 844 134 7 1 1 admin Initial User Added record 'blocker11.cname-blocks1.test CNAME target.example.com', TTL 5400, expires at 2026-02-20 20:20:00-05 2026-02-18 18:03:33.383937-05 0 0 845 135 7 1 1 admin Initial User Added record 'blocker12.cname-blocks1.test CNAME target.example.com', TTL 5400, valid after 2026-02-20 20:20:00-05 2026-02-18 18:03:41.441495-05 0 0 763 846 \. 764 847 … … 768 851 -- 769 852 770 SELECT pg_catalog.setval('public.log_log_id_seq', 55, true);853 SELECT pg_catalog.setval('public.log_log_id_seq', 135, true); 771 854 772 855 … … 855 938 0 45 imma blocker! 16 192.168.2.17 0 0 0 2560 \N 1 1969-12-31 19:00:00-05 f f \N 856 939 0 46 18-2.arpa.example.com 5 192.168.2.18 0 0 0 2560 \N 1 1969-12-31 19:00:00-05 f f \N 940 4 47 expired1.expiry1.test 1 192.168.2.23 0 0 0 5400 \N 0 2025-12-24 18:30:00-05 t t \N 941 4 48 expired2.expiry1.test 16 imma expire soon 0 0 0 5400 \N 0 2026-01-10 07:00:00-05 t t \N 942 4 49 active-after1.expiry1.test 16 not active yet 0 0 0 5400 \N 0 2026-01-11 11:30:00-05 f t \N 943 4 50 active-after2.expiry1.test 16 I'm done waiting 0 0 0 5400 \N 0 2025-12-31 14:00:00-05 f t \N 944 5 51 ns1.example.com:hostmaster.expiry2.test 6 10800:3600:604800:5400 0 0 0 86400 \N 0 1969-12-31 19:00:00-05 f f \N 945 5 52 expiry2.test 2 ns2.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 946 5 53 expiry2.test 2 ns1.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 947 5 54 expiry2.test 1 10.0.0.4 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 948 5 55 expiry2.test 15 mx1.example.com 10 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 949 5 56 www.expiry2.test 5 expiry2.test 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 950 5 57 expiry2.test 16 "v=spf1 a mx -all" 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 951 5 58 expires-at1.expiry2.test 16 Hanging around 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 952 5 59 expires-at2.expiry2.test 16 imma expire soon 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 t t \N 953 5 60 expires-at3.expiry2.test 16 active after pending expiry 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 f t \N 954 5 61 expires-at4.expiry2.test 16 active before pending expiry 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 f t \N 955 5 62 expires-at5.expiry2.test 16 expired before now 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 t t \N 956 5 63 valid-after1.expiry2.test 16 always here 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 957 5 64 valid-after2.expiry2.test 16 expires soon 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 t t \N 958 5 65 valid-after3.expiry2.test 16 valid days ago 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 f t \N 959 5 66 valid-after4.expiry2.test 16 valid quite soon 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 f t \N 960 5 67 valid-after5.expiry2.test 16 expires before pending valid 0 0 0 5400 \N 0 2026-01-15 18:00:00-05 t t \N 961 6 68 ns1.example.com:hostmaster.expiry3.test 6 10800:3600:604800:5400 0 0 0 86400 \N 0 1969-12-31 19:00:00-05 f f \N 962 6 69 expiry3.test 2 ns2.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 963 6 70 expiry3.test 2 ns1.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 964 6 71 expiry3.test 1 10.0.0.4 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 965 6 72 expiry3.test 15 mx1.example.com 10 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 966 6 73 www.expiry3.test 5 expiry3.test 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 967 6 74 expiry3.test 16 "v=spf1 a mx -all" 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 968 6 75 nostamp1a.expiry3.test 16 target - expired 0 0 0 5400 \N 0 2026-01-29 14:00:00-05 t t \N 969 6 76 nostamp2a.expiry3.test 16 target - soon to expire 0 0 0 5400 \N 0 2026-01-31 14:00:00-05 t t \N 970 6 77 nostamp3a.expiry3.test 16 target - valid soon 0 0 0 5400 \N 0 2026-01-31 14:00:00-05 f t \N 971 6 78 nostamp4a.expiry3.test 16 target - already valid 0 0 0 5400 \N 0 2026-01-29 14:00:00-05 f t \N 972 6 79 nostamp1b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 973 6 80 nostamp2b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 974 6 81 nostamp3b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 975 6 82 nostamp4b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 976 6 83 expires1a.expiry3.test 16 target - no timestamp 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 977 6 84 expires2a.expiry3.test 16 target - expired 0 0 0 5400 \N 0 2026-01-29 14:00:00-05 t t \N 978 6 85 expires3a.expiry3.test 16 target - expires soon 0 0 0 5400 \N 0 2026-01-31 14:00:00-05 t t \N 979 6 86 expires4a.expiry3.test 16 target - valid soon 0 0 0 5400 \N 0 2026-01-31 14:00:00-05 f t \N 980 6 87 expires5a.expiry3.test 16 target - already valid 0 0 0 5400 \N 0 2026-01-29 14:00:00-05 f t \N 981 6 88 expires6a.expiry3.test 16 target - valid less soon 0 0 0 5400 \N 0 2026-01-29 14:00:00-05 f t \N 982 6 89 expires1b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 983 6 90 expires2b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 984 6 91 expires3b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 985 6 92 expires4b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 986 6 93 expires5b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 987 6 94 expires6b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 988 6 95 validafter1a.expiry3.test 16 target - no timestamp 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 989 6 96 validafter2a.expiry3.test 16 target - expires in the future 0 0 0 5400 \N 0 2026-02-05 17:30:00-05 t t \N 990 6 97 validafter3a.expiry3.test 16 target - expires soon 0 0 0 5400 \N 0 2026-02-05 17:30:00-05 t t \N 991 6 98 validafter4a.expiry3.test 16 target - valid less soon 0 0 0 5400 \N 0 2026-02-05 17:30:00-05 f t \N 992 6 99 validafter5a.expiry3.test 16 target - valid soon 0 0 0 5400 \N 0 2026-02-05 17:30:00-05 f t \N 993 6 100 validafter1b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 994 6 101 validafter2b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 995 6 102 validafter3b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 996 6 103 validafter4b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 997 6 104 validafter5b.expiry3.test 16 to change 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 998 7 105 ns1.example.com:hostmaster.cname-blocks1.test 6 10800:3600:604800:5400 0 0 0 86400 \N 0 1969-12-31 19:00:00-05 f f \N 999 7 106 cname-blocks1.test 2 ns2.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 1000 7 107 cname-blocks1.test 2 ns1.example.com 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 1001 7 108 cname-blocks1.test 1 10.0.0.4 0 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 1002 7 109 cname-blocks1.test 15 mx1.example.com 10 0 0 7200 \N 0 1969-12-31 19:00:00-05 f f \N 1003 7 110 www.cname-blocks1.test 5 cname-blocks1.test 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 1004 7 111 cname-blocks1.test 16 "v=spf1 a mx -all" 0 0 0 10800 \N 0 1969-12-31 19:00:00-05 f f \N 1005 7 112 blocker01.cname-blocks1.test 16 I do not collide 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 1006 7 113 blocker02.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 1007 7 114 blocker03.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 t t \N 1008 7 115 blocker04.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 f t \N 1009 7 116 blocker05.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 1010 7 117 blocker06.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 t t \N 1011 7 118 blocker07.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 f t \N 1012 7 119 blocker08.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 f t \N 1013 7 120 blocker09.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 1969-12-31 19:00:00-05 f f \N 1014 7 121 blocker10.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 t t \N 1015 7 122 blocker11.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 t t \N 1016 7 123 blocker12.cname-blocks1.test 5 target.example.com 0 0 0 5400 \N 0 2026-02-20 20:20:00-05 f t \N 857 1017 \. 858 1018 … … 862 1022 -- 863 1023 864 SELECT pg_catalog.setval('public.records_record_id_seq', 46, true);1024 SELECT pg_catalog.setval('public.records_record_id_seq', 123, true); 865 1025 866 1026
Note:
See TracChangeset
for help on using the changeset viewer.
![[ DNS Administrator ]](/fx/dnsadmin-logo.png)