summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Blut <vincent.debian@free.fr>2019-05-03 23:09:08 +0200
committerVincent Blut <vincent.debian@free.fr>2019-05-03 23:09:08 +0200
commitaff496ced38fb2ac20b6b4607c29a9b25042d28f (patch)
tree8b8d1f9f618f22f3c58089333910bac95b65e9cf
parenta86d8fa791700e1243d9e39eb8adc1c6d79bd41f (diff)
New upstream version 3.5-pre1
-rw-r--r--FAQ34
-rw-r--r--INSTALL23
-rw-r--r--Makefile.in8
-rw-r--r--NEWS17
-rw-r--r--README109
-rw-r--r--client.c2
-rw-r--r--cmdmon.c2
-rwxr-xr-xconfigure45
-rw-r--r--doc/chrony.conf.adoc69
-rw-r--r--doc/chrony.conf.man.in73
-rw-r--r--doc/chronyc.man.in4
-rw-r--r--doc/chronyd.man.in4
-rw-r--r--doc/faq.adoc29
-rw-r--r--doc/installation.adoc13
-rw-r--r--examples/chrony.conf.example32
-rw-r--r--examples/chrony.keys.example7
-rw-r--r--examples/chrony.spec46
-rw-r--r--hash_intmd5.c1
-rw-r--r--hash_tomcrypt.c2
-rw-r--r--hwclock.c2
-rw-r--r--logging.c2
-rw-r--r--main.c2
-rw-r--r--nameserv.c3
-rw-r--r--ntp_io.c16
-rw-r--r--ntp_io_linux.c6
-rw-r--r--refclock.c66
-rw-r--r--refclock.h1
-rw-r--r--refclock_phc.c3
-rw-r--r--refclock_pps.c3
-rw-r--r--refclock_shm.c3
-rw-r--r--refclock_sock.c2
-rw-r--r--reference.c2
-rw-r--r--samplefilt.c2
-rw-r--r--sources.c2
-rw-r--r--sourcestats.c2
-rw-r--r--sys.c13
-rw-r--r--sys_linux.c208
-rw-r--r--sys_linux.h4
-rw-r--r--sys_macosx.c42
-rw-r--r--sys_posix.c109
-rw-r--r--sys_posix.h36
-rw-r--r--sysincl.h2
-rwxr-xr-xtest/simulation/008-ntpera2
-rwxr-xr-xtest/simulation/012-daemonts15
-rwxr-xr-xtest/simulation/105-ntpauth2
-rwxr-xr-xtest/simulation/106-refclock4
-rwxr-xr-xtest/simulation/107-allowdeny2
-rwxr-xr-xtest/simulation/110-chronyc26
-rwxr-xr-xtest/simulation/112-port2
-rwxr-xr-xtest/simulation/113-leapsecond3
-rwxr-xr-xtest/simulation/115-cmdmontime3
-rwxr-xr-xtest/simulation/119-smoothtime3
-rwxr-xr-xtest/simulation/121-orphan2
-rwxr-xr-xtest/simulation/124-tai3
-rwxr-xr-xtest/simulation/128-nocontrol2
-rwxr-xr-xtest/simulation/129-reload3
-rwxr-xr-xtest/simulation/133-hwtimestamp4
-rwxr-xr-xtest/simulation/134-log33
-rwxr-xr-xtest/simulation/135-ratelimit18
-rwxr-xr-xtest/simulation/136-broadcast16
-rw-r--r--test/simulation/test.common29
-rwxr-xr-xtest/system/001-minimal13
-rwxr-xr-xtest/system/002-extended13
-rwxr-xr-xtest/system/003-memlock15
-rwxr-xr-xtest/system/004-priority15
-rwxr-xr-xtest/system/005-scfilter17
-rwxr-xr-xtest/system/006-privdrop17
-rwxr-xr-xtest/system/007-cmdmon69
-rwxr-xr-xtest/system/100-clockupdate30
-rwxr-xr-xtest/system/101-rtc19
-rwxr-xr-xtest/system/102-hwtimestamp28
-rwxr-xr-xtest/system/103-refclock19
-rwxr-xr-xtest/system/104-systemdirs19
-rwxr-xr-xtest/system/run64
-rw-r--r--test/system/test.common339
-rw-r--r--test/unit/Makefile.in12
-rw-r--r--test/unit/hwclock.c2
-rw-r--r--test/unit/ntp_core.c16
-rw-r--r--test/unit/ntp_sources.c14
-rw-r--r--test/unit/samplefilt.c6
-rw-r--r--test/unit/sources.c2
-rw-r--r--test/unit/test.c8
-rw-r--r--test/unit/test.h9
-rw-r--r--util.c2
-rw-r--r--version.txt2
85 files changed, 1511 insertions, 432 deletions
diff --git a/FAQ b/FAQ
index 76e62fc..f4b38fe 100644
--- a/FAQ
+++ b/FAQ
@@ -15,7 +15,8 @@ Table of Contents
? 2.6. How can I improve the accuracy of the system clock with NTP
sources?
? 2.7. Does chronyd have an ntpdate mode?
- ? 2.8. What happened to the commandkey and generatecommandkey directives?
+ ? 2.8. Can chronyd be configured to control the clock like ntpd?
+ ? 2.9. What happened to the commandkey and generatecommandkey directives?
o 3. Computer is not synchronising
? 3.1. Behind a firewall?
? 3.2. Are NTP servers specified with the offline option?
@@ -226,6 +227,12 @@ tens of nanoseconds may be possible. For example:
server ntp.local minpoll 0 maxpoll 0 xleave
hwtimestamp eth0
+For best stability, the CPU should be running at a constant frequency (i.e.
+disabled power saving and performance boosting). Energy-Efficient Ethernet
+(EEE) should be disabled in the network. The switches should be configured to
+prioritize NTP packets, especially if the network is expected to be heavily
+loaded.
+
If it is acceptable for NTP clients in the network to send requests at an
excessive rate, a sub-second polling interval may be specified. A median filter
can be enabled in order to update the clock at a reduced rate with more stable
@@ -243,7 +250,28 @@ command line. For example:
# chronyd -q 'pool pool.ntp.org iburst'
-2.8. What happened to the commandkey and generatecommandkey directives?
+2.8. Can chronyd be configured to control the clock like ntpd?
+
+It is not possible to perfectly emulate ntpd, but there are some options that
+can configure chronyd to behave more like ntpd.
+
+In the following example the minsamples directive slows down the response to
+changes in the frequency and offset of the clock. The maxslewrate and
+corrtimeratio directives reduce the maximum frequency error due to an offset
+correction and the maxdrift directive reduces the maximum assumed frequency
+error of the clock. The makestep directive enables a step threshold and the
+maxchange directive enables a panic threshold. The maxclockerror directive
+increases the minimum dispersion rate.
+
+minsamples 32
+maxslewrate 500
+corrtimeratio 100
+maxdrift 500
+makestep 0.128 -1
+maxchange 1000 1 1
+maxclockerror 15
+
+2.9. What happened to the commandkey and generatecommandkey directives?
They were removed in version 2.2. Authentication is no longer supported in the
command protocol. Commands that required authentication are now allowed only
@@ -516,4 +544,4 @@ needs to be made to work as a service.
We have no plans to do this. Anyone is welcome to pick this work up and
contribute it back to the project.
-Last updated 2018-08-31 10:11:17 CEST
+Last updated 2019-05-02 11:50:41 CEST
diff --git a/INSTALL b/INSTALL
index 250dd45..a77cfa7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -4,6 +4,27 @@ The software is distributed as source code which has to be compiled. The source
code is supplied in the form of a gzipped tar file, which unpacks to a
subdirectory identifying the name and version of the program.
+The following programs and libraries with their development files are needed to
+build chrony:
+
+ o C compiler (gcc or clang recommended)
+
+ o GNU Make
+
+ o Nettle, NSS, or LibTomCrypt (optional)
+
+ o Editline (optional)
+
+ o libcap (Linux only, optional)
+
+ o libseccomp (Linux only, optional)
+
+ o timepps.h header (optional)
+
+ o Asciidoctor (for HTML documentation)
+
+ o Bash (for testing)
+
After unpacking the source code, change directory into it, and type
./configure
@@ -171,4 +192,4 @@ tar cvf - . | gzip -9 > chrony.tar.gz
to build a package. When untarred within the root directory, this will install
the files to the intended final locations.
-Last updated 2018-08-31 10:11:17 CEST
+Last updated 2019-05-02 11:50:41 CEST
diff --git a/Makefile.in b/Makefile.in
index e748968..8e68ef4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -70,7 +70,8 @@ distclean : clean
-rm -f Makefile config.h config.log
clean :
- -rm -f *.o *.s chronyc chronyd core *~
+ -rm -f *.o *.s chronyc chronyd core.* *~
+ -rm -f *.gcda *.gcno
-rm -rf .deps
-rm -rf *.dSYM
@@ -112,10 +113,15 @@ install-docs :
quickcheck : chronyd chronyc
$(MAKE) -C test/unit check
cd test/simulation && ./run
+ cd test/system && ./run
check : chronyd chronyc
$(MAKE) -C test/unit check
cd test/simulation && ./run -i 20 -m 2
+ cd test/system && ./run
+
+print-chronyd-objects :
+ @echo $(OBJS) $(EXTRA_OBJS)
Makefile : Makefile.in configure
@echo
diff --git a/NEWS b/NEWS
index 51a0c22..b0baf06 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,20 @@
+New in version 3.5
+==================
+
+Enhancements
+------------
+* Add support for more accurate reading of PHC on Linux 5.0
+* Add support for memory locking and real-time priority on FreeBSD,
+ NetBSD, Solaris
+* Update seccomp filter to work on more architectures
+* Validate refclock driver options
+
+Bug fixes
+---------
+* Fix bindaddress directive on FreeBSD
+* Fix transposition of hardware RX timestamp on Linux 4.13 and later
+* Fix building on non-glibc systems
+
New in version 3.4
==================
diff --git a/README b/README
index aad727e..a492446 100644
--- a/README
+++ b/README
@@ -108,132 +108,57 @@ The following people have provided patches and other major contributions
to the program :
Lonnie Abelbeck <lonnie@abelbeck.com>
- Patch to add tab-completion to chronyc
-
Benny Lyne Amorsen <benny@amorsen.dk>
- Patch to add minstratum option
-
Andrew Bishop <amb@gedanken.demon.co.uk>
- Fixes for bugs in logging when in daemon mode
- Fixes for compiler warnings
- Robustness improvements for drift file
- Improve installation (directory checking etc)
- Entries in contrib directory
- Improvements to 'sources' and 'sourcestats' output from chronyc
- Improvements to documentation
- Investigation of required dosynctodr behaviour for various Solaris
- versions
-
+Vincent Blut <vincent.debian@free.fr>
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
- Entries in contrib directory
-
+Goswin Brederlow <brederlo@informatik.uni-tuebingen.de>
+Leigh Brown <leigh@solinno.co.uk>
Erik Bryer <ebryer@spots.ab.ca>
- Entries in contrib directory
-
+Jonathan Cameron <jic23@cam.ac.uk>
Bryan Christianson <bryan@whatroute.net>
- Support for macOS
- Support for privilege separation
- Entries in contrib directory
-
Juliusz Chroboczek <jch@pps.jussieu.fr>
- Patch to fix install rule in Makefile if chronyd file is in use
-
Christian Ehrhardt <christian.ehrhardt@canonical.com>
- Patch to generate a warning message when CAP_SYS_TIME is missing
-
Paul Elliott <pelliott@io.com>
- Entries in contrib directory
-
+Stefan R. Filipek <srfilipek@gmail.com>
Mike Fleetwood <mike@rockover.demon.co.uk>
- Fixes for compiler warnings
-
Alexander Gretencord <arutha@gmx.de>
- Changes to installation directory system to make it easier for
- package builders
-
Andrew Griffiths <agriffit@redhat.com>
- Patch to add support for seccomp filter
-
Walter Haidinger <walter.haidinger@gmx.at>
- Access to a Linux installation where v1.12 wouldn't compile
- Disc space for an independent backup of the sources
-
Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
- Port to NetBSD
-
John Hasler <john@dhh.gt.org>
- Project and website at tuxfamily.org
- Changes to support 64 bit machines (i.e. those where
- sizeof(unsigned long) > 4)
- Bug fix to initstepslew directive
- Fix to remove potential buffer overrun errors
- Memory locking and real-time scheduler support
- Fix fault where chronyd enters an endless loop
-
Tjalling Hattink <t.hattink@fugro.nl>
- Fix scheduler to allow stepping clock from timeout handler
- Patch to take leap second in PPS refclock from locked source
- Patch to make reading of RTC for initial trim more reliable
-
Liam Hatton <me@liamhatton.com>
- Advice on configuring for Linux on PPC
-
Jachym Holecek <jakym@volny.cz>
- Patch to make Linux real time clock work with devfs
-
HÃ¥kan Johansson <f96hajo@chalmers.se>
- Patch to avoid large values in sources and sourcestats output
-
Jim Knoble <jmknoble@pobox.com>
- Fixes for compiler warnings
-
Antti Jrvinen <costello@iki.fi>
- Advice on configuring for BSD/386
-
+Eric Lammerts <eric@lammerts.org>
+Stefan Lucke <stefan@lucke.in-berlin.de>
+Victor Lum <viclum@vanu.com>
+Kevin Lyda <kevin@ie.suberic.net>
+Paul Menzel <paulepanter@users.sourceforge.net>
+Vladimir Michl <vladimir.michl@seznam.cz>
Victor Moroz <vim@prv.adlum.ru>
- Patch to support Linux with HZ!=100
-
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
- Patch to add acquisitionport directive
-
Frank Otto <sandwichmacher@web.de>
- Handling arbitrary HZ values
-
Denny Page <dennypage@me.com>
- Advice on support for hardware timestamping
-
Chris Perl <cperl@janestreet.com>
- Patches to improve support for refclocks keeping time in TAI
-
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
- Patch to add refresh command to chronyc
-
Andreas Piesk <apiesk@virbus.de>
- Patch to make chronyc use the readline library if available
-
Andreas Steinmetz <ast@domdv.de>
- Patch to make stratum of refclocks configurable
-
+NAKAMURA Takumi <takumi@ps.sakura.ne.jp>
Timo Teras <timo.teras@iki.fi>
- Patch to reply correctly on multihomed hosts
-
Bill Unruh <unruh@physics.ubc.ca>
- Advice on statistics
-
Stephen Wadeley <swadeley@redhat.com>
- Improvements to man pages
-
+Bernhard Weiss <lisnablagh@web.de>
Wolfgang Weisselberg <weissel@netcologne.de>
- Entries in contrib directory
-
+Bernhard M. Wiedemann <bwiedemann@suse.de>
+Joachim Wiedorn <ad_debian@joonet.de>
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
- Many robustness and security improvements
-
-Ulrich Windl <ulrich.windl@rz.uni-regensburg.de> for the
- Information about the Linux 2.2 kernel functionality compared to 2.0
-
+Ulrich Windl <ulrich.windl@rz.uni-regensburg.de>
Doug Woodward <dougw@whistler.com>
- Advice on configuring for Solaris 2.8 on x86
+Thomas Zajic <zlatko@zlatko.fdns.net>
Many other people have contributed bug reports and suggestions. We are sorry
we cannot identify all of you individually.
diff --git a/client.c b/client.c
index 5b6056e..029860c 100644
--- a/client.c
+++ b/client.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Lonnie Abelbeck 2016
+ * Copyright (C) Lonnie Abelbeck 2016, 2018
* Copyright (C) Miroslav Lichvar 2009-2018
*
* This program is free software; you can redistribute it and/or modify
diff --git a/cmdmon.c b/cmdmon.c
index e069588..3b4277a 100644
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2009-2016
+ * Copyright (C) Miroslav Lichvar 2009-2016, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/configure b/configure
index 33aacdf..9e21a8b 100755
--- a/configure
+++ b/configure
@@ -227,6 +227,7 @@ feat_timestamping=1
try_timestamping=0
feat_ntp_signd=0
ntp_era_split=""
+use_pthread=0
default_user="root"
default_hwclockfile=""
default_pidfile="/var/run/chrony/chronyd.pid"
@@ -395,7 +396,7 @@ SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
case $OPERATINGSYSTEM in
Linux)
- EXTRA_OBJECTS="sys_generic.o sys_linux.o sys_timex.o"
+ EXTRA_OBJECTS="sys_generic.o sys_linux.o sys_timex.o sys_posix.o"
[ $try_libcap != "0" ] && try_libcap=1
try_rtc=1
[ $try_seccomp != "0" ] && try_seccomp=1
@@ -410,7 +411,9 @@ case $OPERATINGSYSTEM in
# recvmmsg() seems to be broken on FreeBSD 11.0 and it's just
# a wrapper around recvmsg()
try_recvmmsg=0
- EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
+ EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o sys_posix.o"
+ try_setsched=1
+ try_lockmem=1
add_def FREEBSD
if [ $feat_droproot = "1" ]; then
add_def FEAT_PRIVDROP
@@ -419,8 +422,10 @@ case $OPERATINGSYSTEM in
echo "Configuring for $SYSTEM"
;;
NetBSD)
- EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
+ EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o sys_posix.o"
try_clockctl=1
+ try_setsched=1
+ try_lockmem=1
add_def NETBSD
echo "Configuring for $SYSTEM"
;;
@@ -445,9 +450,11 @@ case $OPERATINGSYSTEM in
echo "Configuring for macOS (" $SYSTEM "macOS version" $VERSION ")"
;;
SunOS)
- EXTRA_OBJECTS="sys_generic.o sys_solaris.o sys_timex.o"
+ EXTRA_OBJECTS="sys_generic.o sys_solaris.o sys_timex.o sys_posix.o"
EXTRA_LIBS="-lsocket -lnsl -lresolv"
EXTRA_CLI_LIBS="-lsocket -lnsl -lresolv"
+ try_setsched=1
+ try_lockmem=1
add_def SOLARIS
# These are needed to have msg_control in struct msghdr
add_def __EXTENSIONS__
@@ -647,12 +654,12 @@ fi
if [ $feat_asyncdns = "1" ] && \
test_code 'pthread' 'pthread.h' '-pthread' '' \
- 'return pthread_create((void *)1, NULL, (void *)1, NULL);'
+ 'return (int)pthread_create((void *)1, NULL, (void *)1, NULL);'
then
add_def FEAT_ASYNCDNS
add_def USE_PTHREAD_ASYNCDNS
EXTRA_OBJECTS="$EXTRA_OBJECTS nameserv_async.o"
- MYCFLAGS="$MYCFLAGS -pthread"
+ use_pthread=1
fi
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
@@ -786,25 +793,33 @@ fi
if [ $try_setsched = "1" ] && \
test_code \
- 'sched_setscheduler()' \
- 'sched.h' '' '' '
+ 'pthread_setschedparam()' \
+ 'pthread.h sched.h' '-pthread' '' '
struct sched_param sched;
sched_get_priority_max(SCHED_FIFO);
- sched_setscheduler(0, SCHED_FIFO, &sched);'
+ pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched);'
then
- add_def HAVE_SCHED_SETSCHEDULER
+ add_def HAVE_PTHREAD_SETSCHEDPARAM
+ use_pthread=1
fi
if [ $try_lockmem = "1" ] && \
test_code \
'mlockall()' \
- 'sys/mman.h sys/resource.h' '' '' '
- struct rlimit rlim;
- setrlimit(RLIMIT_MEMLOCK, &rlim);
+ 'sys/mman.h' '' '' '
mlockall(MCL_CURRENT|MCL_FUTURE);'
then
add_def HAVE_MLOCKALL
fi
+if [ $try_lockmem = "1" ] && \
+ test_code \
+ 'setrlimit(RLIMIT_MEMLOCK, ...)' \
+ 'sys/resource.h' '' '' '
+ struct rlimit rlim;
+ setrlimit(RLIMIT_MEMLOCK, &rlim);'
+then
+ add_def HAVE_SETRLIMIT_MEMLOCK
+fi
if [ $feat_forcednsretry = "1" ]
then
@@ -896,6 +911,10 @@ if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]
fi
fi
+if [ $use_pthread = "1" ]; then
+ MYCFLAGS="$MYCFLAGS -pthread"
+fi
+
SYSCONFDIR=/etc
if [ "x$SETSYSCONFDIR" != "x" ]; then
SYSCONFDIR=$SETSYSCONFDIR
diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc
index 4a39c21..e1fbef3 100644
--- a/doc/chrony.conf.adoc
+++ b/doc/chrony.conf.adoc
@@ -374,12 +374,12 @@ for *initstepslew* to finish before exiting. This is useful to prevent programs
started in the boot sequence after *chronyd* from reading the clock before it
has been stepped.
-[[refclock]]*refclock* _driver_ _parameter_[:__option__,...] [_option_]...::
+[[refclock]]*refclock* _driver_ _parameter_[:__option__]... [_option_]...::
The *refclock* directive specifies a hardware reference clock to be used as a
time source. It has two mandatory parameters, a driver name and a
driver-specific parameter. The two parameters are followed by zero or more
refclock options. Some drivers have special options, which can be appended to
-the driver-specific parameter (separated by the *:* and *,* characters).
+the driver-specific parameter using the *:* character.
+
There are four drivers included in *chronyd*:
+
@@ -476,7 +476,7 @@ Examples:
----
refclock PHC /dev/ptp0 poll 0 dpoll -2 offset -37
refclock PHC /dev/ptp1:nocrossts poll 3 pps
-refclock PHC /dev/ptp2:extpps,pin=1 width 0.2 poll 2
+refclock PHC /dev/ptp2:extpps:pin=1 width 0.2 poll 2
----
+
::
@@ -661,6 +661,13 @@ The *minsamples* directive sets the default minimum number of samples that
*chronyd* should keep for each source. This setting can be overridden for
individual sources in the <<server,*server*>> and <<refclock,*refclock*>>
directives. The default value is 6. The useful range is 4 to 64.
++
+Forcing *chronyd* to keep more samples than it would normally keep reduces
+noise in the estimated frequency and offset, but slows down the response to
+changes in the frequency and offset of the clock. The offsets in the
+<<chronyc.adoc#tracking,*tracking*>> and
+<<chronyc.adoc#sourcestats,*sourcestats*>> reports (and the _tracking.log_ and
+_statistics.log_ files) may be smaller than the actual offsets.
=== Source selection
@@ -674,6 +681,8 @@ The *combinelimit* directive limits which sources are included in the combining
algorithm. Their synchronisation distance has to be shorter than the distance
of the selected source multiplied by the value of the limit. Also, their
measured frequencies have to be close to the frequency of the selected source.
+If the selected source was specified with the *prefer* option, it can be
+combined only with other sources specified with this option.
+
By default, the limit is 3. Setting the limit to 0 effectively disables the
source combining algorithm and only the selected source will be used to control
@@ -1594,8 +1603,8 @@ If the *rtconutc* directive appears, it means the RTC is required to keep UTC.
The directive takes no arguments. It is equivalent to specifying the *-u*
switch to the Linux *hwclock* program.
+
-Note that this setting is overridden when the <<hwclockfile,*hwclockfile*>>
-directive is specified.
+Note that this setting is overridden by the <<hwclockfile,*hwclockfile*>> file
+and is not relevant for the <<rtcsync,*rtcsync*>> directive.
[[rtcsync]]*rtcsync*::
The *rtcsync* directive enables a mode where the system time is periodically
@@ -2049,14 +2058,18 @@ that has password shorter than 80 bits.
The <<chronyc.adoc#keygen,*keygen*>> command of *chronyc* can be used to
generate random keys for the key file. By default, it generates 160-bit MD5 or
SHA1 keys.
++
+For security reasons, the file should be readable only by root and the user
+under which *chronyd* is normally running (to allow *chronyd* to re-read the
+file when the <<chronyc.adoc#rekey,*rekey*>> command is issued by *chronyc*).
[[lock_all]]*lock_all*::
The *lock_all* directive will lock chronyd into RAM so that it will never be
-paged out. This mode is only supported on Linux. This directive uses the Linux
-*mlockall()* system call to prevent *chronyd* from ever being swapped out. This
-should result in lower and more consistent latency. It should not have
-significant impact on performance as *chronyd's* memory usage is modest. The
-*mlockall(2)* man page has more details.
+paged out. This mode is supported on Linux, FreeBSD, NetBSD, and Solaris. This
+directive uses the POSIX *mlockall()* system call to prevent *chronyd* from
+ever being swapped out. This should result in lower and more consistent
+latency. It should not have significant impact on performance as *chronyd's*
+memory usage is modest. The *mlockall(2)* man page has more details.
[[pidfile]]*pidfile* _file_::
Unless *chronyd* is started with the *-Q* option, it writes its process ID
@@ -2070,26 +2083,26 @@ pidfile /run/chronyd.pid
----
[[sched_priority]]*sched_priority* _priority_::
-On Linux, the *sched_priority* directive will select the SCHED_FIFO real-time
-scheduler at the specified priority (which must be between 0 and 100). On
-macOS, this option must have either a value of 0 (the default) to disable the
-thread time constraint policy or 1 for the policy to be enabled. Other systems
-do not support this option.
-+
-On Linux, this directive uses the *sched_setscheduler()* system call to
-instruct the kernel to use the SCHED_FIFO first-in, first-out real-time
-scheduling policy for *chronyd* with the specified priority. This means that
-whenever *chronyd* is ready to run it will run, interrupting whatever else is
-running unless it is a higher priority real-time process. This should not
-impact performance as *chronyd* resource requirements are modest, but it should
-result in lower and more consistent latency since *chronyd* will not need to
-wait for the scheduler to get around to running it. You should not use this
-unless you really need it. The *sched_setscheduler(2)* man page has more
-details.
+On Linux, FreeBSD, NetBSD, and Solaris, the *sched_priority* directive will
+select the SCHED_FIFO real-time scheduler at the specified priority (which must
+be between 0 and 100). On macOS, this option must have either a value of 0 (the
+default) to disable the thread time constraint policy or 1 for the policy to be
+enabled.
++
+On systems other than macOS, this directive uses the *pthread_setschedparam()*
+system call to instruct the kernel to use the SCHED_FIFO first-in, first-out
+real-time scheduling policy for *chronyd* with the specified priority. This
+means that whenever *chronyd* is ready to run it will run, interrupting
+whatever else is running unless it is a higher priority real-time process. This
+should not impact performance as *chronyd* resource requirements are modest,
+but it should result in lower and more consistent latency since *chronyd* will
+not need to wait for the scheduler to get around to running it. You should not
+use this unless you really need it. The *pthread_setschedparam(3)* man page has
+more details.
+
On macOS, this directive uses the *thread_policy_set()* kernel call to
-specify real-time scheduling. As noted for Linux, you should not use this
-directive unless you really need it.
+specify real-time scheduling. As noted above, you should not use this directive
+unless you really need it.
[[user]]*user* _user_::
The *user* directive sets the name of the system user to which *chronyd* will
diff --git a/doc/chrony.conf.man.in b/doc/chrony.conf.man.in
index 28fb647..c058e8d 100644
--- a/doc/chrony.conf.man.in
+++ b/doc/chrony.conf.man.in
@@ -2,12 +2,12 @@
.\" Title: chrony.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: Asciidoctor 1.5.6.1
-.\" Date: 2018-08-31
+.\" Date: 2019-05-02
.\" Manual: Configuration Files
.\" Source: chrony @CHRONY_VERSION@
.\" Language: English
.\"
-.TH "CHRONY.CONF" "5" "2018-08-31" "chrony @CHRONY_VERSION@" "Configuration Files"
+.TH "CHRONY.CONF" "5" "2019-05-02" "chrony @CHRONY_VERSION@" "Configuration Files"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
@@ -469,13 +469,13 @@ started in the boot sequence after \fBchronyd\fP from reading the clock before i
has been stepped.
.RE
.sp
-\fBrefclock\fP \fIdriver\fP \fIparameter\fP[:\fIoption\fP,...] [\fIoption\fP]...
+\fBrefclock\fP \fIdriver\fP \fIparameter\fP[:\fIoption\fP]... [\fIoption\fP]...
.RS 4
The \fBrefclock\fP directive specifies a hardware reference clock to be used as a
time source. It has two mandatory parameters, a driver name and a
driver\-specific parameter. The two parameters are followed by zero or more
refclock options. Some drivers have special options, which can be appended to
-the driver\-specific parameter (separated by the \fB:\fP and \fB,\fP characters).
+the driver\-specific parameter using the \fB:\fP character.
.sp
There are four drivers included in \fBchronyd\fP:
.sp
@@ -626,7 +626,7 @@ Examples:
.nf
refclock PHC /dev/ptp0 poll 0 dpoll \-2 offset \-37
refclock PHC /dev/ptp1:nocrossts poll 3 pps
-refclock PHC /dev/ptp2:extpps,pin=1 width 0.2 poll 2
+refclock PHC /dev/ptp2:extpps:pin=1 width 0.2 poll 2
.fi
.if n \{\
.RE
@@ -903,6 +903,13 @@ The \fBminsamples\fP directive sets the default minimum number of samples that
\fBchronyd\fP should keep for each source. This setting can be overridden for
individual sources in the \fBserver\fP and \fBrefclock\fP
directives. The default value is 6. The useful range is 4 to 64.
+.sp
+Forcing \fBchronyd\fP to keep more samples than it would normally keep reduces
+noise in the estimated frequency and offset, but slows down the response to
+changes in the frequency and offset of the clock. The offsets in the
+\fBtracking\fP and
+\fBsourcestats\fP reports (and the \fItracking.log\fP and
+\fIstatistics.log\fP files) may be smaller than the actual offsets.
.RE
.SS "Source selection"
.sp
@@ -917,6 +924,8 @@ The \fBcombinelimit\fP directive limits which sources are included in the combin
algorithm. Their synchronisation distance has to be shorter than the distance
of the selected source multiplied by the value of the limit. Also, their
measured frequencies have to be close to the frequency of the selected source.
+If the selected source was specified with the \fBprefer\fP option, it can be
+combined only with other sources specified with this option.
.sp
By default, the limit is 3. Setting the limit to 0 effectively disables the
source combining algorithm and only the selected source will be used to control
@@ -2152,8 +2161,8 @@ If the \fBrtconutc\fP directive appears, it means the RTC is required to keep UT
The directive takes no arguments. It is equivalent to specifying the \fB\-u\fP
switch to the Linux \fBhwclock\fP program.
.sp
-Note that this setting is overridden when the \fBhwclockfile\fP
-directive is specified.
+Note that this setting is overridden by the \fBhwclockfile\fP file
+and is not relevant for the \fBrtcsync\fP directive.
.RE
.sp
\fBrtcsync\fP
@@ -3445,16 +3454,20 @@ that has password shorter than 80 bits.
The \fBkeygen\fP command of \fBchronyc\fP can be used to
generate random keys for the key file. By default, it generates 160\-bit MD5 or
SHA1 keys.
+.sp
+For security reasons, the file should be readable only by root and the user
+under which \fBchronyd\fP is normally running (to allow \fBchronyd\fP to re\-read the
+file when the \fBrekey\fP command is issued by \fBchronyc\fP).
.RE
.sp
\fBlock_all\fP
.RS 4
The \fBlock_all\fP directive will lock chronyd into RAM so that it will never be
-paged out. This mode is only supported on Linux. This directive uses the Linux
-\fBmlockall()\fP system call to prevent \fBchronyd\fP from ever being swapped out. This
-should result in lower and more consistent latency. It should not have
-significant impact on performance as \fBchronyd\(cqs\fP memory usage is modest. The
-\fBmlockall(2)\fP man page has more details.
+paged out. This mode is supported on Linux, FreeBSD, NetBSD, and Solaris. This
+directive uses the POSIX \fBmlockall()\fP system call to prevent \fBchronyd\fP from
+ever being swapped out. This should result in lower and more consistent
+latency. It should not have significant impact on performance as \fBchronyd\(cqs\fP
+memory usage is modest. The \fBmlockall(2)\fP man page has more details.
.RE
.sp
\fBpidfile\fP \fIfile\fP
@@ -3478,26 +3491,26 @@ pidfile /run/chronyd.pid
.sp
\fBsched_priority\fP \fIpriority\fP
.RS 4
-On Linux, the \fBsched_priority\fP directive will select the SCHED_FIFO real\-time
-scheduler at the specified priority (which must be between 0 and 100). On
-macOS, this option must have either a value of 0 (the default) to disable the
-thread time constraint policy or 1 for the policy to be enabled. Other systems
-do not support this option.
-.sp
-On Linux, this directive uses the \fBsched_setscheduler()\fP system call to
-instruct the kernel to use the SCHED_FIFO first\-in, first\-out real\-time
-scheduling policy for \fBchronyd\fP with the specified priority. This means that
-whenever \fBchronyd\fP is ready to run it will run, interrupting whatever else is
-running unless it is a higher priority real\-time process. This should not
-impact performance as \fBchronyd\fP resource requirements are modest, but it should
-result in lower and more consistent latency since \fBchronyd\fP will not need to
-wait for the scheduler to get around to running it. You should not use this
-unless you really need it. The \fBsched_setscheduler(2)\fP man page has more
-details.
+On Linux, FreeBSD, NetBSD, and Solaris, the \fBsched_priority\fP directive will
+select the SCHED_FIFO real\-time scheduler at the specified priority (which must
+be between 0 and 100). On macOS, this option must have either a value of 0 (the
+default) to disable the thread time constraint policy or 1 for the policy to be
+enabled.
+.sp
+On systems other than macOS, this directive uses the \fBpthread_setschedparam()\fP
+system call to instruct the kernel to use the SCHED_FIFO first\-in, first\-out
+real\-time scheduling policy for \fBchronyd\fP with the specified priority. This
+means that whenever \fBchronyd\fP is ready to run it will run, interrupting
+whatever else is running unless it is a higher priority real\-time process. This
+should not impact performance as \fBchronyd\fP resource requirements are modest,
+but it should result in lower and more consistent latency since \fBchronyd\fP will
+not need to wait for the scheduler to get around to running it. You should not
+use this unless you really need it. The \fBpthread_setschedparam(3)\fP man page has
+more details.
.sp
On macOS, this directive uses the \fBthread_policy_set()\fP kernel call to
-specify real\-time scheduling. As noted for Linux, you should not use this
-directive unless you really need it.
+specify real\-time scheduling. As noted above, you should not use this directive
+unless you really need it.
.RE
.sp
\fBuser\fP \fIuser\fP
diff --git a/doc/chronyc.man.in b/doc/chronyc.man.in
index 5c76fe4..6ad8e01 100644
--- a/doc/chronyc.man.in
+++ b/doc/chronyc.man.in
@@ -2,12 +2,12 @@
.\" Title: chronyc
.\" Author: [see the "AUTHORS" section]
.\" Generator: Asciidoctor 1.5.6.1
-.\" Date: 2018-08-31
+.\" Date: 2019-05-02
.\" Manual: User manual
.\" Source: chrony @CHRONY_VERSION@
.\" Language: English
.\"
-.TH "CHRONYC" "1" "2018-08-31" "chrony @CHRONY_VERSION@" "User manual"
+.TH "CHRONYC" "1" "2019-05-02" "chrony @CHRONY_VERSION@" "User manual"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
diff --git a/doc/chronyd.man.in b/doc/chronyd.man.in
index a95de6a..e346d78 100644
--- a/doc/chronyd.man.in
+++ b/doc/chronyd.man.in
@@ -2,12 +2,12 @@
.\" Title: chronyd
.\" Author: [see the "AUTHORS" section]
.\" Generator: Asciidoctor 1.5.6.1
-.\" Date: 2018-08-31
+.\" Date: 2019-05-02
.\" Manual: System Administration
.\" Source: chrony @CHRONY_VERSION@
.\" Language: English
.\"
-.TH "CHRONYD" "8" "2018-08-31" "chrony @CHRONY_VERSION@" "System Administration"
+.TH "CHRONYD" "8" "2019-05-02" "chrony @CHRONY_VERSION@" "System Administration"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
diff --git a/doc/faq.adoc b/doc/faq.adoc
index 8e6926b..318b418 100644
--- a/doc/faq.adoc
+++ b/doc/faq.adoc
@@ -217,6 +217,12 @@ server ntp.local minpoll 0 maxpoll 0 xleave
hwtimestamp eth0
----
+For best stability, the CPU should be running at a constant frequency (i.e.
+disabled power saving and performance boosting). Energy-Efficient Ethernet
+(EEE) should be disabled in the network. The switches should be configured to
+prioritize NTP packets, especially if the network is expected to be heavily
+loaded.
+
If it is acceptable for NTP clients in the network to send requests at an
excessive rate, a sub-second polling interval may be specified. A median filter
can be enabled in order to update the clock at a reduced rate with more stable
@@ -238,6 +244,29 @@ specified on the command line. For example:
# chronyd -q 'pool pool.ntp.org iburst'
----
+=== Can `chronyd` be configured to control the clock like `ntpd`?
+
+It is not possible to perfectly emulate `ntpd`, but there are some options that
+can configure `chronyd` to behave more like `ntpd`.
+
+In the following example the `minsamples` directive slows down the response to
+changes in the frequency and offset of the clock. The `maxslewrate` and
+`corrtimeratio` directives reduce the maximum frequency error due to an offset
+correction and the `maxdrift` directive reduces the maximum assumed frequency
+error of the clock. The `makestep` directive enables a step threshold and the
+`maxchange` directive enables a panic threshold. The `maxclockerror` directive
+increases the minimum dispersion rate.
+
+----
+minsamples 32
+maxslewrate 500
+corrtimeratio 100
+maxdrift 500
+makestep 0.128 -1
+maxchange 1000 1 1
+maxclockerror 15
+----
+
=== What happened to the `commandkey` and `generatecommandkey` directives?
They were removed in version 2.2. Authentication is no longer supported in the
diff --git a/doc/installation.adoc b/doc/installation.adoc
index eea9088..3e0f3c3 100644
--- a/doc/installation.adoc
+++ b/doc/installation.adoc
@@ -22,6 +22,19 @@ The software is distributed as source code which has to be compiled. The source
code is supplied in the form of a gzipped tar file, which unpacks to a
subdirectory identifying the name and version of the program.
+The following programs and libraries with their development files are needed to
+build `chrony`:
+
+* C compiler (gcc or clang recommended)
+* GNU Make
+* Nettle, NSS, or LibTomCrypt (optional)
+* Editline (optional)
+* libcap (Linux only, optional)
+* libseccomp (Linux only, optional)
+* timepps.h header (optional)
+* Asciidoctor (for HTML documentation)
+* Bash (for testing)
+
After unpacking the source code, change directory into it, and type
----
diff --git a/examples/chrony.conf.example3 b/examples/chrony.conf.example3
index 05a4e98..c04f871 100644
--- a/examples/chrony.conf.example3
+++ b/examples/chrony.conf.example3
@@ -95,7 +95,7 @@ driftfile /var/lib/chrony/drift
# still running and bail out. If you want to change the path to the PID
# file, uncomment this line and edit it. The default path is shown.
-! pidfile /var/run/chronyd.pid
+! pidfile /var/run/chrony/chronyd.pid
# If the system timezone database is kept up to date and includes the
# right/UTC timezone, chronyd can use it to determine the current
diff --git a/examples/chrony.keys.example b/examples/chrony.keys.example
index 2dd19cd..65b6be2 100644
--- a/examples/chrony.keys.example
+++ b/examples/chrony.keys.example
@@ -1,6 +1,7 @@
-# This is an example chrony keys file. It is used for NTP authentication with
-# symmetric keys. It should be readable only by root or the user to which
-# chronyd is configured to switch to after start.
+# This is an example chrony keys file. It enables authentication of NTP
+# packets with symmetric keys when its location is specified by the keyfile
+# directive in chrony.conf(5). It should be readable only by root and the
+# user under which chronyd is running.
#
# Don't use the example keys! It's recommended to generate random keys using
# the chronyc keygen command.
diff --git a/examples/chrony.spec b/examples/chrony.spec
deleted file mode 100644
index 94454a5..0000000
--- a/examples/chrony.spec
+++ /dev/null
@@ -1,46 +0,0 @@
-%global chrony_version 3.4-pre1
-%if 0%(echo %{chrony_version} | grep -q pre && echo 1)
-%global prerelease %(echo %{chrony_version} | sed 's/.*-//')
-%endif
-Summary: An NTP client/server
-Name: chrony
-Version: %(echo %{chrony_version} | sed 's/-.*//')
-Release: %{!?prerelease:1}%{?prerelease:0.1.%{prerelease}}
-Source: chrony-%{version}%{?prerelease:-%{prerelease}}.tar.gz
-License: GPLv2
-Group: Applications/Utilities
-BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
-
-%description
-chrony is a client and server for the Network Time Protocol (NTP).
-This program keeps your computer's clock accurate. It was specially
-designed to support systems with intermittent Internet connections,
-but it also works well in permanently connected environments. It can
-also use hardware reference clocks, the system real-time clock, or
-manual input as time references.
-
-%prep
-%setup -q -n %{name}-%{version}%{?prerelease:-%{prerelease}}
-
-%build
-./configure \
- --prefix=%{_prefix} \
- --bindir=%{_bindir} \
- --sbindir=%{_sbindir} \
- --mandir=%{_mandir}
-make
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make install DESTDIR=$RPM_BUILD_ROOT
-
-%files
-%{_sbindir}/chronyd
-%{_bindir}/chronyc
-%{_mandir}/man1/chronyc.1.gz
-%{_mandir}/man5/chrony.conf.5.gz
-%{_mandir}/man8/chronyd.8.gz
-%doc README FAQ NEWS COPYING
-%doc examples/chrony.conf.example*
-%doc examples/chrony.keys.example
-
diff --git a/hash_intmd5.c b/hash_intmd5.c
index 0b60f9b..49da1cf 100644
--- a/hash_intmd5.c
+++ b/hash_intmd5.c
@@ -29,6 +29,7 @@
#include "sysincl.h"
#include "hash.h"
#include "memory.h"
+#include "util.h"
#include "md5.c"
diff --git a/hash_tomcrypt.c b/hash_tomcrypt.c
index 51b63d9..4326c9e 100644
--- a/hash_tomcrypt.c
+++ b/hash_tomcrypt.c
@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
- * Copyright (C) Miroslav Lichvar 2012
+ * Copyright (C) Miroslav Lichvar 2012, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/hwclock.c b/hwclock.c
index 6122ab2..8e13e7e 100644
--- a/hwclock.c
+++ b/hwclock.c
@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
- * Copyright (C) Miroslav Lichvar 2016-2017
+ * Copyright (C) Miroslav Lichvar 2016-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/logging.c b/logging.c
index 828ae30..d2296e0 100644
--- a/logging.c
+++ b/logging.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2011-2014
+ * Copyright (C) Miroslav Lichvar 2011-2014, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/main.c b/main.c
index c40fb25..6ccf32e 100644
--- a/main.c
+++ b/main.c
@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
- * Copyright (C) Miroslav Lichvar 2012-2017
+ * Copyright (C) Miroslav Lichvar 2012-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/nameserv.c b/nameserv.c
index 1cb9608..90a65b1 100644
--- a/nameserv.c
+++ b/nameserv.c
@@ -30,6 +30,9 @@
#include "sysincl.h"
+#include <netdb.h>
+#include <resolv.h>
+
#include "nameserv.h"
#include "util.h"
diff --git a/ntp_io.c b/ntp_io.c
index b71a1d4..ab08372 100644
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009
- * Copyright (C) Miroslav Lichvar 2009, 2013-2016
+ * Copyright (C) Miroslav Lichvar 2009, 2013-2016, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -105,6 +105,9 @@ static int separate_client_sockets;
disabled */
static int permanent_server_sockets;
+/* Flag indicating the server IPv4 socket is bound to an address */
+static int bound_server_sock_fd4;
+
/* Flag indicating that we have been initialised */
static int initialised=0;
@@ -168,6 +171,9 @@ prepare_socket(int family, int port_number, int client_only)
my_addr.in4.sin_port = htons(port_number);
my_addr_len = sizeof (my_addr.in4);
+ if (!client_only)
+ bound_server_sock_fd4 = my_addr.in4.sin_addr.s_addr != htonl(INADDR_ANY);
+
break;
#ifdef FEAT_IPV6
case AF_INET6:
@@ -821,8 +827,8 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
msg.msg_flags = 0;
cmsglen = 0;
- if (local_addr->ip_addr.family == IPADDR_INET4) {
#ifdef HAVE_IN_PKTINFO
+ if (local_addr->ip_addr.family == IPADDR_INET4) {
struct in_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg);
@@ -837,7 +843,11 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
ipi->ipi_spec_dst.s_addr = htonl(local_addr->ip_addr.addr.in4);
if (local_addr->if_index != INVALID_IF_INDEX)
ipi->ipi_ifindex = local_addr->if_index;
+ }
#elif defined(IP_SENDSRCADDR)
+ /* Specify the IPv4 source address only if the socket is not bound */
+ if (local_addr->ip_addr.family == IPADDR_INET4 &&
+ local_addr->sock_fd == server_sock_fd4 && !bound_server_sock_fd4) {
struct in_addr *addr;
cmsg = CMSG_FIRSTHDR(&msg);
@@ -850,8 +860,8 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
addr = (struct in_addr *)CMSG_DATA(cmsg);
addr->s_addr = htonl(local_addr->ip_addr.addr.in4);
-#endif
}
+#endif
#ifdef HAVE_IN6_PKTINFO
if (local_addr->ip_addr.family == IPADDR_INET6) {
diff --git a/ntp_io_linux.c b/ntp_io_linux.c
index 819792a..eb4a3a8 100644
--- a/ntp_io_linux.c
+++ b/ntp_io_linux.c
@@ -584,7 +584,11 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts,
if (rx_ntp_length && iface->link_speed) {
if (!l2_length)
l2_length = (family == IPADDR_INET4 ? iface->l2_udp4_ntp_start :
- iface->l2_udp6_ntp_start) + rx_ntp_length + 4;
+ iface->l2_udp6_ntp_start) + rx_ntp_length;
+
+ /* Include the frame check sequence (FCS) */
+ l2_length += 4;
+
rx_correction = l2_length / (1.0e6 / 8 * iface->link_speed);
UTI_AddDoubleToTimespec(hw_ts, rx_correction, hw_ts);
diff --git a/refclock.c b/refclock.c
index 66224d5..42fee4c 100644
--- a/refclock.c
+++ b/refclock.c
@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
- * Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2017
+ * Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -325,25 +325,57 @@ RCL_GetDriverParameter(RCL_Instance instance)
return instance->driver_parameter;
}
-char *
-RCL_GetDriverOption(RCL_Instance instance, char *name)
+static char *
+get_next_driver_option(RCL_Instance instance, char *option)
{
- char *s, *e;
- int n;
+ if (option == NULL)
+ option = instance->driver_parameter;
- s = instance->driver_parameter;
- e = s + instance->driver_parameter_length;
- n = strlen(name);
+ option += strlen(option) + 1;
- while (1) {
- s += strlen(s) + 1;
- if (s >= e)
- break;
- if (!strncmp(name, s, n)) {
- if (s[n] == '=')
- return s + n + 1;
- if (s[n] == '\0')
- return s + n;
+ if (option >= instance->driver_parameter + instance->driver_parameter_length)
+ return NULL;
+
+ return option;
+}
+
+void
+RCL_CheckDriverOptions(RCL_Instance instance, const char **options)
+{
+ char *option;
+ int i, len;
+
+ for (option = get_next_driver_option(instance, NULL);
+ option;
+ option = get_next_driver_option(instance, option)) {
+ for (i = 0; options && options[i]; i++) {
+ len = strlen(options[i]);
+ if (!strncmp(options[i], option, strlen(options[i])) &&
+ (option[len] == '=' || option[len] == '\0'))
+ break;
+ }
+
+ if (!options || !options[i])
+ LOG_FATAL("Invalid refclock driver option %s", option);
+ }
+}
+
+char *
+RCL_GetDriverOption(RCL_Instance instance, char *name)
+{
+ char *option;
+ int len;
+
+ len = strlen(name);
+
+ for (option = get_next_driver_option(instance, NULL);
+ option;
+ option = get_next_driver_option(instance, option)) {
+ if (!strncmp(name, option, len)) {
+ if (option[len] == '=')
+ return option + len + 1;
+ if (option[len] == '\0')
+ return option + len;
}
}
diff --git a/refclock.h b/refclock.h
index 724f620..69a0152 100644
--- a/refclock.h
+++ b/refclock.h
@@ -72,6 +72,7 @@ extern void RCL_ReportSource(RPT_SourceReport *report, struct timespec *now);
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
extern void *RCL_GetDriverData(RCL_Instance instance);
extern char *RCL_GetDriverParameter(RCL_Instance instance);
+extern void RCL_CheckDriverOptions(RCL_Instance instance, const char **options);
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
extern int RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap);
extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
diff --git a/refclock_phc.c b/refclock_phc.c
index 03450db..a000fe4 100644
--- a/refclock_phc.c
+++ b/refclock_phc.c
@@ -56,10 +56,13 @@ static void read_ext_pulse(int sockfd, int event, void *anything);
static int phc_initialise(RCL_Instance instance)
{
+ const char *options[] = {"nocrossts", "extpps", "pin", "channel", "clear", NULL};
struct phc_instance *phc;
int phc_fd, rising_edge;
char *path, *s;
+ RCL_CheckDriverOptions(instance, options);
+
path = RCL_GetDriverParameter(instance);
phc_fd = SYS_Linux_OpenPHC(path, 0);
diff --git a/refclock_pps.c b/refclock_pps.c
index 85ff9e9..b9e8009 100644
--- a/refclock_pps.c
+++ b/refclock_pps.c
@@ -48,12 +48,15 @@ struct pps_instance {
};
static int pps_initialise(RCL_Instance instance) {
+ const char *options[] = {"clear", NULL};
pps_handle_t handle;
pps_params_t params;
struct pps_instance *pps;
int fd, edge_clear, mode;
char *path;
+ RCL_CheckDriverOptions(instance, options);
+
path = RCL_GetDriverParameter(instance);
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
diff --git a/refclock_shm.c b/refclock_shm.c
index e8f6256..ed68095 100644
--- a/refclock_shm.c
+++ b/refclock_shm.c
@@ -59,10 +59,13 @@ struct shmTime {
};
static int shm_initialise(RCL_Instance instance) {
+ const char *options[] = {"perm", NULL};
int id, param, perm;
char *s;
struct shmTime *shm;
+ RCL_CheckDriverOptions(instance, options);
+
param = atoi(RCL_GetDriverParameter(instance));
s = RCL_GetDriverOption(instance, "perm");
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
diff --git a/refclock_sock.c b/refclock_sock.c
index 176310c..492ee32 100644
--- a/refclock_sock.c
+++ b/refclock_sock.c
@@ -101,6 +101,8 @@ static int sock_initialise(RCL_Instance instance)
int sockfd;
char *path;
+ RCL_CheckDriverOptions(instance, NULL);
+
path = RCL_GetDriverParameter(instance);
s.sun_family = AF_UNIX;
diff --git a/reference.c b/reference.c
index 2f1ffc8..40b7482 100644
--- a/reference.c
+++ b/reference.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2009-2017
+ * Copyright (C) Miroslav Lichvar 2009-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/samplefilt.c b/samplefilt.c
index 7226963..2b737e9 100644
--- a/samplefilt.c
+++ b/samplefilt.c
@@ -75,7 +75,7 @@ SPF_CreateInstance(int min_samples, int max_samples, double max_dispersion, doub
filter->last = -1;
/* Set the first estimate to the system precision */
filter->avg_var_n = 0;
- filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
+ filter->avg_var = SQUARE(LCL_GetSysPrecisionAsQuantum());
filter->max_var = SQUARE(max_dispersion);
filter->combine_ratio = combine_ratio;
filter->samples = MallocArray(NTP_Sample, filter->max_samples);
diff --git a/sources.c b/sources.c
index 47d6638..9ca937e 100644
--- a/sources.c
+++ b/sources.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2011-2016
+ * Copyright (C) Miroslav Lichvar 2011-2016, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/sourcestats.c b/sourcestats.c
index 7150f6e..2c49272 100644
--- a/sourcestats.c
+++ b/sourcestats.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2011-2014, 2016-2017
+ * Copyright (C) Miroslav Lichvar 2011-2014, 2016-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/sys.c b/sys.c
index 4d68b37..f3797c4 100644
--- a/sys.c
+++ b/sys.c
@@ -35,10 +35,13 @@
#if defined(LINUX)
#include "sys_linux.h"
+#include "sys_posix.h"
#elif defined(SOLARIS)
#include "sys_solaris.h"
+#include "sys_posix.h"
#elif defined(NETBSD) || defined(FREEBSD)
#include "sys_netbsd.h"
+#include "sys_posix.h"
#elif defined(MACOSX)
#include "sys_macosx.h"
#endif
@@ -124,10 +127,10 @@ void SYS_EnableSystemCallFilter(int level)
void SYS_SetScheduler(int SchedPriority)
{
-#if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
- SYS_Linux_SetScheduler(SchedPriority);
-#elif defined(MACOSX)
+#if defined(MACOSX)
SYS_MacOSX_SetScheduler(SchedPriority);
+#elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
+ SYS_Posix_SetScheduler(SchedPriority);
#else
LOG_FATAL("scheduler priority setting not supported");
#endif
@@ -137,8 +140,8 @@ void SYS_SetScheduler(int SchedPriority)
void SYS_LockMemory(void)
{
-#if defined(LINUX) && defined(HAVE_MLOCKALL)
- SYS_Linux_MemLockAll(1);
+#if defined(HAVE_MLOCKALL)
+ SYS_Posix_MemLockAll();
#else
LOG_FATAL("memory locking not supported");
#endif
diff --git a/sys_linux.c b/sys_linux.c
index b829022..898dc7a 100644
--- a/sys_linux.c
+++ b/sys_linux.c
@@ -4,7 +4,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
- * Copyright (C) Miroslav Lichvar 2009-2012, 2014-2017
+ * Copyright (C) Miroslav Lichvar 2009-2012, 2014-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -33,15 +33,6 @@
#include <sys/utsname.h>
-#if defined(HAVE_SCHED_SETSCHEDULER)
-# include <sched.h>
-#endif
-
-#if defined(HAVE_MLOCKALL)
-# include <sys/mman.h>
-#include <sys/resource.h>
-#endif
-
#if defined(FEAT_PHC) || defined(HAVE_LINUX_TIMESTAMPING)
#include <linux/ptp_clock.h>
#endif
@@ -493,25 +484,27 @@ SYS_Linux_EnableSystemCallFilter(int level)
SCMP_SYS(clone), SCMP_SYS(exit), SCMP_SYS(exit_group), SCMP_SYS(getpid),
SCMP_SYS(getrlimit), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigreturn),
SCMP_SYS(rt_sigprocmask), SCMP_SYS(set_tid_address), SCMP_SYS(sigreturn),
- SCMP_SYS(wait4),
+ SCMP_SYS(wait4), SCMP_SYS(waitpid),
/* Memory */
SCMP_SYS(brk), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2),
SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(shmdt),
/* Filesystem */
- SCMP_SYS(access), SCMP_SYS(chmod), SCMP_SYS(chown), SCMP_SYS(chown32),
+ SCMP_SYS(_llseek), SCMP_SYS(access), SCMP_SYS(chmod), SCMP_SYS(chown),
+ SCMP_SYS(chown32), SCMP_SYS(faccessat), SCMP_SYS(fchmodat), SCMP_SYS(fchownat),
SCMP_SYS(fstat), SCMP_SYS(fstat64), SCMP_SYS(getdents), SCMP_SYS(getdents64),
- SCMP_SYS(lseek), SCMP_SYS(rename), SCMP_SYS(stat), SCMP_SYS(stat64),
- SCMP_SYS(statfs), SCMP_SYS(statfs64), SCMP_SYS(unlink),
+ SCMP_SYS(lseek), SCMP_SYS(newfstatat), SCMP_SYS(rename), SCMP_SYS(renameat),
+ SCMP_SYS(stat), SCMP_SYS(stat64), SCMP_SYS(statfs), SCMP_SYS(statfs64),
+ SCMP_SYS(unlink), SCMP_SYS(unlinkat),
/* Socket */
SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
- SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
- SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
+ SCMP_SYS(recv), SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
+ SCMP_SYS(send), SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
/* TODO: check socketcall arguments */
SCMP_SYS(socketcall),
/* General I/O */
SCMP_SYS(_newselect), SCMP_SYS(close), SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(pipe),
- SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(futex), SCMP_SYS(select),
- SCMP_SYS(set_robust_list), SCMP_SYS(write),
+ SCMP_SYS(pipe2), SCMP_SYS(poll), SCMP_SYS(ppoll), SCMP_SYS(pselect6), SCMP_SYS(read),
+ SCMP_SYS(futex), SCMP_SYS(select), SCMP_SYS(set_robust_list), SCMP_SYS(write),
/* Miscellaneous */
SCMP_SYS(getrandom), SCMP_SYS(sysinfo), SCMP_SYS(uname),
};
@@ -544,6 +537,9 @@ SYS_Linux_EnableSystemCallFilter(int level)
#ifdef PTP_PIN_SETFUNC
PTP_PIN_SETFUNC,
#endif
+#ifdef PTP_SYS_OFFSET_EXTENDED
+ PTP_SYS_OFFSET_EXTENDED,
+#endif
#ifdef PTP_SYS_OFFSET_PRECISE
PTP_SYS_OFFSET_PRECISE,
#endif
@@ -627,63 +623,6 @@ add_failed:
/* ================================================== */
-#if defined(HAVE_SCHED_SETSCHEDULER)
- /* Install SCHED_FIFO real-time scheduler with specified priority */
-void SYS_Linux_SetScheduler(int SchedPriority)
-{
- int pmax, pmin;
- struct sched_param sched;
-
- if (SchedPriority < 1 || SchedPriority > 99) {
- LOG_FATAL("Bad scheduler priority: %d", SchedPriority);
- } else {
- sched.sched_priority = SchedPriority;
- pmax = sched_get_priority_max(SCHED_FIFO);
- pmin = sched_get_priority_min(SCHED_FIFO);
- if ( SchedPriority > pmax ) {
- sched.sched_priority = pmax;
- }
- else if ( SchedPriority < pmin ) {
- sched.sched_priority = pmin;
- }
- if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) {
- LOG(LOGS_ERR, "sched_setscheduler() failed");
- }
- else {
- DEBUG_LOG("Enabled SCHED_FIFO with priority %d",
- sched.sched_priority);
- }
- }
-}
-#endif /* HAVE_SCHED_SETSCHEDULER */
-
-#if defined(HAVE_MLOCKALL)
-/* Lock the process into RAM so that it will never be swapped out */
-void SYS_Linux_MemLockAll(int LockAll)
-{
- struct rlimit rlim;
- if (LockAll == 1 ) {
- /* Make sure that we will be able to lock all the memory we need */
- /* even after dropping privileges. This does not actually reaerve any memory */
- rlim.rlim_max = RLIM_INFINITY;
- rlim.rlim_cur = RLIM_INFINITY;
- if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
- LOG(LOGS_ERR, "setrlimit() failed: not locking into RAM");
- }
- else {
- if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
- LOG(LOGS_ERR, "mlockall() failed");
- }
- else {
- DEBUG_LOG("Successfully locked into RAM");
- }
- }
- }
-}
-#endif /* HAVE_MLOCKALL */
-
-/* ================================================== */
-
int
SYS_Linux_CheckKernelVersion(int req_major, int req_minor)
{
@@ -701,35 +640,17 @@ SYS_Linux_CheckKernelVersion(int req_major, int req_minor)
#define PHC_READINGS 10
static int
-get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
- struct timespec *sys_ts, double *err)
+process_phc_readings(struct timespec ts[][3], int n, double precision,
+ struct timespec *phc_ts, struct timespec *sys_ts, double *err)
{
- struct ptp_sys_offset sys_off;
- struct timespec ts1, ts2, ts3, phc_tss[PHC_READINGS], sys_tss[PHC_READINGS];
- double min_delay = 0.0, delays[PHC_READINGS], phc_sum, sys_sum, sys_prec;
- int i, n;
+ double min_delay = 0.0, delays[PTP_MAX_SAMPLES], phc_sum, sys_sum, sys_prec;
+ int i, combined;
- /* Silence valgrind */
- memset(&sys_off, 0, sizeof (sys_off));
-
- sys_off.n_samples = PHC_READINGS;
-
- if (ioctl(phc_fd, PTP_SYS_OFFSET, &sys_off)) {
- DEBUG_LOG("ioctl(%s) failed : %s", "PTP_SYS_OFFSET", strerror(errno));
+ if (n > PTP_MAX_SAMPLES)
return 0;
- }
- for (i = 0; i < PHC_READINGS; i++) {
- ts1.tv_sec = sys_off.ts[i * 2].sec;
- ts1.tv_nsec = sys_off.ts[i * 2].nsec;
- ts2.tv_sec = sys_off.ts[i * 2 + 1].sec;
- ts2.tv_nsec = sys_off.ts[i * 2 + 1].nsec;
- ts3.tv_sec = sys_off.ts[i * 2 + 2].sec;
- ts3.tv_nsec = sys_off.ts[i * 2 + 2].nsec;
-
- sys_tss[i] = ts1;
- phc_tss[i] = ts2;
- delays[i] = UTI_DiffTimespecsToDouble(&ts3, &ts1);
+ for (i = 0; i < n; i++) {
+ delays[i] = UTI_DiffTimespecsToDouble(&ts[i][2], &ts[i][0]);
if (delays[i] < 0.0) {
/* Step in the middle of a PHC reading? */
@@ -744,23 +665,92 @@ get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
sys_prec = LCL_GetSysPrecisionAsQuantum();
/* Combine best readings */
- for (i = n = 0, phc_sum = sys_sum = 0.0; i < PHC_READINGS; i++) {
+ for (i = combined = 0, phc_sum = sys_sum = 0.0; i < n; i++) {
if (delays[i] > min_delay + MAX(sys_prec, precision))
continue;
- phc_sum += UTI_DiffTimespecsToDouble(&phc_tss[i], &phc_tss[0]);
- sys_sum += UTI_DiffTimespecsToDouble(&sys_tss[i], &sys_tss[0]) + delays[i] / 2.0;
- n++;
+ phc_sum += UTI_DiffTimespecsToDouble(&ts[i][1], &ts[0][1]);
+ sys_sum += UTI_DiffTimespecsToDouble(&ts[i][0], &ts[0][0]) + delays[i] / 2.0;
+ combined++;
}
- assert(n);
+ assert(combined);
- UTI_AddDoubleToTimespec(&phc_tss[0], phc_sum / n, phc_ts);
- UTI_AddDoubleToTimespec(&sys_tss[0], sys_sum / n, sys_ts);
+ UTI_AddDoubleToTimespec(&ts[0][1], phc_sum / combined, phc_ts);
+ UTI_AddDoubleToTimespec(&ts[0][0], sys_sum / combined, sys_ts);
*err = MAX(min_delay / 2.0, precision);
return 1;
}
+
+/* ================================================== */
+
+static int
+get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
+ struct timespec *sys_ts, double *err)
+{
+ struct timespec ts[PHC_READINGS][3];
+ struct ptp_sys_offset sys_off;
+ int i;
+
+ /* Silence valgrind */
+ memset(&sys_off, 0, sizeof (sys_off));
+
+ sys_off.n_samples = PHC_READINGS;
+
+ if (ioctl(phc_fd, PTP_SYS_OFFSET, &sys_off)) {
+ DEBUG_LOG("ioctl(%s) failed : %s", "PTP_SYS_OFFSET", strerror(errno));
+ return 0;
+ }
+
+ for (i = 0; i < PHC_READINGS; i++) {
+ ts[i][0].tv_sec = sys_off.ts[i * 2].sec;
+ ts[i][0].tv_nsec = sys_off.ts[i * 2].nsec;
+ ts[i][1].tv_sec = sys_off.ts[i * 2 + 1].sec;
+ ts[i][1].tv_nsec = sys_off.ts[i * 2 + 1].nsec;
+ ts[i][2].tv_sec = sys_off.ts[i * 2 + 2].sec;
+ ts[i][2].tv_nsec = sys_off.ts[i * 2 + 2].nsec;
+ }
+
+ return process_phc_readings(ts, PHC_READINGS, precision, phc_ts, sys_ts, err);
+}
+
+/* ================================================== */
+
+static int
+get_extended_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
+ struct timespec *sys_ts, double *err)
+{
+#ifdef PTP_SYS_OFFSET_EXTENDED
+ struct timespec ts[PHC_READINGS][3];
+ struct ptp_sys_offset_extended sys_off;
+ int i;
+
+ /* Silence valgrind */
+ memset(&sys_off, 0, sizeof (sys_off));
+
+ sys_off.n_samples = PHC_READINGS;
+
+ if (ioctl(phc_fd, PTP_SYS_OFFSET_EXTENDED, &sys_off)) {
+ DEBUG_LOG("ioctl(%s) failed : %s", "PTP_SYS_OFFSET_EXTENDED", strerror(errno));
+ return 0;
+ }
+
+ for (i = 0; i < PHC_READINGS; i++) {
+ ts[i][0].tv_sec = sys_off.ts[i][0].sec;
+ ts[i][0].tv_nsec = sys_off.ts[i][0].nsec;
+ ts[i][1].tv_sec = sys_off.ts[i][1].sec;
+ ts[i][1].tv_nsec = sys_off.ts[i][1].nsec;
+ ts[i][2].tv_sec = sys_off.ts[i][2].sec;
+ ts[i][2].tv_nsec = sys_off.ts[i][2].nsec;
+ }
+
+ return process_phc_readings(ts, PHC_READINGS, precision, phc_ts, sys_ts, err);
+#else
+ return 0;
+#endif
+}
+
/* ================================================== */
static int
@@ -834,6 +824,10 @@ SYS_Linux_GetPHCSample(int fd, int nocrossts, double precision, int *reading_mod
get_precise_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
*reading_mode = 2;
return 1;
+ } else if ((*reading_mode == 3 || !*reading_mode) &&
+ get_extended_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
+ *reading_mode = 3;
+ return 1;
} else if ((*reading_mode == 1 || !*reading_mode) &&
get_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
*reading_mode = 1;
diff --git a/sys_linux.h b/sys_linux.h
index 799ae9a..551a186 100644
--- a/sys_linux.h
+++ b/sys_linux.h
@@ -35,10 +35,6 @@ extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);
extern void SYS_Linux_EnableSystemCallFilter(int level);
-extern void SYS_Linux_MemLockAll(int LockAll);
-
-extern void SYS_Linux_SetScheduler(int SchedPriority);
-
extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
extern int SYS_Linux_OpenPHC(const char *path, int phc_index);
diff --git a/sys_macosx.c b/sys_macosx.c
index 00ce302..807d62e 100644
--- a/sys_macosx.c
+++ b/sys_macosx.c
@@ -49,10 +49,8 @@
#ifdef HAVE_MACOS_SYS_TIMEX
#include <dlfcn.h>
#include "sys_netbsd.h"
-#include "sys_timex.h"
static int have_ntp_adjtime = 0;
-static int have_bad_adjtime = 0;
#endif
/* ================================================== */
@@ -453,45 +451,13 @@ legacy_MacOSX_Finalise(void)
/* ================================================== */
-#ifdef HAVE_MACOS_SYS_TIMEX
-/*
- Test adjtime() to see if Apple have fixed the signed/unsigned bug
-*/
-static int
-test_adjtime()
-{
- struct timeval tv1 = {-1, 0};
- struct timeval tv2 = {0, 0};
- struct timeval tv;
-
- if (PRV_AdjustTime(&tv1, &tv) != 0) {
- return 0;
- }
- if (PRV_AdjustTime(&tv2, &tv) != 0) {
- return 0;
- }
- if (tv.tv_sec < -1 || tv.tv_sec > 1) {
- return 0;
- }
- return 1;
-}
-#endif
-
-/* ================================================== */
-
void
SYS_MacOSX_Initialise(void)
{
#ifdef HAVE_MACOS_SYS_TIMEX
have_ntp_adjtime = (dlsym(RTLD_NEXT, "ntp_adjtime") != NULL);
if (have_ntp_adjtime) {
- have_bad_adjtime = !test_adjtime();
- if (have_bad_adjtime) {
- LOG(LOGS_WARN, "adjtime() is buggy - using timex driver");
- SYS_Timex_Initialise();
- } else {
- SYS_NetBSD_Initialise();
- }
+ SYS_NetBSD_Initialise();
return;
}
#endif
@@ -505,11 +471,7 @@ SYS_MacOSX_Finalise(void)
{
#ifdef HAVE_MACOS_SYS_TIMEX
if (have_ntp_adjtime) {
- if (have_bad_adjtime) {
- SYS_Timex_Finalise();
- } else {
- SYS_NetBSD_Finalise();
- }
+ SYS_NetBSD_Finalise();
return;
}
#endif
diff --git a/sys_posix.c b/sys_posix.c
new file mode 100644
index 0000000..356e86a
--- /dev/null
+++ b/sys_posix.c
@@ -0,0 +1,109 @@
+/*
+ chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Richard P. Curnow 1997-2003
+ * Copyright (C) John G. Hasler 2009
+ * Copyright (C) Miroslav Lichvar 2009-2012, 2014-2018
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ **********************************************************************
+
+ =======================================================================
+
+ This module is for POSIX compliant operating systems.
+
+ */
+
+#include "config.h"
+
+#include "sysincl.h"
+
+#include <sys/utsname.h>
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
+#include <pthread.h>
+#include <sched.h>
+#endif
+
+#if defined(HAVE_MLOCKALL)
+#include <sys/mman.h>
+#endif
+#if defined(HAVE_SETRLIMIT_MEMLOCK)
+#include <sys/resource.h>
+#endif
+
+#include "sys_posix.h"
+#include "conf.h"
+#include "local.h"
+#include "logging.h"
+#include "util.h"
+
+/* ================================================== */
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
+/* Install SCHED_FIFO real-time scheduler with specified priority */
+void
+SYS_Posix_SetScheduler(int priority)
+{
+ struct sched_param sched;
+ int pmax, pmin;
+
+ if (priority < 1 || priority > 99)
+ LOG_FATAL("Bad scheduler priority: %d", priority);
+
+ sched.sched_priority = priority;
+ pmax = sched_get_priority_max(SCHED_FIFO);
+ pmin = sched_get_priority_min(SCHED_FIFO);
+ if (priority > pmax) {
+ sched.sched_priority = pmax;
+ } else if (priority < pmin) {
+ sched.sched_priority = pmin;
+ }
+
+ if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched) < 0) {
+ LOG(LOGS_ERR, "pthread_setschedparam() failed");
+ } else {
+ DEBUG_LOG("Enabled SCHED_FIFO with priority %d", sched.sched_priority);
+ }
+}
+#endif /* HAVE_PTHREAD_SETSCHEDPARAM */
+
+/* ================================================== */
+
+#if defined(HAVE_MLOCKALL)
+/* Lock the process into RAM so that it will never be swapped out */
+void
+SYS_Posix_MemLockAll(void)
+{
+#if defined(HAVE_SETRLIMIT_MEMLOCK)
+ struct rlimit rlim;
+
+ /* Ensure we can reserve as much as we need */
+ rlim.rlim_max = RLIM_INFINITY;
+ rlim.rlim_cur = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
+ LOG(LOGS_ERR, "setrlimit() failed");
+ return;
+ }
+#endif
+
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
+ LOG(LOGS_ERR, "mlockall() failed");
+ } else {
+ DEBUG_LOG("Successfully locked into RAM");
+ }
+}
+#endif /* HAVE_MLOCKALL */
diff --git a/sys_posix.h b/sys_posix.h
new file mode 100644
index 0000000..bb34b80
--- /dev/null
+++ b/sys_posix.h
@@ -0,0 +1,36 @@
+/*
+ chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Richard P. Curnow 1997-2003
+ * Copyright (C) John G. Hasler 2009
+ * Copyright (C) Miroslav Lichvar 2009-2012, 2014-2018
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ **********************************************************************
+
+ =======================================================================
+
+ The header file for shared Posix functionality
+ */
+
+#ifndef GOT_SYS_POSIX_H
+#define GOT_SYS_POSIX_H
+
+extern void SYS_Posix_MemLockAll(void);
+
+extern void SYS_Posix_SetScheduler(int priority);
+
+#endif /* GOT_SYS_POSIX_H */
diff --git a/sysincl.h b/sysincl.h
index 54431de..296c5e6 100644
--- a/sysincl.h
+++ b/sysincl.h
@@ -38,10 +38,8 @@
#include <grp.h>
#include <inttypes.h>
#include <math.h>
-#include <netdb.h>
#include <netinet/in.h>
#include <pwd.h>
-#include <resolv.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
diff --git a/test/simulation/008-ntpera b/test/simulation/008-ntpera
index 3c63419..360a97d 100755
--- a/test/simulation/008-ntpera
+++ b/test/simulation/008-ntpera
@@ -16,7 +16,7 @@ check_packet_interval || test_fail
check_sync || test_fail
# The following tests need 64-bit time_t
-grep -q 'HAVE_LONG_TIME_T 1' ../../config.h || test_skip
+check_config_h 'HAVE_LONG_TIME_T 1' || test_skip
for year in 1990 2090; do
export CLKNETSIM_START_DATE=$(date -d "Jan 1 00:00:00 UTC $year" +'%s')
diff --git a/test/simulation/012-daemonts b/test/simulation/012-daemonts
new file mode 100755
index 0000000..b883516
--- /dev/null
+++ b/test/simulation/012-daemonts
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. ./test.common
+
+test_start "daemon timestamping"
+
+export CLKNETSIM_TIMESTAMPING=0
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_source_selection || test_fail
+check_packet_interval || test_fail
+check_sync || test_fail
+
+test_pass
diff --git a/test/simulation/105-ntpauth b/test/simulation/105-ntpauth
index 4c77f10..9ec4fba 100755
--- a/test/simulation/105-ntpauth
+++ b/test/simulation/105-ntpauth
@@ -23,7 +23,7 @@ EOF
keys=4
-if grep -q 'FEAT_SECHASH 1' ../../config.h; then
+if check_config_h 'FEAT_SECHASH 1'; then
hashes="MD5 SHA1 SHA256 SHA384 SHA512"
else
hashes="MD5"
diff --git a/test/simulation/106-refclock b/test/simulation/106-refclock
index 5c5794c..c4cec20 100755
--- a/test/simulation/106-refclock
+++ b/test/simulation/106-refclock
@@ -3,6 +3,10 @@
. ./test.common
test_start "SHM refclock"
+check_config_h 'FEAT_REFCLOCK 1' || test_skip
+check_config_h 'FEAT_PHC 1' || test_skip
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
servers=0
limit=1000
refclock_jitter=$jitter
diff --git a/test/simulation/107-allowdeny b/test/simulation/107-allowdeny
index b11db32..3ab83ff 100755
--- a/test/simulation/107-allowdeny
+++ b/test/simulation/107-allowdeny
@@ -4,6 +4,8 @@
test_start "allow/deny directives"
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
limit=500
# Note that start_client in clknetsim.bash always adds allow to the config
diff --git a/test/simulation/110-chronyc b/test/simulation/110-chronyc
index 944cf3f..5736ae4 100755
--- a/test/simulation/110-chronyc
+++ b/test/simulation/110-chronyc
@@ -4,6 +4,9 @@
test_start "chronyc"
+check_config_h 'FEAT_REFCLOCK 1' || test_skip
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
refclock_jitter=$jitter
client_conf="
refclock SHM 0 noselect
@@ -95,6 +98,8 @@ for chronyc_conf in \
"delete 10.0.0.0" \
"deny 1.2.3.4" \
"deny all 1.2.3.0/24" \
+ "dfreq 1.0e-3" \
+ "doffset -1.0" \
"dump" \
"local stratum 5 distance 1.0 orphan" \
"local off" \
@@ -126,6 +131,7 @@ for chronyc_conf in \
"settime 16:30" \
"settime 16:30:05" \
"settime Nov 21, 2015 16:30:05" \
+ "serverstats" \
"shutdown" \
"smoothtime reset" \
"smoothtime activate" \
@@ -137,4 +143,24 @@ do
check_chronyc_output "501 Not authorised" || test_fail
done
+chronyc_conf="dns -n
+dns +n
+dns -4
+dns -6
+dns -46
+timeout 200
+retries 1
+keygen
+keygen 10 MD5 128
+help
+quit
+nosuchcommand"
+
+run_test || test_fail
+
+check_chronyc_output "^1 (MD5|SHA1) HEX:........................................
+10 MD5 HEX:................................
+System clock:.*this help
+ *$" || test_fail
+
test_pass
diff --git a/test/simulation/112-port b/test/simulation/112-port
index e983757..a8efabd 100755
--- a/test/simulation/112-port
+++ b/test/simulation/112-port
@@ -4,6 +4,8 @@
test_start "port and acquisitionport directives"
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
run_test || test_fail
check_chronyd_exit || test_fail
check_source_selection || test_fail
diff --git a/test/simulation/113-leapsecond b/test/simulation/113-leapsecond
index 5b9758f..2fb81b8 100755
--- a/test/simulation/113-leapsecond
+++ b/test/simulation/113-leapsecond
@@ -1,8 +1,11 @@
#!/bin/bash
. ./test.common
+
test_start "leap second"
+check_config_h 'FEAT_REFCLOCK 1' || test_skip
+
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s')
leap=$[2 * 24 * 3600]
diff --git a/test/simulation/115-cmdmontime b/test/simulation/115-cmdmontime
index 2806a1f..732decd 100755
--- a/test/simulation/115-cmdmontime
+++ b/test/simulation/115-cmdmontime
@@ -5,7 +5,8 @@
test_start "cmdmon timestamps"
# The following tests need 64-bit time_t
-grep -q 'HAVE_LONG_TIME_T 1' ../../config.h || test_skip
+check_config_h 'HAVE_LONG_TIME_T 1' || test_skip
+check_config_h 'FEAT_CMDMON 1' || test_skip
limit=2
client_server_options="noselect"
diff --git a/test/simulation/119-smoothtime b/test/simulation/119-smoothtime
index 6b4ae39..3f90715 100755
--- a/test/simulation/119-smoothtime
+++ b/test/simulation/119-smoothtime
@@ -1,8 +1,11 @@
#!/bin/bash
. ./test.common
+
test_start "smoothtime option"
+check_config_h 'FEAT_REFCLOCK 1' || test_skip
+
server_strata=2
server_conf="smoothtime 400 0.001"
server_server_options="minpoll 8"
diff --git a/test/simulation/121-orphan b/test/simulation/121-orphan
index 1b47f76..bbebc9d 100755
--- a/test/simulation/121-orphan
+++ b/test/simulation/121-orphan
@@ -4,6 +4,8 @@
test_start "orphan option"
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
server_strata=3
server_conf="local stratum 5 orphan
server 192.168.123.1
diff --git a/test/simulation/124-tai b/test/simulation/124-tai
index b5be030..d41d29d 100755
--- a/test/simulation/124-tai
+++ b/test/simulation/124-tai
@@ -1,8 +1,11 @@
#!/bin/bash
. ./test.common
+
test_start "tai option"
+check_config_h 'FEAT_REFCLOCK 1' || test_skip
+
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 31 2008 23:50:00' +'%s')
leap=$[10 * 60]
diff --git a/test/simulation/128-nocontrol b/test/simulation/128-nocontrol
index 0a98cd7..cca82f4 100755
--- a/test/simulation/128-nocontrol
+++ b/test/simulation/128-nocontrol
@@ -4,6 +4,8 @@
test_start "-x option"
+check_config_h 'FEAT_CMDMON 1' || test_skip
+
wander=0.0
time_offset=0.0
freq_offset=0.0
diff --git a/test/simulation/129-reload b/test/simulation/129-reload
index 9c4e985..7a346a4 100755
--- a/test/simulation/129-reload
+++ b/test/simulation/129-reload
@@ -9,7 +9,8 @@ limit=100
min_sync_time=100
max_sync_time=104
client_chronyd_options="-r"
-client_conf="dumpdir tmp"
+client_conf="dumpdir tmp
+maxupdateskew 10000"
run_test || test_fail
diff --git a/test/simulation/133-hwtimestamp b/test/simulation/133-hwtimestamp
index 1448c21..113ea69 100755
--- a/test/simulation/133-hwtimestamp
+++ b/test/simulation/133-hwtimestamp
@@ -4,6 +4,8 @@
test_start "hwtimestamp directive"
+check_config_h 'HAVE_LINUX_TIMESTAMPING 1' || test_skip
+
export CLKNETSIM_TIMESTAMPING=2
refclock_jitter=1e-8
@@ -20,7 +22,7 @@ check_chronyd_exit || test_fail
check_source_selection || test_fail
check_sync || test_fail
-if grep -q 'FEAT_DEBUG 1' ../../config.h; then
+if check_config_h 'FEAT_DEBUG 1'; then
check_log_messages "HW clock samples" 190 200 || test_fail
check_log_messages "HW clock reset" 0 0 || test_fail
check_log_messages "Received.*tss=1" 1 1 || test_fail
diff --git a/test/simulation/134-log b/test/simulation/134-log
new file mode 100755
index 0000000..0a6ef76
--- /dev/null
+++ b/test/simulation/134-log
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+. ./test.common
+
+test_start "log directive"
+
+check_config_h 'FEAT_PHC 1' || test_skip
+
+refclock_jitter=$jitter
+client_server_options="maxpoll 6"
+client_conf="refclock PHC /dev/ptp0 dpoll 4 poll 6 noselect
+logbanner 10
+logdir tmp
+log tracking rawmeasurements measurements statistics rtc refclocks tempcomp
+tempcomp tmp/tempcomp 64 0.0 0.0 0.0 0.0"
+
+echo 0.0 > tmp/tempcomp
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_source_selection || test_fail
+check_packet_interval || test_fail
+check_sync || test_fail
+
+check_file_messages "=============" 31 33 \
+ tracking.log measurements.log tempcomp.log || test_fail
+check_file_messages "20.*192\.168\.123\.1" 150 160 \
+ tracking.log measurements.log statistics.log || test_fail
+check_file_messages "20.*PHC0" 150 160 statistics.log || test_fail
+check_file_messages "20.*PHC0" 750 800 refclocks.log || test_fail
+check_file_messages "20.* 0\.0000" 150 160 tempcomp.log || test_fail
+
+test_pass
diff --git a/test/simulation/135-ratelimit b/test/simulation/135-ratelimit
new file mode 100755
index 0000000..cfa5eab
--- /dev/null
+++ b/test/simulation/135-ratelimit
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+. ./test.common
+test_start "ratelimit directive"
+
+server_conf="ratelimit interval 6 burst 2 leak 4"
+client_server_options="minpoll 3 maxpoll 3"
+min_sync_time=16
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_packet_interval || test_fail
+check_sync || test_fail
+
+check_file_messages " 2 1 " 1200 1300 log.packets || test_fail
+check_file_messages " 1 2 " 180 220 log.packets || test_fail
+
+test_pass
diff --git a/test/simulation/136-broadcast b/test/simulation/136-broadcast
new file mode 100755
index 0000000..d60d678
--- /dev/null
+++ b/test/simulation/136-broadcast
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. ./test.common
+
+test_start "broadcast directive"
+
+server_conf="broadcast 64 192.168.123.255"
+client_server_options="offline"
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_packet_interval && test_fail
+
+check_file_messages " 1 2 " 150 160 log.packets || test_fail
+
+test_pass
diff --git a/test/simulation/test.common b/test/simulation/test.common
index c5758c6..951a794 100644
--- a/test/simulation/test.common
+++ b/test/simulation/test.common
@@ -84,6 +84,8 @@ done
test_start() {
rm -f tmp/*
echo "Testing $@:"
+
+ check_config_h 'FEAT_NTP 1' || test_skip
}
test_pass() {
@@ -211,6 +213,12 @@ get_chronyd_conf() {
fi
}
+# Check if chrony was built with specified option in config.h
+check_config_h() {
+ local pattern=$1
+ grep -q "^#define $pattern" ../../config.h
+}
+
# Check if the clock was well synchronized
check_sync() {
local i sync_time max_time_error max_freq_error ret=0
@@ -337,7 +345,7 @@ check_chronyc_output() {
return $ret
}
-# Check the number of messages matching a matter in the client logs
+# Check the number of messages matching a pattern in the client logs
check_log_messages() {
local i count ret=0 pattern=$1 min=$2 max=$3
@@ -355,6 +363,25 @@ check_log_messages() {
return $ret
}
+# Check the number of messages matching a pattern in a specified file
+check_file_messages() {
+ local i count ret=0 pattern=$1 min=$2 max=$3
+ shift 3
+
+ test_message 2 1 "checking number of messages \"$pattern\":"
+
+ for i; do
+ count=$(grep "$pattern" tmp/$i | wc -l)
+ test_message 3 0 "$i: $count"
+
+ [ "$min" -le "$count" ] && [ "$count" -le "$max" ] && \
+ test_ok || test_bad
+ [ $? -eq 0 ] || ret=1
+ done
+
+ return $ret
+}
+
# Check if only NTP port (123) was used
check_packet_port() {
local i ret=0 port=123
diff --git a/test/system/001-minimal b/test/system/001-minimal
new file mode 100755
index 0000000..107fa3f
--- /dev/null
+++ b/test/system/001-minimal
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "minimal configuration"
+
+minimal_config=1
+
+start_chronyd || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+
+test_pass
diff --git a/test/system/002-extended b/test/system/002-extended
new file mode 100755
index 0000000..7a6734f
--- /dev/null
+++ b/test/system/002-extended
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "extended configuration"
+
+start_chronyd || test_fail
+wait_for_sync || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_files || test_fail
+
+test_pass
diff --git a/test/system/003-memlock b/test/system/003-memlock
new file mode 100755
index 0000000..e4ab1bf
--- /dev/null
+++ b/test/system/003-memlock
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "memory locking"
+
+extra_chronyd_options="-m"
+
+start_chronyd || test_fail
+wait_for_sync || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_files || test_fail
+
+test_pass
diff --git a/test/system/004-priority b/test/system/004-priority
new file mode 100755
index 0000000..bf8a04b
--- /dev/null
+++ b/test/system/004-priority
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "process priority"
+
+extra_chronyd_options="-P 1"
+
+start_chronyd || test_fail
+wait_for_sync || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_files || test_fail
+
+test_pass
diff --git a/test/system/005-scfilter b/test/system/005-scfilter
new file mode 100755
index 0000000..778a688
--- /dev/null
+++ b/test/system/005-scfilter
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+check_chronyd_features SCFILTER || test_skip "SCFILTER support disabled"
+
+test_start "system call filter"
+
+for extra_chronyd_options in "-F -1" "-F 1"; do
+ start_chronyd || test_fail
+ wait_for_sync || test_fail
+ stop_chronyd || test_fail
+ check_chronyd_messages || test_fail
+ check_chronyd_files || test_fail
+done
+
+test_pass
diff --git a/test/system/006-privdrop b/test/system/006-privdrop
new file mode 100755
index 0000000..6d7b0c9
--- /dev/null
+++ b/test/system/006-privdrop
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+check_chronyd_features PRIVDROP || test_skip "PRIVDROP support disabled"
+
+user="nobody"
+
+test_start "dropping of root privileges"
+
+minimal_config=1
+
+start_chronyd || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+
+test_pass
diff --git a/test/system/007-cmdmon b/test/system/007-cmdmon
new file mode 100755
index 0000000..f705fb0
--- /dev/null
+++ b/test/system/007-cmdmon
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "chronyc commands"
+
+start_chronyd || test_fail
+
+for command in \
+ "accheck 1.2.3.4" \
+ "delete $server" \
+ "add server $server" \
+ "deny" \
+ "allow" \
+ "burst 1/1" \
+ "clients" \
+ "cmdallow 1.2.3.4" \
+ "cmdaccheck 1.2.3.4" \
+ "cmddeny 1.2.3.4" \
+ "cyclelogs" \
+ "dfreq 1.0e-3" \
+ "doffset -0.1" \
+ "dump" \
+ "local off" \
+ "local" \
+ "manual on" \
+ "settime now" \
+ "manual delete 0" \
+ "settime now" \
+ "manual reset" \
+ "manual off" \
+ "maxdelay $server 1e-2" \
+ "maxdelaydevratio $server 5.0" \
+ "maxdelayratio $server 3.0" \
+ "maxpoll $server 5" \
+ "maxupdateskew $server 10.0" \
+ "minpoll $server 3" \
+ "minstratum $server 1" \
+ "ntpdata $server" \
+ "offline" \
+ "online" \
+ "onoffline" \
+ "polltarget $server 10" \
+ "refresh" \
+ "rekey" \
+ "reselect" \
+ "reselectdist 1e-3" \
+ "serverstats" \
+ "smoothtime reset" \
+ "smoothtime activate" \
+ "shutdown" \
+; do
+ run_chronyc "$command" || test_fail
+done
+
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+start_chronyd || test_fail
+
+run_chronyc "makestep" && test_fail
+check_chronyc_output "500 Failure" || test_fail
+run_chronyc "trimrtc" && test_fail
+check_chronyc_output "513 RTC driver not running" || test_fail
+run_chronyc "writertc" && test_fail
+check_chronyc_output "513 RTC driver not running" || test_fail
+
+stop_chronyd || test_fail
+
+test_pass
diff --git a/test/system/100-clockupdate b/test/system/100-clockupdate
new file mode 100755
index 0000000..191e461
--- /dev/null
+++ b/test/system/100-clockupdate
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+test_start "update of system clock"
+
+clock_control=1
+minimal_config=1
+
+start_chronyd || test_fail
+run_chronyc "dfreq 1e-3" || test_fail
+check_chronyc_output "200 OK" || test_fail
+
+before=$(date '+%s')
+run_chronyc "doffset -1.0" || test_fail
+check_chronyc_output "200 OK" || test_fail
+run_chronyc "makestep" || test_fail
+check_chronyc_output "200 OK" || test_fail
+after=$(date '+%s')
+
+test_message 1 0 "checking system clock"
+[ "$before" -lt "$after" ] && test_ok || test_bad || test_fail
+
+run_chronyc "doffset 1.0" || test_fail
+run_chronyc "makestep" || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_message_count "System clock was stepped by" 2 2 || test_fail
+
+test_pass
diff --git a/test/system/101-rtc b/test/system/101-rtc
new file mode 100755
index 0000000..fa9a70d
--- /dev/null
+++ b/test/system/101-rtc
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+check_chronyd_features RTC || test_skip "RTC support disabled"
+[ -c "/dev/rtc" ] || test_skip "missing /dev/rtc"
+
+test_start "real-time clock"
+
+minimal_config=1
+extra_chronyd_options="-s"
+extra_chronyd_directives="rtcfile $TEST_DIR/rtcfile"
+echo "1 $(date +%s) 0.0 0.0" > "$TEST_DIR/rtcfile"
+
+start_chronyd || test_fail
+stop_chronyd || test_fail
+check_chronyd_message_count "\(clock off from RTC\|RTC time before last\)" 1 1 || test_fail
+
+test_pass
diff --git a/test/system/102-hwtimestamp b/test/system/102-hwtimestamp
new file mode 100755
index 0000000..86f2287
--- /dev/null
+++ b/test/system/102-hwtimestamp
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+[ "$(uname -s)" = "Linux" ] || test_skip "non-Linux system"
+
+hwts_iface=""
+for iface_path in /sys/class/net/*; do
+ iface=$(basename "$iface_path")
+ if ethtool -T "$iface" 2> /dev/null | grep -q HWTSTAMP_FILTER_ALL; then
+ hwts_iface="$iface"
+ break
+ fi
+done
+
+[ -n "$hwts_iface" ] || test_skip "no HW timestamping interface found"
+
+test_start "hardware timestamping"
+
+minimal_config=1
+extra_chronyd_directives="hwtimestamp $hwts_iface"
+
+start_chronyd || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_message_count "Enabled HW timestamping on $hwts_iface" 1 1 || test_fail
+
+test_pass
diff --git a/test/system/103-refclock b/test/system/103-refclock
new file mode 100755
index 0000000..e5b74e0
--- /dev/null
+++ b/test/system/103-refclock
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+. ./test.common
+
+check_chronyd_features REFCLOCK || test_skip "refclock support disabled"
+
+test_start "reference clocks"
+
+extra_chronyd_directives="
+refclock SOCK $TEST_DIR/refclock.sock
+refclock SHM 100"
+
+start_chronyd || test_fail
+wait_for_sync || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_files || test_fail
+
+test_pass
diff --git a/test/system/104-systemdirs b/test/system/104-systemdirs
new file mode 100755
index 0000000..15508dc
--- /dev/null
+++ b/test/system/104-systemdirs
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+TEST_LIBDIR=${CHRONY_LIBDIR:-/var/lib/chrony}
+TEST_LOGDIR=${CHRONY_LOGDIR:-/var/log/chrony}
+TEST_RUNDIR=${CHRONY_RUNDIR:-/var/run/chrony}
+
+. ./test.common
+
+user=$(ls -ld "$TEST_RUNDIR" 2> /dev/null | awk '{print $3}')
+
+test_start "system directories"
+
+start_chronyd || test_fail
+wait_for_sync || test_fail
+stop_chronyd || test_fail
+check_chronyd_messages || test_fail
+check_chronyd_files || test_fail
+
+test_pass
diff --git a/test/system/run b/test/system/run
new file mode 100755
index 0000000..5516ed4
--- /dev/null
+++ b/test/system/run
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+
+print_help() {
+ echo "$1 [-a] [-d] [TEST]..."
+}
+
+run_test() {
+ local result name=$1
+
+ if [ $destructive -ne 1 ] && [[ "$name" == 1[0-9][0-9]-* ]]; then
+ echo "SKIP (destructive test)"
+ return 9
+ fi
+
+ ./$name
+ result=$?
+
+ if [ $result -ne 0 -a $result -ne 9 ]; then
+ if [ $abort_on_fail -ne 0 ]; then
+ exit 1
+ fi
+ fi
+
+ return $result
+}
+
+passed=() failed=() skipped=()
+
+abort_on_fail=0
+destructive=0
+
+while getopts ":ad" opt; do
+ case $opt in
+ a) abort_on_fail=1;;
+ d) destructive=1;;
+ *) print_help "$0"; exit 3;;
+ esac
+done
+
+shift $[$OPTIND - 1]
+
+[ $# -gt 0 ] && tests=($@) || tests=([0-9]*-*[^_])
+
+for test in "${tests[@]}"; do
+ printf "%s " "$test"
+ run_test $test
+ result=$?
+ echo
+
+ case $result in
+ 0) passed=(${passed[@]} $test);;
+ 9) skipped=(${skipped[@]} $test);;
+ *) failed=(${failed[@]} $test);;
+ esac
+done
+
+echo
+echo "SUMMARY:"
+echo " TOTAL $[${#passed[@]} + ${#failed[@]} + ${#skipped[@]}]"
+echo " PASSED ${#passed[@]}"
+echo " FAILED ${#failed[@]} (${failed[@]})"
+echo " SKIPPED ${#skipped[@]} (${skipped[@]})"
+
+[ ${#failed[@]} -eq 0 ]
diff --git a/test/system/test.common b/test/system/test.common
new file mode 100644
index 0000000..28c4805
--- /dev/null
+++ b/test/system/test.common
@@ -0,0 +1,339 @@
+# Copyright (C) Miroslav Lichvar 2009
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+export LC_ALL=C
+export PATH=${CHRONY_PATH:-../..}:$PATH
+
+TEST_DIR=${TEST_DIR:-$(pwd)/tmp}
+TEST_LIBDIR=${TEST_LIBDIR:-$TEST_DIR}
+TEST_LOGDIR=${TEST_LOGDIR:-$TEST_DIR}
+TEST_RUNDIR=${TEST_RUNDIR:-$TEST_DIR}
+
+test_start() {
+ check_chronyd_features NTP CMDMON || test_skip "NTP/CMDMON support disabled"
+
+ [ "${#TEST_DIR}" -ge 5 ] || test_skip "invalid TEST_DIR"
+
+ rm -rf "$TEST_DIR"
+ mkdir -p "$TEST_DIR" && chmod 700 "$TEST_DIR" || test_skip "could not create $TEST_DIR"
+
+ [ -d "$TEST_LIBDIR" ] || test_skip "missing $TEST_LIBDIR"
+ [ -d "$TEST_LOGDIR" ] || test_skip "missing $TEST_LOGDIR"
+ [ -d "$TEST_RUNDIR" ] || test_skip "missing $TEST_RUNDIR"
+
+ rm -f "$TEST_LIBDIR"/* "$TEST_LOGDIR"/* "$TEST_RUNDIR"/*
+
+ if [ "$user" != "root" ]; then
+ id -u "$user" > /dev/null 2> /dev/null || test_skip "missing user $user"
+ chown "$user:$(id -g "$user")" "$TEST_DIR" || test_skip "could not chown $TEST_DIR"
+ su "$user" -s /bin/sh -c "touch $TEST_DIR/test" 2> /dev/null || \
+ test_skip "$user cannot access $TEST_DIR"
+ rm "$TEST_DIR/test"
+ fi
+
+ echo "Testing $*:"
+}
+
+test_pass() {
+ echo "PASS"
+ exit 0
+}
+
+test_fail() {
+ echo "FAIL"
+ exit 1
+}
+
+test_skip() {
+ local msg=$1
+
+ [ -n "$msg" ] && echo "SKIP ($msg)" || echo "SKIP"
+ exit 9
+}
+
+test_ok() {
+ pad_line
+ echo -e "\tOK"
+ return 0
+}
+
+test_bad() {
+ pad_line
+ echo -e "\tBAD"
+ return 1
+}
+
+test_error() {
+ pad_line
+ echo -e "\tERROR"
+ return 1
+}
+
+chronyd=$(command -v chronyd)
+chronyc=$(command -v chronyc)
+
+[ $EUID -eq 0 ] || test_skip "not root"
+
+[ -x "$chronyd" ] || test_skip "chronyd not found"
+[ -x "$chronyc" ] || test_skip "chronyc not found"
+
+netstat -aln > /dev/null 2> /dev/null || test_skip "missing netstat"
+
+# Default test testings
+default_minimal_config=0
+default_extra_chronyd_directives=""
+default_extra_chronyd_options=""
+default_clock_control=0
+default_server=127.0.0.1
+default_user=root
+
+# Initialize test settings from their defaults
+for defoptname in ${!default_*}; do
+ optname=${defoptname#default_}
+ [ -z "${!optname}" ] && declare "$optname"="${!defoptname}"
+done
+
+msg_length=0
+pad_line() {
+ local line_length=56
+ [ $msg_length -lt $line_length ] && \
+ printf "%$((line_length - msg_length))s" ""
+ msg_length=0
+}
+
+# Print aligned message
+test_message() {
+ local level=$1 eol=$2
+ shift 2
+ local msg="$*"
+
+ while [ "$level" -gt 0 ]; do
+ echo -n " "
+ level=$((level - 1))
+ msg_length=$((msg_length + 2))
+ done
+ echo -n "$msg"
+
+ msg_length=$((msg_length + ${#msg}))
+ if [ "$eol" -ne 0 ]; then
+ echo
+ msg_length=0
+ fi
+}
+
+# Check if chronyd has specified features
+check_chronyd_features() {
+ local feature features
+
+ features=$($chronyd -v | sed 's/.*(\(.*\)).*/\1/')
+
+ for feature; do
+ echo "$features" | grep -q "+$feature" || return 1
+ done
+}
+
+# Print test settings which differ from default value
+print_nondefaults() {
+ local defoptname optname
+
+ test_message 1 1 "non-default settings:"
+ for defoptname in ${!default_*}; do
+ optname=${defoptname#default_}
+ [ "${!defoptname}" = "${!optname}" ] || \
+ test_message 2 1 "$optname"=${!optname}
+ done
+}
+
+get_conffile() {
+ echo "$TEST_DIR/chronyd.conf"
+}
+
+get_pidfile() {
+ echo "$TEST_RUNDIR/chronyd.pid"
+}
+
+get_logfile() {
+ echo "$TEST_LOGDIR/chronyd.log"
+}
+
+get_cmdsocket() {
+ echo "$TEST_RUNDIR/chronyd.sock"
+}
+
+# Find a free port in the 10000-20000 range (their use is racy)
+get_free_port() {
+ local port
+
+ while true; do
+ port=$((RANDOM % 10000 + 10000))
+ netstat -aln | grep '^udp.*:'$port && continue
+ break
+ done
+
+ echo $port
+}
+
+generate_chrony_conf() {
+ local ntpport cmdport
+
+ ntpport=$(get_free_port)
+ cmdport=$(get_free_port)
+
+ echo "0.0 10000" > "$TEST_LIBDIR/driftfile"
+ echo "1 MD5 abcdefghijklmnopq" > "$TEST_DIR/keys"
+ chown "$user:$(id -g "$user")" "$TEST_LIBDIR/driftfile" "$TEST_DIR/keys"
+ echo "0.0" > "$TEST_DIR/tempcomp"
+
+ (
+ echo "pidfile $(get_pidfile)"
+ echo "bindcmdaddress $(get_cmdsocket)"
+ echo "port $ntpport"
+ echo "cmdport $cmdport"
+
+ echo "$extra_chronyd_directives"
+
+ [ "$minimal_config" -ne 0 ] && exit 0
+
+ echo "allow"
+ echo "cmdallow"
+ echo "local"
+
+ echo "server $server port $ntpport minpoll -6 maxpoll -6"
+
+ [ "$server" = "127.0.0.1" ] && echo "bindacqaddress $server"
+ echo "bindaddress 127.0.0.1"
+ echo "bindcmdaddress 127.0.0.1"
+ echo "dumpdir $TEST_RUNDIR"
+ echo "logdir $TEST_LOGDIR"
+ echo "log tempcomp rawmeasurements refclocks statistics tracking rtc"
+ echo "logbanner 0"
+ echo "smoothtime 100.0 0.001"
+
+ echo "include /dev/null"
+ echo "keyfile $TEST_DIR/keys"
+ echo "driftfile $TEST_LIBDIR/driftfile"
+ echo "tempcomp $TEST_DIR/tempcomp 0.1 0 0 0 0"
+
+ ) > "$(get_conffile)"
+}
+
+get_chronyd_options() {
+ [ "$clock_control" -eq 0 ] && echo "-x"
+ echo "-l $(get_logfile)"
+ echo "-f $(get_conffile)"
+ echo "-u $user"
+ echo "$extra_chronyd_options"
+}
+
+# Start a chronyd instance
+start_chronyd() {
+ local pid pidfile=$(get_pidfile)
+
+ print_nondefaults
+ test_message 1 0 "starting chronyd"
+
+ generate_chrony_conf
+
+ trap stop_chronyd EXIT
+
+ $CHRONYD_WRAPPER "$chronyd" $(get_chronyd_options) > "$TEST_DIR/chronyd.out" 2>&1
+
+ [ $? -eq 0 ] && [ -f "$pidfile" ] && ps -p "$(cat "$pidfile")" > /dev/null && test_ok || test_error
+}
+
+wait_for_sync() {
+ test_message 1 0 "waiting for synchronization"
+ sleep 1 && test_ok || test_error
+}
+
+# Stop the chronyd instance
+stop_chronyd() {
+ local pid pidfile
+
+ pidfile=$(get_pidfile)
+ [ -f "$pidfile" ] || return 0
+
+ pid=$(cat "$pidfile")
+
+ test_message 1 0 "stopping chronyd"
+
+ if ! kill "$pid" 2> /dev/null; then
+ test_error
+ return
+ fi
+
+ # Wait for the process to terminate (we cannot use "wait")
+ while ps -p "$pid" > /dev/null; do
+ sleep 0.1
+ done
+
+ test_ok
+}
+
+# Check chronyd log for expected and unexpected messages
+check_chronyd_messages() {
+ local logfile=$(get_logfile)
+
+ test_message 1 0 "checking chronyd messages"
+
+ grep -q 'chronyd exiting' "$logfile" && \
+ ([ "$clock_control" -eq 0 ] || ! grep -q 'Disabled control of system clock' "$logfile") && \
+ ([ "$clock_control" -ne 0 ] || grep -q 'Disabled control of system clock' "$logfile") && \
+ ([ "$minimal_config" -ne 0 ] || grep -q 'Frequency .* read from' "$logfile") && \
+ grep -q 'chronyd exiting' "$logfile" && \
+ ! grep -q 'Could not' "$logfile" && \
+ ! grep -q 'Disabled command socket' "$logfile" && \
+ test_ok || test_bad
+}
+
+# Check the number of messages matching a pattern in a specified file
+check_chronyd_message_count() {
+ local count pattern=$1 min=$2 max=$3 logfile=$(get_logfile)
+
+ test_message 1 0 "checking message \"$pattern\""
+
+ count=$(grep "$pattern" "$(get_logfile)" | wc -l)
+
+ [ "$min" -le "$count" ] && [ "$count" -le "$max" ] && test_ok || test_bad
+}
+
+# Check the logs and dump file for measurements and a clock update
+check_chronyd_files() {
+ test_message 1 0 "checking chronyd files"
+
+ grep -q " $server .* 111 111 1111 " "$TEST_LOGDIR/measurements.log" && \
+ grep -q " $server " "$TEST_LOGDIR/statistics.log" && \
+ grep -q " $server " "$TEST_LOGDIR/tracking.log" && \
+ [ -f "$TEST_LOGDIR/tempcomp.log" ] && [ "$(wc -l < "$TEST_LOGDIR/tempcomp.log")" -ge 2 ] && \
+ [ -f "$TEST_RUNDIR/$server.dat" ] && [ "$(wc -l < "$TEST_RUNDIR/$server.dat")" -ge 5 ] && \
+ test_ok || test_bad
+}
+
+# Run a chronyc command
+run_chronyc() {
+ test_message 1 0 "running chronyc $*"
+
+ $CHRONYC_WRAPPER "$chronyc" -h "$(get_cmdsocket)" -n -m "$@" > "$TEST_DIR/chronyc.out" && \
+ test_ok || test_error
+}
+
+# Compare chronyc output with specified pattern
+check_chronyc_output() {
+ local pattern=$1
+
+ test_message 1 0 "checking chronyc output"
+
+ [[ "$(cat "$TEST_DIR/chronyc.out")" =~ $pattern ]] && test_ok || test_bad
+}
diff --git a/test/unit/Makefile.in b/test/unit/Makefile.in
index 554663b..e789a1b 100644
--- a/test/unit/Makefile.in
+++ b/test/unit/Makefile.in
@@ -11,13 +11,15 @@ SHARED_OBJS = test.o
TEST_OBJS := $(sort $(patsubst %.c,%.o,$(wildcard *.c)))
TESTS := $(patsubst %.o,%.test,$(filter-out $(SHARED_OBJS),$(TEST_OBJS)))
-FILTER_OBJS = %/main.o %/client.o %/getdate.o
-CHRONY_OBJS := $(filter-out $(FILTER_OBJS),$(wildcard $(CHRONY_SRCDIR)/*.o))
+CHRONYD_OBJS := $(patsubst %.o,$(CHRONY_SRCDIR)/%.o,$(filter-out main.o,\
+ $(filter %.o,$(shell $(MAKE) -f $(CHRONY_SRCDIR)/Makefile print-chronyd-objects))))
all: $(TESTS)
-%.test: %.o $(SHARED_OBJS)
- $(CC) $(CFLAGS) -o $@ $^ $(CHRONY_OBJS:%/$*.o=) $(LDFLAGS)
+$(CHRONYD_OBJS): ;
+
+%.test: %.o $(SHARED_OBJS) $(CHRONYD_OBJS)
+ $(CC) $(CFLAGS) -o $@ $(filter-out $(CHRONY_SRCDIR)/$<,$^) $(LDFLAGS)
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $<
@@ -30,7 +32,7 @@ check: $(TESTS)
exit $$ret
clean:
- rm -f *.o $(TESTS)
+ rm -f *.o *.gcda *.gcno core.* $(TESTS)
rm -rf .deps
distclean: clean
diff --git a/test/unit/hwclock.c b/test/unit/hwclock.c
index 216dbfb..6462c5c 100644
--- a/test/unit/hwclock.c
+++ b/test/unit/hwclock.c
@@ -1,6 +1,6 @@
/*
**********************************************************************
- * Copyright (C) Miroslav Lichvar 2016-2017
+ * Copyright (C) Miroslav Lichvar 2016-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/test/unit/ntp_core.c b/test/unit/ntp_core.c
index 5e519e5..ac01205 100644
--- a/test/unit/ntp_core.c
+++ b/test/unit/ntp_core.c
@@ -28,6 +28,8 @@
#include <local.h>
#include "test.h"
+#ifdef FEAT_NTP
+
static struct timespec current_time;
static NTP_Receive_Buffer req_buffer, res_buffer;
static int req_length, res_length;
@@ -332,10 +334,8 @@ test_unit(void)
CPS_ParseNTPSourceAdd(source_line, &source);
for (i = 0; i < 1000; i++) {
- if (random() % 2)
- source.params.interleaved = 1;
- if (random() % 2)
- source.params.authkey = get_random_key_id();
+ source.params.interleaved = random() % 2;
+ source.params.authkey = random() % 2 ? get_random_key_id() : INACTIVE_AUTHKEY;
source.params.version = random() % 4 + 1;
UTI_ZeroTimespec(&current_time);
@@ -475,3 +475,11 @@ test_unit(void)
CNF_Finalise();
HSH_Finalise();
}
+
+#else
+void
+test_unit(void)
+{
+ TEST_REQUIRE(0);
+}
+#endif
diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c
index ea8f19c..f13852e 100644
--- a/test/unit/ntp_sources.c
+++ b/test/unit/ntp_sources.c
@@ -18,10 +18,14 @@
**********************************************************************
*/
+#include <config.h>
+#include "test.h"
+
+#ifdef FEAT_NTP
+
#include <ntp_sources.c>
#include <conf.h>
#include <ntp_io.h>
-#include "test.h"
void
test_unit(void)
@@ -98,3 +102,11 @@ test_unit(void)
CNF_Finalise();
HSH_Finalise();
}
+
+#else
+void
+test_unit(void)
+{
+ TEST_REQUIRE(0);
+}
+#endif
diff --git a/test/unit/samplefilt.c b/test/unit/samplefilt.c
index 294a9bf..a371b3a 100644
--- a/test/unit/samplefilt.c
+++ b/test/unit/samplefilt.c
@@ -18,9 +18,13 @@
**********************************************************************
*/
-#include <samplefilt.c>
+#include <local.h>
#include "test.h"
+#define LCL_GetSysPrecisionAsQuantum() (1.0e-6)
+
+#include <samplefilt.c>
+
void
test_unit(void)
{
diff --git a/test/unit/sources.c b/test/unit/sources.c
index b81f808..83f7060 100644
--- a/test/unit/sources.c
+++ b/test/unit/sources.c
@@ -1,6 +1,6 @@
/*
**********************************************************************
- * Copyright (C) Miroslav Lichvar 2016
+ * Copyright (C) Miroslav Lichvar 2016, 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/test/unit/test.c b/test/unit/test.c
index 3a9ec74..fbfeb4b 100644
--- a/test/unit/test.c
+++ b/test/unit/test.c
@@ -22,6 +22,7 @@
#include <sysincl.h>
#include <logging.h>
#include <localp.h>
+#include <util.h>
#include "test.h"
@@ -32,6 +33,13 @@ TST_Fail(int line)
exit(1);
}
+void
+TST_Skip(int line)
+{
+ printf("SKIP (on line %d)\n", line);
+ exit(0);
+}
+
int
main(int argc, char **argv)
{
diff --git a/test/unit/test.h b/test/unit/test.h
index f409252..2d3637b 100644
--- a/test/unit/test.h
+++ b/test/unit/test.h
@@ -33,7 +33,16 @@ extern void test_unit(void);
} \
} while (0)
+#define TEST_REQUIRE(expr) \
+ do { \
+ if (!(expr)) { \
+ TST_Skip(__LINE__); \
+ exit(0); \
+ } \
+ } while (0)
+
extern void TST_Fail(int line);
+extern void TST_Skip(int line);
extern void TST_SuspendLogging(void);
extern void TST_ResumeLogging(void);
diff --git a/util.c b/util.c
index bfbae33..e7e3442 100644
--- a/util.c
+++ b/util.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2009, 2012-2017
+ * Copyright (C) Miroslav Lichvar 2009, 2012-2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
diff --git a/version.txt b/version.txt
index 37969b7..c50661d 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-3.4-pre1
+3.5-pre1