[LEAPSECS] Bulletin C and all that

Zefram zefram at fysh.org
Tue Feb 10 11:45:53 EST 2015


Rob Seaman wrote:
>The trouble with encoding dates in the names and interpolating in the
>client is that by the time you're done it would have been easier to simply
>use a web service.

Not really.  Local computation is cheap, getting cheaper relative to
network traffic, and still easier to manage than network-related APIs.
The lightweight nature of DNS queries (not to mention its ability to
pass proxies and firewalls) is still a valuable feature when the client
is sophisticated enough to stringify the month.

>I share the same vision of a focused scope for this DNS mechanism that
>PHK has expressed.  We need to converge on the precise encoding, but I
>think this is pretty close:
>
>	bulletin-c.leapsec.com  ->  250.10.36.152   -> OK 2015  7  36  1  (1, 0)

If you have the month in the domain name, then the RR that is returned
only needs to encode the TAI-UTC difference, not any date as well.
So it gets much more comfortable to fit it into an A record.  Say,
represent (TAI-UTC)/s in 16 bits, including sign bit, then there's room
for a 12-bit check field.  I think it's a safe bet that AAAA lookups
will be commonly available before we exceed the 16-bit range.  I'd also
base the check field on a cryptographic hash function rather than a CRC,
because we're not trying to detect line noise, we're trying to detect
addresses that weren't intended to be used in this protocol.  I suggest:

    use Digest::SHA qw(sha1);
    sub diff_to_ipv4 {
	my($diff) = @_;
	die "out of range" unless $diff >= -0x8000 && $diff <= 0x7fff;
	my $o = pack("n", $diff & 0xffff);
	my $c = substr(sha1("\x97\x9b\x67\xb4\xf2\xa3\x94\xe2".$o), 0, 2)
	    | "\xf0\x00";
	return join(".", unpack("CCCC", $c.$o));
    }
    sub ipv4_to_diff {
	my($ipv4) = @_;
	($ipv4.".") =~ /\A
	    (?:(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))\.){4}
	\z/x or die "not an IPv4 address";
	my $diff = unpack("n", substr(pack("CCCC", split(/\./, $ipv4)), 2, 2));
	$diff -= 0x10000 if $diff & 0x8000;
	die "bad check" unless diff_to_ipv4($diff) eq $ipv4;
	return $diff;
    }

Test values for the above encoding:

    -32768  255.194.128.0
    -10000  248.211.216.240
     -1000  250.199.252.24
      -100  245.118.255.156
       -10  253.93.255.246
        -1  242.43.255.255
         0  245.79.0.0
         1  252.228.0.1
        10  250.83.0.10
        35  249.163.0.35
       100  255.127.0.100
      1000  245.137.3.232
     10000  243.246.39.16
     32767  242.222.127.255

>If the policy changes to permit months other than June and December
>we're ready - as long as we figure out what to call it in such cases.
>c48a, c48b, c48c?

That's not a good naming scheme for use in the protocol.  It's importing
irrelevant information by virtue of the unhealthy focus on Bulletin C
per se.  Just name it for the month concerned.

>We need 5 bits for the day of the month and 5 for the current 0.9s range.
>(I believe all historical values could just barely squeeze into 4 bits.)
>This would allow 6 bits for a CRC.  Alternately we might want to permit
>a larger range for DUT1, trading off bits in the CRC.

For Bulletin D you can perfectly well put the complete date in the
domain name and just encode the DUT1 value itself in the RR.  As an
A record, perhaps 16-bit number of milliseconds (anticipating future
finer resolution as well as increased tolerance), same encoding as
I suggested for DTAI but using a different magic number in the check
field computation.

If you really want to publish information about spans of days to
which the same DUT1 applies, you still don't have to squeeze date
and DUT1 value into the same RR.  They can go in separate RRs in one
RRset, or be stored under different domain names (value.d121.example,
prevchangedate.d121.example, nextchangedate.d121.example).  The date
also doesn't need to be broken up into month and day-of-month: a linear
day count will do just fine.

-zefram


More information about the LEAPSECS mailing list