s6-networking
Software
skarnet.org
The s6-sntpclock program
s6-sntpclock is a small SNTP client. It connects to an
SNTP or NTP server, computes an estimated discrepancy between the
local clock time and the absolute time given by the server, and
outputs it on stdout.
Interface
s6-sntpclock [ -f ] [ -v verbosity ] [ -r roundtrips ] [ -t triptimeout ] [ -h throttle ] [ -T totaltimeout ] [ -e errmax ] [ -p port ] ipaddress | s6-clockview
- s6-sntpclock exchanges SNTPv4 messages with a SNTP server
listening on ipaddress, UDP port 123.
ipaddress can be IPv4 or IPv6.
- It computes the mean difference between the absolute time
given by the system clock and the one given by the server.
- It prints the difference to stdout in a format understood
by s6-clockadd and
s6-clockview. It then exits 0.
Options
- -f : force. Normally, s6-sntpclock exits 111 if it cannot
compute a time with a smaller uncertainty than errmax. If this
option is set, it will output a time difference and exit 0 even if the
error is too big.
- -v verbosity : be more or less verbose.
By default, verbosity is 1. 0 means only print fatal error
messages; 3 means trace every exchange with the server.
- -r roundtrips : perform roundtrips
exchanges with the server. By default, roundtrips is 10. A lower
value yields a higher time uncertainty; a higher value puts more load on
the server.
- -t triptimeout : if a SNTP exchange with
the server takes more than triptimeout milliseconds, abort this
exchange and move on to the next one. By default, triptimeout
is 2000.
- -h throttle : wait throttle
milliseconds between exchanges with the server. A lower value gets the
final result earlier, but exerts more load on the server. A higher
value puts a lighter load on the server, but delays the computation.
By default, throttle is 0. It is recommended to set it to a
reasonable nonzero value when increasing roundtrips.
- -T totaltimeout : if the whole
operation takes more than totaltimeout milliseconds, abort
and exit 1. By default, totaltimeout is 10000.
- -e errmax : accept a maximum time
uncertainty of errmax milliseconds. By default, errmax
is 100.
- -p port : contact a server on port
port. By default, port is 123.
Notes
- There are a lot of infelicities in the NTP protocol (which SNTP is
a subset of). The biggest offender is probably that NTP cannot handle
a time difference of more than 34 years: if the time given by the NTP
server is more than 34 years away from the time given by the system clock,
then NTP just cannot compute. This is a problem for CMOS-less systems,
where the system clock is initialized to the Unix Epoch. The solution
is to first manually initialize the system clock with a program such as
date or
s6-clock
to a closer time (such as 2013-01-01, which will be good up to 2047), then
contact the NTP server.
- A less obvious problem with NTP is that it works with UTC time,
which means that it gives inaccurate results when close to a leap second,
up to one second off when used during a leap second, and this
is bound to the use of UTC: there is nothing you can do about it. The
only solution to get reliable results even around a leap second is to
use linear time such as TAI; the
s6-taiclock and
s6-taiclockd programs provide tools to
do so.
A word on ntpd
From a Unix software engineering standpoint, the well-known
ntpd program is an
eldritch abomination. The main reason for it is that, just like its
lovely cousin BIND,
ntpd performs a lot of different tasks in a unique process, instead
of separating what could, and should, be separated. This is confusing
for both the programmer and the software user.
- The term "NTP server" means two different things:
- A program that serves NTP time to the Internet and can be
accessed by NTP clients.
- A daemon, i.e. a long-lived process, that runs on a machine
and handles NTP-related stuff such as keeping the system clock accurate.
The former is the real meaning of "NTP server". The latter is a common
usage for the term, but comes from a misuse of "server" to mean "daemon".
ntpd does not help clear the misunderstanding since it does both. It acts
as an NTP server, and as an NTP client getting its time from
lower-strata NTP servers, and as a local system clock management
daemon. Those are already 3 separate tasks.
- Local system clock management itself involves several duties. There
is the regular setting of the system clock, which can be done with
a loop over a simple program such as s6-clockadd.
There is also control of the clock skew, which s6-networking does not
provide because there is no portable interface for that; there is such a tool
in the clockspeed package.
- ntpd includes a complete cryptographic key management system for the
crypto part of NTP. NTP is not the only protocol that uses cryptography
and asymmetric keys; managing keys in a separate tool, not in the NTP
daemon itself, would be simpler and smarter.
- ntpd provides monitoring support for client and server timekeeping
performance. This would be best implemented as a separate specific log
analyzing tool.
And of course, no matter how many layers of complexity you add onto
ntpd, it will never be able to give accurate time in the vicinity of a
leap second, since the very protocol is flawed by design - but
the ntpd authors cannot be blamed for that. Also, the ntpd
writers, not the designers, should be praised: the history of
ntpd security flaws is remarkably small, which is quite a feat for a
huge monolithic root daemon.
Network synchronization is important, NTP has its perks and
valid use cases, and its existence is a good thing. However, I wish that
the main NTP implementation weren't written as a big fat clumsy process
running as root. s6-sntpclock together with
s6-clockadd aims to provide a small, simple
tool to keep system clocks, especially in embedded devices, synchronized
to a NTP server.