mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 09:55:06 -05:00
Compare commits
45 Commits
3.4
...
3.5-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04328ceead | ||
|
|
f00fed2009 | ||
|
|
ffb9887cce | ||
|
|
9220c9b8a2 | ||
|
|
2e28b19112 | ||
|
|
636a4e2794 | ||
|
|
5c9e1e0b69 | ||
|
|
64fd1b8ba5 | ||
|
|
69d3913f3e | ||
|
|
08fd011b6a | ||
|
|
c172268cfe | ||
|
|
94b014865c | ||
|
|
099aaf2cb1 | ||
|
|
4481a8b24f | ||
|
|
b626fe661e | ||
|
|
ba8fcd145d | ||
|
|
981d09de40 | ||
|
|
86a99bb257 | ||
|
|
3093a11cd0 | ||
|
|
058b788d38 | ||
|
|
66a42fa493 | ||
|
|
a85f63cc15 | ||
|
|
bbe1e69dcc | ||
|
|
1b52bba7b9 | ||
|
|
c5c80ef400 | ||
|
|
a78031ce0d | ||
|
|
34e9dd13ce | ||
|
|
6e52a9be7a | ||
|
|
69c6dffd63 | ||
|
|
2ddd0ae231 | ||
|
|
79db0b7eca | ||
|
|
2ebba7fbaa | ||
|
|
e392d1fde9 | ||
|
|
d7c93ec950 | ||
|
|
6af39d63aa | ||
|
|
cc8414b1b3 | ||
|
|
6b44055e3d | ||
|
|
9f9c6cc6ab | ||
|
|
f176193d35 | ||
|
|
e8bc41e862 | ||
|
|
91dbe3c6c2 | ||
|
|
3e876d4218 | ||
|
|
31b1f2e8a1 | ||
|
|
4169e94b1d | ||
|
|
948ecf8431 |
@@ -113,10 +113,12 @@ install-docs :
|
|||||||
quickcheck : chronyd chronyc
|
quickcheck : chronyd chronyc
|
||||||
$(MAKE) -C test/unit check
|
$(MAKE) -C test/unit check
|
||||||
cd test/simulation && ./run
|
cd test/simulation && ./run
|
||||||
|
cd test/system && ./run
|
||||||
|
|
||||||
check : chronyd chronyc
|
check : chronyd chronyc
|
||||||
$(MAKE) -C test/unit check
|
$(MAKE) -C test/unit check
|
||||||
cd test/simulation && ./run -i 20 -m 2
|
cd test/simulation && ./run -i 20 -m 2
|
||||||
|
cd test/system && ./run
|
||||||
|
|
||||||
print-chronyd-objects :
|
print-chronyd-objects :
|
||||||
@echo $(OBJS) $(EXTRA_OBJS)
|
@echo $(OBJS) $(EXTRA_OBJS)
|
||||||
|
|||||||
26
NEWS
26
NEWS
@@ -1,3 +1,29 @@
|
|||||||
|
New in version 3.5.1
|
||||||
|
====================
|
||||||
|
|
||||||
|
Security fixes
|
||||||
|
--------------
|
||||||
|
* Create new file when writing pidfile (CVE-2020-14367)
|
||||||
|
|
||||||
|
New in version 3.5
|
||||||
|
==================
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
* Add support for more accurate reading of PHC on Linux 5.0
|
||||||
|
* Add support for hardware timestamping on interfaces with read-only
|
||||||
|
timestamping configuration
|
||||||
|
* 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
|
New in version 3.4
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|||||||
109
README
109
README
@@ -108,132 +108,57 @@ The following people have provided patches and other major contributions
|
|||||||
to the program :
|
to the program :
|
||||||
|
|
||||||
Lonnie Abelbeck <lonnie@abelbeck.com>
|
Lonnie Abelbeck <lonnie@abelbeck.com>
|
||||||
Patch to add tab-completion to chronyc
|
|
||||||
|
|
||||||
Benny Lyne Amorsen <benny@amorsen.dk>
|
Benny Lyne Amorsen <benny@amorsen.dk>
|
||||||
Patch to add minstratum option
|
|
||||||
|
|
||||||
Andrew Bishop <amb@gedanken.demon.co.uk>
|
Andrew Bishop <amb@gedanken.demon.co.uk>
|
||||||
Fixes for bugs in logging when in daemon mode
|
Vincent Blut <vincent.debian@free.fr>
|
||||||
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
|
|
||||||
|
|
||||||
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
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>
|
Erik Bryer <ebryer@spots.ab.ca>
|
||||||
Entries in contrib directory
|
Jonathan Cameron <jic23@cam.ac.uk>
|
||||||
|
|
||||||
Bryan Christianson <bryan@whatroute.net>
|
Bryan Christianson <bryan@whatroute.net>
|
||||||
Support for macOS
|
|
||||||
Support for privilege separation
|
|
||||||
Entries in contrib directory
|
|
||||||
|
|
||||||
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
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>
|
Christian Ehrhardt <christian.ehrhardt@canonical.com>
|
||||||
Patch to generate a warning message when CAP_SYS_TIME is missing
|
|
||||||
|
|
||||||
Paul Elliott <pelliott@io.com>
|
Paul Elliott <pelliott@io.com>
|
||||||
Entries in contrib directory
|
Stefan R. Filipek <srfilipek@gmail.com>
|
||||||
|
|
||||||
Mike Fleetwood <mike@rockover.demon.co.uk>
|
Mike Fleetwood <mike@rockover.demon.co.uk>
|
||||||
Fixes for compiler warnings
|
|
||||||
|
|
||||||
Alexander Gretencord <arutha@gmx.de>
|
Alexander Gretencord <arutha@gmx.de>
|
||||||
Changes to installation directory system to make it easier for
|
|
||||||
package builders
|
|
||||||
|
|
||||||
Andrew Griffiths <agriffit@redhat.com>
|
Andrew Griffiths <agriffit@redhat.com>
|
||||||
Patch to add support for seccomp filter
|
|
||||||
|
|
||||||
Walter Haidinger <walter.haidinger@gmx.at>
|
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>
|
Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
|
||||||
Port to NetBSD
|
|
||||||
|
|
||||||
John Hasler <john@dhh.gt.org>
|
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>
|
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>
|
Liam Hatton <me@liamhatton.com>
|
||||||
Advice on configuring for Linux on PPC
|
|
||||||
|
|
||||||
Jachym Holecek <jakym@volny.cz>
|
Jachym Holecek <jakym@volny.cz>
|
||||||
Patch to make Linux real time clock work with devfs
|
|
||||||
|
|
||||||
Håkan Johansson <f96hajo@chalmers.se>
|
Håkan Johansson <f96hajo@chalmers.se>
|
||||||
Patch to avoid large values in sources and sourcestats output
|
|
||||||
|
|
||||||
Jim Knoble <jmknoble@pobox.com>
|
Jim Knoble <jmknoble@pobox.com>
|
||||||
Fixes for compiler warnings
|
|
||||||
|
|
||||||
Antti Jrvinen <costello@iki.fi>
|
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>
|
Victor Moroz <vim@prv.adlum.ru>
|
||||||
Patch to support Linux with HZ!=100
|
|
||||||
|
|
||||||
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
||||||
Patch to add acquisitionport directive
|
|
||||||
|
|
||||||
Frank Otto <sandwichmacher@web.de>
|
Frank Otto <sandwichmacher@web.de>
|
||||||
Handling arbitrary HZ values
|
|
||||||
|
|
||||||
Denny Page <dennypage@me.com>
|
Denny Page <dennypage@me.com>
|
||||||
Advice on support for hardware timestamping
|
|
||||||
|
|
||||||
Chris Perl <cperl@janestreet.com>
|
Chris Perl <cperl@janestreet.com>
|
||||||
Patches to improve support for refclocks keeping time in TAI
|
|
||||||
|
|
||||||
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
||||||
Patch to add refresh command to chronyc
|
|
||||||
|
|
||||||
Andreas Piesk <apiesk@virbus.de>
|
Andreas Piesk <apiesk@virbus.de>
|
||||||
Patch to make chronyc use the readline library if available
|
|
||||||
|
|
||||||
Andreas Steinmetz <ast@domdv.de>
|
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>
|
Timo Teras <timo.teras@iki.fi>
|
||||||
Patch to reply correctly on multihomed hosts
|
|
||||||
|
|
||||||
Bill Unruh <unruh@physics.ubc.ca>
|
Bill Unruh <unruh@physics.ubc.ca>
|
||||||
Advice on statistics
|
|
||||||
|
|
||||||
Stephen Wadeley <swadeley@redhat.com>
|
Stephen Wadeley <swadeley@redhat.com>
|
||||||
Improvements to man pages
|
Bernhard Weiss <lisnablagh@web.de>
|
||||||
|
|
||||||
Wolfgang Weisselberg <weissel@netcologne.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>
|
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||||
Many robustness and security improvements
|
Ulrich Windl <ulrich.windl@rz.uni-regensburg.de>
|
||||||
|
|
||||||
Ulrich Windl <ulrich.windl@rz.uni-regensburg.de> for the
|
|
||||||
Information about the Linux 2.2 kernel functionality compared to 2.0
|
|
||||||
|
|
||||||
Doug Woodward <dougw@whistler.com>
|
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
|
Many other people have contributed bug reports and suggestions. We are sorry
|
||||||
we cannot identify all of you individually.
|
we cannot identify all of you individually.
|
||||||
|
|||||||
2
client.c
2
client.c
@@ -3159,7 +3159,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2018 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2019 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
|
|||||||
44
configure
vendored
44
configure
vendored
@@ -6,6 +6,7 @@
|
|||||||
# Copyright (C) Richard P. Curnow 1997-2003
|
# Copyright (C) Richard P. Curnow 1997-2003
|
||||||
# Copyright (C) Bryan Christianson 2016
|
# Copyright (C) Bryan Christianson 2016
|
||||||
# Copyright (C) Miroslav Lichvar 2009, 2012-2018
|
# Copyright (C) Miroslav Lichvar 2009, 2012-2018
|
||||||
|
# Copyright (C) Stefan R. Filipek 2019
|
||||||
#
|
#
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
@@ -227,6 +228,7 @@ feat_timestamping=1
|
|||||||
try_timestamping=0
|
try_timestamping=0
|
||||||
feat_ntp_signd=0
|
feat_ntp_signd=0
|
||||||
ntp_era_split=""
|
ntp_era_split=""
|
||||||
|
use_pthread=0
|
||||||
default_user="root"
|
default_user="root"
|
||||||
default_hwclockfile=""
|
default_hwclockfile=""
|
||||||
default_pidfile="/var/run/chrony/chronyd.pid"
|
default_pidfile="/var/run/chrony/chronyd.pid"
|
||||||
@@ -395,7 +397,7 @@ SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
|
|||||||
|
|
||||||
case $OPERATINGSYSTEM in
|
case $OPERATINGSYSTEM in
|
||||||
Linux)
|
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_libcap != "0" ] && try_libcap=1
|
||||||
try_rtc=1
|
try_rtc=1
|
||||||
[ $try_seccomp != "0" ] && try_seccomp=1
|
[ $try_seccomp != "0" ] && try_seccomp=1
|
||||||
@@ -410,7 +412,9 @@ case $OPERATINGSYSTEM in
|
|||||||
# recvmmsg() seems to be broken on FreeBSD 11.0 and it's just
|
# recvmmsg() seems to be broken on FreeBSD 11.0 and it's just
|
||||||
# a wrapper around recvmsg()
|
# a wrapper around recvmsg()
|
||||||
try_recvmmsg=0
|
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
|
add_def FREEBSD
|
||||||
if [ $feat_droproot = "1" ]; then
|
if [ $feat_droproot = "1" ]; then
|
||||||
add_def FEAT_PRIVDROP
|
add_def FEAT_PRIVDROP
|
||||||
@@ -419,8 +423,10 @@ case $OPERATINGSYSTEM in
|
|||||||
echo "Configuring for $SYSTEM"
|
echo "Configuring for $SYSTEM"
|
||||||
;;
|
;;
|
||||||
NetBSD)
|
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_clockctl=1
|
||||||
|
try_setsched=1
|
||||||
|
try_lockmem=1
|
||||||
add_def NETBSD
|
add_def NETBSD
|
||||||
echo "Configuring for $SYSTEM"
|
echo "Configuring for $SYSTEM"
|
||||||
;;
|
;;
|
||||||
@@ -445,9 +451,11 @@ case $OPERATINGSYSTEM in
|
|||||||
echo "Configuring for macOS (" $SYSTEM "macOS version" $VERSION ")"
|
echo "Configuring for macOS (" $SYSTEM "macOS version" $VERSION ")"
|
||||||
;;
|
;;
|
||||||
SunOS)
|
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_LIBS="-lsocket -lnsl -lresolv"
|
||||||
EXTRA_CLI_LIBS="-lsocket -lnsl -lresolv"
|
EXTRA_CLI_LIBS="-lsocket -lnsl -lresolv"
|
||||||
|
try_setsched=1
|
||||||
|
try_lockmem=1
|
||||||
add_def SOLARIS
|
add_def SOLARIS
|
||||||
# These are needed to have msg_control in struct msghdr
|
# These are needed to have msg_control in struct msghdr
|
||||||
add_def __EXTENSIONS__
|
add_def __EXTENSIONS__
|
||||||
@@ -652,7 +660,7 @@ then
|
|||||||
add_def FEAT_ASYNCDNS
|
add_def FEAT_ASYNCDNS
|
||||||
add_def USE_PTHREAD_ASYNCDNS
|
add_def USE_PTHREAD_ASYNCDNS
|
||||||
EXTRA_OBJECTS="$EXTRA_OBJECTS nameserv_async.o"
|
EXTRA_OBJECTS="$EXTRA_OBJECTS nameserv_async.o"
|
||||||
MYCFLAGS="$MYCFLAGS -pthread"
|
use_pthread=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
if test_code 'arc4random_buf()' 'stdlib.h' '' '' 'arc4random_buf(NULL, 0);'; then
|
||||||
@@ -786,25 +794,33 @@ fi
|
|||||||
|
|
||||||
if [ $try_setsched = "1" ] && \
|
if [ $try_setsched = "1" ] && \
|
||||||
test_code \
|
test_code \
|
||||||
'sched_setscheduler()' \
|
'pthread_setschedparam()' \
|
||||||
'sched.h' '' '' '
|
'pthread.h sched.h' '-pthread' '' '
|
||||||
struct sched_param sched;
|
struct sched_param sched;
|
||||||
sched_get_priority_max(SCHED_FIFO);
|
sched_get_priority_max(SCHED_FIFO);
|
||||||
sched_setscheduler(0, SCHED_FIFO, &sched);'
|
pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched);'
|
||||||
then
|
then
|
||||||
add_def HAVE_SCHED_SETSCHEDULER
|
add_def HAVE_PTHREAD_SETSCHEDPARAM
|
||||||
|
use_pthread=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $try_lockmem = "1" ] && \
|
if [ $try_lockmem = "1" ] && \
|
||||||
test_code \
|
test_code \
|
||||||
'mlockall()' \
|
'mlockall()' \
|
||||||
'sys/mman.h sys/resource.h' '' '' '
|
'sys/mman.h' '' '' '
|
||||||
struct rlimit rlim;
|
|
||||||
setrlimit(RLIMIT_MEMLOCK, &rlim);
|
|
||||||
mlockall(MCL_CURRENT|MCL_FUTURE);'
|
mlockall(MCL_CURRENT|MCL_FUTURE);'
|
||||||
then
|
then
|
||||||
add_def HAVE_MLOCKALL
|
add_def HAVE_MLOCKALL
|
||||||
fi
|
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" ]
|
if [ $feat_forcednsretry = "1" ]
|
||||||
then
|
then
|
||||||
@@ -896,6 +912,10 @@ if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $use_pthread = "1" ]; then
|
||||||
|
MYCFLAGS="$MYCFLAGS -pthread"
|
||||||
|
fi
|
||||||
|
|
||||||
SYSCONFDIR=/etc
|
SYSCONFDIR=/etc
|
||||||
if [ "x$SETSYSCONFDIR" != "x" ]; then
|
if [ "x$SETSYSCONFDIR" != "x" ]; then
|
||||||
SYSCONFDIR=$SETSYSCONFDIR
|
SYSCONFDIR=$SETSYSCONFDIR
|
||||||
|
|||||||
@@ -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
|
started in the boot sequence after *chronyd* from reading the clock before it
|
||||||
has been stepped.
|
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
|
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
|
time source. It has two mandatory parameters, a driver name and a
|
||||||
driver-specific parameter. The two parameters are followed by zero or more
|
driver-specific parameter. The two parameters are followed by zero or more
|
||||||
refclock options. Some drivers have special options, which can be appended to
|
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*:
|
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/ptp0 poll 0 dpoll -2 offset -37
|
||||||
refclock PHC /dev/ptp1:nocrossts poll 3 pps
|
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
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
::
|
::
|
||||||
@@ -681,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
|
algorithm. Their synchronisation distance has to be shorter than the distance
|
||||||
of the selected source multiplied by the value of the limit. Also, their
|
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.
|
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
|
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
|
source combining algorithm and only the selected source will be used to control
|
||||||
@@ -1601,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*
|
The directive takes no arguments. It is equivalent to specifying the *-u*
|
||||||
switch to the Linux *hwclock* program.
|
switch to the Linux *hwclock* program.
|
||||||
+
|
+
|
||||||
Note that this setting is overridden when the <<hwclockfile,*hwclockfile*>>
|
Note that this setting is overridden by the <<hwclockfile,*hwclockfile*>> file
|
||||||
directive is specified.
|
and is not relevant for the <<rtcsync,*rtcsync*>> directive.
|
||||||
|
|
||||||
[[rtcsync]]*rtcsync*::
|
[[rtcsync]]*rtcsync*::
|
||||||
The *rtcsync* directive enables a mode where the system time is periodically
|
The *rtcsync* directive enables a mode where the system time is periodically
|
||||||
@@ -2063,11 +2065,11 @@ file when the <<chronyc.adoc#rekey,*rekey*>> command is issued by *chronyc*).
|
|||||||
|
|
||||||
[[lock_all]]*lock_all*::
|
[[lock_all]]*lock_all*::
|
||||||
The *lock_all* directive will lock chronyd into RAM so that it will never be
|
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
|
paged out. This mode is supported on Linux, FreeBSD, NetBSD, and Solaris. This
|
||||||
*mlockall()* system call to prevent *chronyd* from ever being swapped out. This
|
directive uses the POSIX *mlockall()* system call to prevent *chronyd* from
|
||||||
should result in lower and more consistent latency. It should not have
|
ever being swapped out. This should result in lower and more consistent
|
||||||
significant impact on performance as *chronyd's* memory usage is modest. The
|
latency. It should not have significant impact on performance as *chronyd's*
|
||||||
*mlockall(2)* man page has more details.
|
memory usage is modest. The *mlockall(2)* man page has more details.
|
||||||
|
|
||||||
[[pidfile]]*pidfile* _file_::
|
[[pidfile]]*pidfile* _file_::
|
||||||
Unless *chronyd* is started with the *-Q* option, it writes its process ID
|
Unless *chronyd* is started with the *-Q* option, it writes its process ID
|
||||||
@@ -2081,26 +2083,26 @@ pidfile /run/chronyd.pid
|
|||||||
----
|
----
|
||||||
|
|
||||||
[[sched_priority]]*sched_priority* _priority_::
|
[[sched_priority]]*sched_priority* _priority_::
|
||||||
On Linux, the *sched_priority* directive will select the SCHED_FIFO real-time
|
On Linux, FreeBSD, NetBSD, and Solaris, the *sched_priority* directive will
|
||||||
scheduler at the specified priority (which must be between 0 and 100). On
|
select the SCHED_FIFO real-time scheduler at the specified priority (which must
|
||||||
macOS, this option must have either a value of 0 (the default) to disable the
|
be between 0 and 100). On macOS, this option must have either a value of 0 (the
|
||||||
thread time constraint policy or 1 for the policy to be enabled. Other systems
|
default) to disable the thread time constraint policy or 1 for the policy to be
|
||||||
do not support this option.
|
enabled.
|
||||||
+
|
+
|
||||||
On Linux, this directive uses the *sched_setscheduler()* system call to
|
On systems other than macOS, this directive uses the *pthread_setschedparam()*
|
||||||
instruct the kernel to use the SCHED_FIFO first-in, first-out real-time
|
system call to instruct the kernel to use the SCHED_FIFO first-in, first-out
|
||||||
scheduling policy for *chronyd* with the specified priority. This means that
|
real-time scheduling policy for *chronyd* with the specified priority. This
|
||||||
whenever *chronyd* is ready to run it will run, interrupting whatever else is
|
means that whenever *chronyd* is ready to run it will run, interrupting
|
||||||
running unless it is a higher priority real-time process. This should not
|
whatever else is running unless it is a higher priority real-time process. This
|
||||||
impact performance as *chronyd* resource requirements are modest, but it should
|
should not impact performance as *chronyd* resource requirements are modest,
|
||||||
result in lower and more consistent latency since *chronyd* will not need to
|
but it should result in lower and more consistent latency since *chronyd* will
|
||||||
wait for the scheduler to get around to running it. You should not use this
|
not need to wait for the scheduler to get around to running it. You should not
|
||||||
unless you really need it. The *sched_setscheduler(2)* man page has more
|
use this unless you really need it. The *pthread_setschedparam(3)* man page has
|
||||||
details.
|
more details.
|
||||||
+
|
+
|
||||||
On macOS, this directive uses the *thread_policy_set()* kernel call to
|
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
|
specify real-time scheduling. As noted above, you should not use this directive
|
||||||
directive unless you really need it.
|
unless you really need it.
|
||||||
|
|
||||||
[[user]]*user* _user_::
|
[[user]]*user* _user_::
|
||||||
The *user* directive sets the name of the system user to which *chronyd* will
|
The *user* directive sets the name of the system user to which *chronyd* will
|
||||||
|
|||||||
10
doc/faq.adoc
10
doc/faq.adoc
@@ -217,6 +217,12 @@ server ntp.local minpoll 0 maxpoll 0 xleave
|
|||||||
hwtimestamp eth0
|
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
|
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
|
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
|
can be enabled in order to update the clock at a reduced rate with more stable
|
||||||
@@ -261,6 +267,10 @@ maxchange 1000 1 1
|
|||||||
maxclockerror 15
|
maxclockerror 15
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Note that increasing `minsamples` may cause the offsets in the `tracking` and
|
||||||
|
`sourcestats` reports/logs to be significantly smaller than the actual offsets
|
||||||
|
and be unsuitable for monitoring.
|
||||||
|
|
||||||
=== What happened to the `commandkey` and `generatecommandkey` directives?
|
=== What happened to the `commandkey` and `generatecommandkey` directives?
|
||||||
|
|
||||||
They were removed in version 2.2. Authentication is no longer supported in the
|
They were removed in version 2.2. Authentication is no longer supported in the
|
||||||
|
|||||||
@@ -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
|
code is supplied in the form of a gzipped tar file, which unpacks to a
|
||||||
subdirectory identifying the name and version of the program.
|
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
|
After unpacking the source code, change directory into it, and type
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ ConditionCapability=CAP_SYS_TIME
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=forking
|
Type=forking
|
||||||
PIDFile=/var/run/chrony/chronyd.pid
|
PIDFile=/run/chrony/chronyd.pid
|
||||||
EnvironmentFile=-/etc/sysconfig/chronyd
|
EnvironmentFile=-/etc/sysconfig/chronyd
|
||||||
ExecStart=/usr/sbin/chronyd $OPTIONS
|
ExecStart=/usr/sbin/chronyd $OPTIONS
|
||||||
PrivateTmp=yes
|
PrivateTmp=yes
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "sysincl.h"
|
#include "sysincl.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include "md5.c"
|
#include "md5.c"
|
||||||
|
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ void LOG_Message(LOG_Severity severity,
|
|||||||
system_log = 0;
|
system_log = 0;
|
||||||
log_message(1, severity, buf);
|
log_message(1, severity, buf);
|
||||||
}
|
}
|
||||||
|
exit(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|||||||
6
main.c
6
main.c
@@ -281,13 +281,9 @@ write_pidfile(void)
|
|||||||
if (!pidfile[0])
|
if (!pidfile[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out = fopen(pidfile, "w");
|
out = UTI_OpenFile(NULL, pidfile, NULL, 'W', 0644);
|
||||||
if (!out) {
|
|
||||||
LOG_FATAL("Could not open %s : %s", pidfile, strerror(errno));
|
|
||||||
} else {
|
|
||||||
fprintf(out, "%d\n", (int)getpid());
|
fprintf(out, "%d\n", (int)getpid());
|
||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
#include "sysincl.h"
|
#include "sysincl.h"
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
|
||||||
#include "nameserv.h"
|
#include "nameserv.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|||||||
14
ntp_io.c
14
ntp_io.c
@@ -105,6 +105,9 @@ static int separate_client_sockets;
|
|||||||
disabled */
|
disabled */
|
||||||
static int permanent_server_sockets;
|
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 */
|
/* Flag indicating that we have been initialised */
|
||||||
static int initialised=0;
|
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.in4.sin_port = htons(port_number);
|
||||||
my_addr_len = sizeof (my_addr.in4);
|
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;
|
break;
|
||||||
#ifdef FEAT_IPV6
|
#ifdef FEAT_IPV6
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
@@ -821,8 +827,8 @@ NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr,
|
|||||||
msg.msg_flags = 0;
|
msg.msg_flags = 0;
|
||||||
cmsglen = 0;
|
cmsglen = 0;
|
||||||
|
|
||||||
if (local_addr->ip_addr.family == IPADDR_INET4) {
|
|
||||||
#ifdef HAVE_IN_PKTINFO
|
#ifdef HAVE_IN_PKTINFO
|
||||||
|
if (local_addr->ip_addr.family == IPADDR_INET4) {
|
||||||
struct in_pktinfo *ipi;
|
struct in_pktinfo *ipi;
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
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);
|
ipi->ipi_spec_dst.s_addr = htonl(local_addr->ip_addr.addr.in4);
|
||||||
if (local_addr->if_index != INVALID_IF_INDEX)
|
if (local_addr->if_index != INVALID_IF_INDEX)
|
||||||
ipi->ipi_ifindex = local_addr->if_index;
|
ipi->ipi_ifindex = local_addr->if_index;
|
||||||
|
}
|
||||||
#elif defined(IP_SENDSRCADDR)
|
#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;
|
struct in_addr *addr;
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
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 = (struct in_addr *)CMSG_DATA(cmsg);
|
||||||
addr->s_addr = htonl(local_addr->ip_addr.addr.in4);
|
addr->s_addr = htonl(local_addr->ip_addr.addr.in4);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IN6_PKTINFO
|
#ifdef HAVE_IN6_PKTINFO
|
||||||
if (local_addr->ip_addr.family == IPADDR_INET6) {
|
if (local_addr->ip_addr.family == IPADDR_INET6) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016-2018
|
* Copyright (C) Miroslav Lichvar 2016-2019
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -123,7 +123,7 @@ add_interface(CNF_HwTsInterface *conf_iface)
|
|||||||
struct ethtool_ts_info ts_info;
|
struct ethtool_ts_info ts_info;
|
||||||
struct hwtstamp_config ts_config;
|
struct hwtstamp_config ts_config;
|
||||||
struct ifreq req;
|
struct ifreq req;
|
||||||
int sock_fd, if_index, phc_fd, req_hwts_flags;
|
int sock_fd, if_index, phc_fd, req_hwts_flags, rx_filter;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct Interface *iface;
|
struct Interface *iface;
|
||||||
|
|
||||||
@@ -177,41 +177,52 @@ add_interface(CNF_HwTsInterface *conf_iface)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_config.flags = 0;
|
|
||||||
ts_config.tx_type = HWTSTAMP_TX_ON;
|
|
||||||
|
|
||||||
switch (conf_iface->rxfilter) {
|
switch (conf_iface->rxfilter) {
|
||||||
case CNF_HWTS_RXFILTER_ANY:
|
case CNF_HWTS_RXFILTER_ANY:
|
||||||
#ifdef HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP
|
#ifdef HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP
|
||||||
if (ts_info.rx_filters & (1 << HWTSTAMP_FILTER_NTP_ALL))
|
if (ts_info.rx_filters & (1 << HWTSTAMP_FILTER_NTP_ALL))
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_NTP_ALL;
|
rx_filter = HWTSTAMP_FILTER_NTP_ALL;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (ts_info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))
|
if (ts_info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_ALL;
|
rx_filter = HWTSTAMP_FILTER_ALL;
|
||||||
else
|
else
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
rx_filter = HWTSTAMP_FILTER_NONE;
|
||||||
break;
|
break;
|
||||||
case CNF_HWTS_RXFILTER_NONE:
|
case CNF_HWTS_RXFILTER_NONE:
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
rx_filter = HWTSTAMP_FILTER_NONE;
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP
|
#ifdef HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP
|
||||||
case CNF_HWTS_RXFILTER_NTP:
|
case CNF_HWTS_RXFILTER_NTP:
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_NTP_ALL;
|
rx_filter = HWTSTAMP_FILTER_NTP_ALL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ts_config.rx_filter = HWTSTAMP_FILTER_ALL;
|
rx_filter = HWTSTAMP_FILTER_ALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ts_config.flags = 0;
|
||||||
|
ts_config.tx_type = HWTSTAMP_TX_ON;
|
||||||
|
ts_config.rx_filter = rx_filter;
|
||||||
req.ifr_data = (char *)&ts_config;
|
req.ifr_data = (char *)&ts_config;
|
||||||
|
|
||||||
if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) {
|
if (ioctl(sock_fd, SIOCSHWTSTAMP, &req)) {
|
||||||
DEBUG_LOG("ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno));
|
DEBUG_LOG("ioctl(%s) failed : %s", "SIOCSHWTSTAMP", strerror(errno));
|
||||||
|
|
||||||
|
/* Check the current timestamping configuration in case this interface
|
||||||
|
allows only reading of the configuration and it was already configured
|
||||||
|
as requested */
|
||||||
|
req.ifr_data = (char *)&ts_config;
|
||||||
|
#ifdef SIOCGHWTSTAMP
|
||||||
|
if (ioctl(sock_fd, SIOCGHWTSTAMP, &req) ||
|
||||||
|
ts_config.tx_type != HWTSTAMP_TX_ON || ts_config.rx_filter != rx_filter)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
close(sock_fd);
|
close(sock_fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close(sock_fd);
|
close(sock_fd);
|
||||||
|
|
||||||
@@ -584,7 +595,11 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts,
|
|||||||
if (rx_ntp_length && iface->link_speed) {
|
if (rx_ntp_length && iface->link_speed) {
|
||||||
if (!l2_length)
|
if (!l2_length)
|
||||||
l2_length = (family == IPADDR_INET4 ? iface->l2_udp4_ntp_start :
|
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);
|
rx_correction = l2_length / (1.0e6 / 8 * iface->link_speed);
|
||||||
|
|
||||||
UTI_AddDoubleToTimespec(hw_ts, rx_correction, hw_ts);
|
UTI_AddDoubleToTimespec(hw_ts, rx_correction, hw_ts);
|
||||||
@@ -841,7 +856,12 @@ NIO_Linux_RequestTxTimestamp(struct msghdr *msg, int cmsglen, int sock_fd)
|
|||||||
/* Add control message that will enable TX timestamping for this message.
|
/* Add control message that will enable TX timestamping for this message.
|
||||||
Don't use CMSG_NXTHDR as the one in glibc is buggy for creating new
|
Don't use CMSG_NXTHDR as the one in glibc is buggy for creating new
|
||||||
control messages. */
|
control messages. */
|
||||||
cmsg = (struct cmsghdr *)((char *)CMSG_FIRSTHDR(msg) + cmsglen);
|
|
||||||
|
cmsg = CMSG_FIRSTHDR(msg);
|
||||||
|
if (!cmsg || cmsglen + CMSG_SPACE(sizeof (ts_tx_flags)) > msg->msg_controllen)
|
||||||
|
return cmsglen;
|
||||||
|
|
||||||
|
cmsg = (struct cmsghdr *)((char *)cmsg + cmsglen);
|
||||||
memset(cmsg, 0, CMSG_SPACE(sizeof (ts_tx_flags)));
|
memset(cmsg, 0, CMSG_SPACE(sizeof (ts_tx_flags)));
|
||||||
cmsglen += CMSG_SPACE(sizeof (ts_tx_flags));
|
cmsglen += CMSG_SPACE(sizeof (ts_tx_flags));
|
||||||
|
|
||||||
|
|||||||
62
refclock.c
62
refclock.c
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2018
|
* Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2019
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* 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;
|
return instance->driver_parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_next_driver_option(RCL_Instance instance, char *option)
|
||||||
|
{
|
||||||
|
if (option == NULL)
|
||||||
|
option = instance->driver_parameter;
|
||||||
|
|
||||||
|
option += strlen(option) + 1;
|
||||||
|
|
||||||
|
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, len) &&
|
||||||
|
(option[len] == '=' || option[len] == '\0'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options || !options[i])
|
||||||
|
LOG_FATAL("Invalid refclock driver option %s", option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
RCL_GetDriverOption(RCL_Instance instance, char *name)
|
RCL_GetDriverOption(RCL_Instance instance, char *name)
|
||||||
{
|
{
|
||||||
char *s, *e;
|
char *option;
|
||||||
int n;
|
int len;
|
||||||
|
|
||||||
s = instance->driver_parameter;
|
len = strlen(name);
|
||||||
e = s + instance->driver_parameter_length;
|
|
||||||
n = strlen(name);
|
|
||||||
|
|
||||||
while (1) {
|
for (option = get_next_driver_option(instance, NULL);
|
||||||
s += strlen(s) + 1;
|
option;
|
||||||
if (s >= e)
|
option = get_next_driver_option(instance, option)) {
|
||||||
break;
|
if (!strncmp(name, option, len)) {
|
||||||
if (!strncmp(name, s, n)) {
|
if (option[len] == '=')
|
||||||
if (s[n] == '=')
|
return option + len + 1;
|
||||||
return s + n + 1;
|
if (option[len] == '\0')
|
||||||
if (s[n] == '\0')
|
return option + len;
|
||||||
return s + n;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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_SetDriverData(RCL_Instance instance, void *data);
|
||||||
extern void *RCL_GetDriverData(RCL_Instance instance);
|
extern void *RCL_GetDriverData(RCL_Instance instance);
|
||||||
extern char *RCL_GetDriverParameter(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 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_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);
|
extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
|
||||||
|
|||||||
@@ -56,10 +56,13 @@ static void read_ext_pulse(int sockfd, int event, void *anything);
|
|||||||
|
|
||||||
static int phc_initialise(RCL_Instance instance)
|
static int phc_initialise(RCL_Instance instance)
|
||||||
{
|
{
|
||||||
|
const char *options[] = {"nocrossts", "extpps", "pin", "channel", "clear", NULL};
|
||||||
struct phc_instance *phc;
|
struct phc_instance *phc;
|
||||||
int phc_fd, rising_edge;
|
int phc_fd, rising_edge;
|
||||||
char *path, *s;
|
char *path, *s;
|
||||||
|
|
||||||
|
RCL_CheckDriverOptions(instance, options);
|
||||||
|
|
||||||
path = RCL_GetDriverParameter(instance);
|
path = RCL_GetDriverParameter(instance);
|
||||||
|
|
||||||
phc_fd = SYS_Linux_OpenPHC(path, 0);
|
phc_fd = SYS_Linux_OpenPHC(path, 0);
|
||||||
|
|||||||
@@ -48,12 +48,15 @@ struct pps_instance {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int pps_initialise(RCL_Instance instance) {
|
static int pps_initialise(RCL_Instance instance) {
|
||||||
|
const char *options[] = {"clear", NULL};
|
||||||
pps_handle_t handle;
|
pps_handle_t handle;
|
||||||
pps_params_t params;
|
pps_params_t params;
|
||||||
struct pps_instance *pps;
|
struct pps_instance *pps;
|
||||||
int fd, edge_clear, mode;
|
int fd, edge_clear, mode;
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
|
RCL_CheckDriverOptions(instance, options);
|
||||||
|
|
||||||
path = RCL_GetDriverParameter(instance);
|
path = RCL_GetDriverParameter(instance);
|
||||||
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
|
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
|
||||||
|
|
||||||
|
|||||||
@@ -59,10 +59,13 @@ struct shmTime {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int shm_initialise(RCL_Instance instance) {
|
static int shm_initialise(RCL_Instance instance) {
|
||||||
|
const char *options[] = {"perm", NULL};
|
||||||
int id, param, perm;
|
int id, param, perm;
|
||||||
char *s;
|
char *s;
|
||||||
struct shmTime *shm;
|
struct shmTime *shm;
|
||||||
|
|
||||||
|
RCL_CheckDriverOptions(instance, options);
|
||||||
|
|
||||||
param = atoi(RCL_GetDriverParameter(instance));
|
param = atoi(RCL_GetDriverParameter(instance));
|
||||||
s = RCL_GetDriverOption(instance, "perm");
|
s = RCL_GetDriverOption(instance, "perm");
|
||||||
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
|
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ static int sock_initialise(RCL_Instance instance)
|
|||||||
int sockfd;
|
int sockfd;
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
|
RCL_CheckDriverOptions(instance, NULL);
|
||||||
|
|
||||||
path = RCL_GetDriverParameter(instance);
|
path = RCL_GetDriverParameter(instance);
|
||||||
|
|
||||||
s.sun_family = AF_UNIX;
|
s.sun_family = AF_UNIX;
|
||||||
|
|||||||
13
sys.c
13
sys.c
@@ -35,10 +35,13 @@
|
|||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
#include "sys_linux.h"
|
#include "sys_linux.h"
|
||||||
|
#include "sys_posix.h"
|
||||||
#elif defined(SOLARIS)
|
#elif defined(SOLARIS)
|
||||||
#include "sys_solaris.h"
|
#include "sys_solaris.h"
|
||||||
|
#include "sys_posix.h"
|
||||||
#elif defined(NETBSD) || defined(FREEBSD)
|
#elif defined(NETBSD) || defined(FREEBSD)
|
||||||
#include "sys_netbsd.h"
|
#include "sys_netbsd.h"
|
||||||
|
#include "sys_posix.h"
|
||||||
#elif defined(MACOSX)
|
#elif defined(MACOSX)
|
||||||
#include "sys_macosx.h"
|
#include "sys_macosx.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -124,10 +127,10 @@ void SYS_EnableSystemCallFilter(int level)
|
|||||||
|
|
||||||
void SYS_SetScheduler(int SchedPriority)
|
void SYS_SetScheduler(int SchedPriority)
|
||||||
{
|
{
|
||||||
#if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
|
#if defined(MACOSX)
|
||||||
SYS_Linux_SetScheduler(SchedPriority);
|
|
||||||
#elif defined(MACOSX)
|
|
||||||
SYS_MacOSX_SetScheduler(SchedPriority);
|
SYS_MacOSX_SetScheduler(SchedPriority);
|
||||||
|
#elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
|
||||||
|
SYS_Posix_SetScheduler(SchedPriority);
|
||||||
#else
|
#else
|
||||||
LOG_FATAL("scheduler priority setting not supported");
|
LOG_FATAL("scheduler priority setting not supported");
|
||||||
#endif
|
#endif
|
||||||
@@ -137,8 +140,8 @@ void SYS_SetScheduler(int SchedPriority)
|
|||||||
|
|
||||||
void SYS_LockMemory(void)
|
void SYS_LockMemory(void)
|
||||||
{
|
{
|
||||||
#if defined(LINUX) && defined(HAVE_MLOCKALL)
|
#if defined(HAVE_MLOCKALL)
|
||||||
SYS_Linux_MemLockAll(1);
|
SYS_Posix_MemLockAll();
|
||||||
#else
|
#else
|
||||||
LOG_FATAL("memory locking not supported");
|
LOG_FATAL("memory locking not supported");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
206
sys_linux.c
206
sys_linux.c
@@ -33,15 +33,6 @@
|
|||||||
|
|
||||||
#include <sys/utsname.h>
|
#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)
|
#if defined(FEAT_PHC) || defined(HAVE_LINUX_TIMESTAMPING)
|
||||||
#include <linux/ptp_clock.h>
|
#include <linux/ptp_clock.h>
|
||||||
#endif
|
#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(clone), SCMP_SYS(exit), SCMP_SYS(exit_group), SCMP_SYS(getpid),
|
||||||
SCMP_SYS(getrlimit), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigreturn),
|
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(rt_sigprocmask), SCMP_SYS(set_tid_address), SCMP_SYS(sigreturn),
|
||||||
SCMP_SYS(wait4),
|
SCMP_SYS(wait4), SCMP_SYS(waitpid),
|
||||||
/* Memory */
|
/* Memory */
|
||||||
SCMP_SYS(brk), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2),
|
SCMP_SYS(brk), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2),
|
||||||
SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(shmdt),
|
SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(shmdt),
|
||||||
/* Filesystem */
|
/* 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(fstat), SCMP_SYS(fstat64), SCMP_SYS(getdents), SCMP_SYS(getdents64),
|
||||||
SCMP_SYS(lseek), SCMP_SYS(rename), SCMP_SYS(stat), SCMP_SYS(stat64),
|
SCMP_SYS(lseek), SCMP_SYS(newfstatat), SCMP_SYS(rename), SCMP_SYS(renameat),
|
||||||
SCMP_SYS(statfs), SCMP_SYS(statfs64), SCMP_SYS(unlink),
|
SCMP_SYS(stat), SCMP_SYS(stat64), SCMP_SYS(statfs), SCMP_SYS(statfs64),
|
||||||
|
SCMP_SYS(unlink), SCMP_SYS(unlinkat),
|
||||||
/* Socket */
|
/* Socket */
|
||||||
SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
|
SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
|
||||||
SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
|
SCMP_SYS(recv), SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
|
||||||
SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
|
SCMP_SYS(send), SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
|
||||||
/* TODO: check socketcall arguments */
|
/* TODO: check socketcall arguments */
|
||||||
SCMP_SYS(socketcall),
|
SCMP_SYS(socketcall),
|
||||||
/* General I/O */
|
/* General I/O */
|
||||||
SCMP_SYS(_newselect), SCMP_SYS(close), SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(pipe),
|
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(pipe2), SCMP_SYS(poll), SCMP_SYS(ppoll), SCMP_SYS(pselect6), SCMP_SYS(read),
|
||||||
SCMP_SYS(set_robust_list), SCMP_SYS(write),
|
SCMP_SYS(futex), SCMP_SYS(select), SCMP_SYS(set_robust_list), SCMP_SYS(write),
|
||||||
/* Miscellaneous */
|
/* Miscellaneous */
|
||||||
SCMP_SYS(getrandom), SCMP_SYS(sysinfo), SCMP_SYS(uname),
|
SCMP_SYS(getrandom), SCMP_SYS(sysinfo), SCMP_SYS(uname),
|
||||||
};
|
};
|
||||||
@@ -544,6 +537,9 @@ SYS_Linux_EnableSystemCallFilter(int level)
|
|||||||
#ifdef PTP_PIN_SETFUNC
|
#ifdef PTP_PIN_SETFUNC
|
||||||
PTP_PIN_SETFUNC,
|
PTP_PIN_SETFUNC,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PTP_SYS_OFFSET_EXTENDED
|
||||||
|
PTP_SYS_OFFSET_EXTENDED,
|
||||||
|
#endif
|
||||||
#ifdef PTP_SYS_OFFSET_PRECISE
|
#ifdef PTP_SYS_OFFSET_PRECISE
|
||||||
PTP_SYS_OFFSET_PRECISE,
|
PTP_SYS_OFFSET_PRECISE,
|
||||||
#endif
|
#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
|
int
|
||||||
SYS_Linux_CheckKernelVersion(int req_major, int req_minor)
|
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
|
#define PHC_READINGS 10
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
|
process_phc_readings(struct timespec ts[][3], int n, double precision,
|
||||||
struct timespec *sys_ts, double *err)
|
struct timespec *phc_ts, struct timespec *sys_ts, double *err)
|
||||||
{
|
{
|
||||||
struct ptp_sys_offset sys_off;
|
double min_delay = 0.0, delays[PTP_MAX_SAMPLES], phc_sum, sys_sum, sys_prec;
|
||||||
struct timespec ts1, ts2, ts3, phc_tss[PHC_READINGS], sys_tss[PHC_READINGS];
|
int i, combined;
|
||||||
double min_delay = 0.0, delays[PHC_READINGS], phc_sum, sys_sum, sys_prec;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
/* Silence valgrind */
|
if (n > PTP_MAX_SAMPLES)
|
||||||
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;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < PHC_READINGS; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
ts1.tv_sec = sys_off.ts[i * 2].sec;
|
delays[i] = UTI_DiffTimespecsToDouble(&ts[i][2], &ts[i][0]);
|
||||||
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);
|
|
||||||
|
|
||||||
if (delays[i] < 0.0) {
|
if (delays[i] < 0.0) {
|
||||||
/* Step in the middle of a PHC reading? */
|
/* 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();
|
sys_prec = LCL_GetSysPrecisionAsQuantum();
|
||||||
|
|
||||||
/* Combine best readings */
|
/* 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))
|
if (delays[i] > min_delay + MAX(sys_prec, precision))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
phc_sum += UTI_DiffTimespecsToDouble(&phc_tss[i], &phc_tss[0]);
|
phc_sum += UTI_DiffTimespecsToDouble(&ts[i][1], &ts[0][1]);
|
||||||
sys_sum += UTI_DiffTimespecsToDouble(&sys_tss[i], &sys_tss[0]) + delays[i] / 2.0;
|
sys_sum += UTI_DiffTimespecsToDouble(&ts[i][0], &ts[0][0]) + delays[i] / 2.0;
|
||||||
n++;
|
combined++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(n);
|
assert(combined);
|
||||||
|
|
||||||
UTI_AddDoubleToTimespec(&phc_tss[0], phc_sum / n, phc_ts);
|
UTI_AddDoubleToTimespec(&ts[0][1], phc_sum / combined, phc_ts);
|
||||||
UTI_AddDoubleToTimespec(&sys_tss[0], sys_sum / n, sys_ts);
|
UTI_AddDoubleToTimespec(&ts[0][0], sys_sum / combined, sys_ts);
|
||||||
*err = MAX(min_delay / 2.0, precision);
|
*err = MAX(min_delay / 2.0, precision);
|
||||||
|
|
||||||
return 1;
|
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
|
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)) {
|
get_precise_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
|
||||||
*reading_mode = 2;
|
*reading_mode = 2;
|
||||||
return 1;
|
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) &&
|
} else if ((*reading_mode == 1 || !*reading_mode) &&
|
||||||
get_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
|
get_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
|
||||||
*reading_mode = 1;
|
*reading_mode = 1;
|
||||||
|
|||||||
@@ -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_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_CheckKernelVersion(int req_major, int req_minor);
|
||||||
|
|
||||||
extern int SYS_Linux_OpenPHC(const char *path, int phc_index);
|
extern int SYS_Linux_OpenPHC(const char *path, int phc_index);
|
||||||
|
|||||||
38
sys_macosx.c
38
sys_macosx.c
@@ -49,10 +49,8 @@
|
|||||||
#ifdef HAVE_MACOS_SYS_TIMEX
|
#ifdef HAVE_MACOS_SYS_TIMEX
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "sys_netbsd.h"
|
#include "sys_netbsd.h"
|
||||||
#include "sys_timex.h"
|
|
||||||
|
|
||||||
static int have_ntp_adjtime = 0;
|
static int have_ntp_adjtime = 0;
|
||||||
static int have_bad_adjtime = 0;
|
|
||||||
#endif
|
#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
|
void
|
||||||
SYS_MacOSX_Initialise(void)
|
SYS_MacOSX_Initialise(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_MACOS_SYS_TIMEX
|
#ifdef HAVE_MACOS_SYS_TIMEX
|
||||||
have_ntp_adjtime = (dlsym(RTLD_NEXT, "ntp_adjtime") != NULL);
|
have_ntp_adjtime = (dlsym(RTLD_NEXT, "ntp_adjtime") != NULL);
|
||||||
if (have_ntp_adjtime) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -505,11 +471,7 @@ SYS_MacOSX_Finalise(void)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_MACOS_SYS_TIMEX
|
#ifdef HAVE_MACOS_SYS_TIMEX
|
||||||
if (have_ntp_adjtime) {
|
if (have_ntp_adjtime) {
|
||||||
if (have_bad_adjtime) {
|
|
||||||
SYS_Timex_Finalise();
|
|
||||||
} else {
|
|
||||||
SYS_NetBSD_Finalise();
|
SYS_NetBSD_Finalise();
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
109
sys_posix.c
Normal file
109
sys_posix.c
Normal file
@@ -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 */
|
||||||
36
sys_posix.h
Normal file
36
sys_posix.h
Normal file
@@ -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 */
|
||||||
@@ -37,11 +37,10 @@
|
|||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <resolv.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ check_packet_interval || test_fail
|
|||||||
check_sync || test_fail
|
check_sync || test_fail
|
||||||
|
|
||||||
# The following tests need 64-bit time_t
|
# 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
|
for year in 1990 2090; do
|
||||||
export CLKNETSIM_START_DATE=$(date -d "Jan 1 00:00:00 UTC $year" +'%s')
|
export CLKNETSIM_START_DATE=$(date -d "Jan 1 00:00:00 UTC $year" +'%s')
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ EOF
|
|||||||
|
|
||||||
keys=4
|
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"
|
hashes="MD5 SHA1 SHA256 SHA384 SHA512"
|
||||||
else
|
else
|
||||||
hashes="MD5"
|
hashes="MD5"
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
. ./test.common
|
. ./test.common
|
||||||
test_start "SHM refclock"
|
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
|
servers=0
|
||||||
limit=1000
|
limit=1000
|
||||||
refclock_jitter=$jitter
|
refclock_jitter=$jitter
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
test_start "allow/deny directives"
|
test_start "allow/deny directives"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||||
|
|
||||||
limit=500
|
limit=500
|
||||||
|
|
||||||
# Note that start_client in clknetsim.bash always adds allow to the config
|
# Note that start_client in clknetsim.bash always adds allow to the config
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
test_start "chronyc"
|
test_start "chronyc"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_REFCLOCK 1' || test_skip
|
||||||
|
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||||
|
|
||||||
refclock_jitter=$jitter
|
refclock_jitter=$jitter
|
||||||
client_conf="
|
client_conf="
|
||||||
refclock SHM 0 noselect
|
refclock SHM 0 noselect
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
test_start "port and acquisitionport directives"
|
test_start "port and acquisitionport directives"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
check_source_selection || test_fail
|
check_source_selection || test_fail
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ./test.common
|
. ./test.common
|
||||||
|
|
||||||
test_start "leap second"
|
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')
|
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s')
|
||||||
|
|
||||||
leap=$[2 * 24 * 3600]
|
leap=$[2 * 24 * 3600]
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
test_start "cmdmon timestamps"
|
test_start "cmdmon timestamps"
|
||||||
|
|
||||||
# The following tests need 64-bit time_t
|
# 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
|
limit=2
|
||||||
client_server_options="noselect"
|
client_server_options="noselect"
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ./test.common
|
. ./test.common
|
||||||
|
|
||||||
test_start "smoothtime option"
|
test_start "smoothtime option"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_REFCLOCK 1' || test_skip
|
||||||
|
|
||||||
server_strata=2
|
server_strata=2
|
||||||
server_conf="smoothtime 400 0.001"
|
server_conf="smoothtime 400 0.001"
|
||||||
server_server_options="minpoll 8"
|
server_server_options="minpoll 8"
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
test_start "orphan option"
|
test_start "orphan option"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||||
|
|
||||||
server_strata=3
|
server_strata=3
|
||||||
server_conf="local stratum 5 orphan
|
server_conf="local stratum 5 orphan
|
||||||
server 192.168.123.1
|
server 192.168.123.1
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ./test.common
|
. ./test.common
|
||||||
|
|
||||||
test_start "tai option"
|
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')
|
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 31 2008 23:50:00' +'%s')
|
||||||
|
|
||||||
leap=$[10 * 60]
|
leap=$[10 * 60]
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
test_start "-x option"
|
test_start "-x option"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||||
|
|
||||||
wander=0.0
|
wander=0.0
|
||||||
time_offset=0.0
|
time_offset=0.0
|
||||||
freq_offset=0.0
|
freq_offset=0.0
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
test_start "hwtimestamp directive"
|
test_start "hwtimestamp directive"
|
||||||
|
|
||||||
|
check_config_h 'HAVE_LINUX_TIMESTAMPING 1' || test_skip
|
||||||
|
|
||||||
export CLKNETSIM_TIMESTAMPING=2
|
export CLKNETSIM_TIMESTAMPING=2
|
||||||
|
|
||||||
refclock_jitter=1e-8
|
refclock_jitter=1e-8
|
||||||
@@ -11,22 +13,25 @@ refclock_offset=10.0
|
|||||||
min_sync_time=4
|
min_sync_time=4
|
||||||
max_sync_time=20
|
max_sync_time=20
|
||||||
limit=200
|
limit=200
|
||||||
client_conf="hwtimestamp eth0"
|
server_conf="hwtimestamp eth0"
|
||||||
client_server_options="minpoll 0 maxpoll 0 minsamples 32"
|
client_server_options="minpoll 0 maxpoll 0 minsamples 32 xleave"
|
||||||
client_chronyd_options="-d"
|
client_chronyd_options="-d"
|
||||||
|
|
||||||
run_test || test_fail
|
for client_conf in "hwtimestamp eth0" "hwtimestamp eth0
|
||||||
check_chronyd_exit || test_fail
|
acquisitionport 123"; do
|
||||||
check_source_selection || test_fail
|
run_test || test_fail
|
||||||
check_sync || test_fail
|
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 samples" 190 200 || test_fail
|
||||||
check_log_messages "HW clock reset" 0 0 || test_fail
|
check_log_messages "HW clock reset" 0 0 || test_fail
|
||||||
check_log_messages "Received.*tss=1" 1 1 || test_fail
|
check_log_messages "Received.*tss=1" 1 1 || test_fail
|
||||||
check_log_messages "Received.*tss=2" 390 400 || test_fail
|
check_log_messages "Received.*tss=2" 390 400 || test_fail
|
||||||
check_log_messages "update_tx_timestamp.*Updated" 50 140 || test_fail
|
check_log_messages "update_tx_timestamp.*Updated" 50 140 || test_fail
|
||||||
check_log_messages "update_tx_timestamp.*Unacceptable" 50 140 || test_fail
|
check_log_messages "update_tx_timestamp.*Unacceptable" 50 140 || test_fail
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ./test.common
|
. ./test.common
|
||||||
|
|
||||||
test_start "log directive"
|
test_start "log directive"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_PHC 1' || test_skip
|
||||||
|
|
||||||
refclock_jitter=$jitter
|
refclock_jitter=$jitter
|
||||||
client_server_options="maxpoll 6"
|
client_server_options="maxpoll 6"
|
||||||
client_conf="refclock PHC /dev/ptp0 dpoll 4 poll 6 noselect
|
client_conf="refclock PHC /dev/ptp0 dpoll 4 poll 6 noselect
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ done
|
|||||||
test_start() {
|
test_start() {
|
||||||
rm -f tmp/*
|
rm -f tmp/*
|
||||||
echo "Testing $@:"
|
echo "Testing $@:"
|
||||||
|
|
||||||
|
check_config_h 'FEAT_NTP 1' || test_skip
|
||||||
}
|
}
|
||||||
|
|
||||||
test_pass() {
|
test_pass() {
|
||||||
@@ -211,6 +213,12 @@ get_chronyd_conf() {
|
|||||||
fi
|
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 if the clock was well synchronized
|
||||||
check_sync() {
|
check_sync() {
|
||||||
local i sync_time max_time_error max_freq_error ret=0
|
local i sync_time max_time_error max_freq_error ret=0
|
||||||
|
|||||||
13
test/system/001-minimal
Executable file
13
test/system/001-minimal
Executable file
@@ -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
|
||||||
13
test/system/002-extended
Executable file
13
test/system/002-extended
Executable file
@@ -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
|
||||||
15
test/system/003-memlock
Executable file
15
test/system/003-memlock
Executable file
@@ -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
|
||||||
15
test/system/004-priority
Executable file
15
test/system/004-priority
Executable file
@@ -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
|
||||||
17
test/system/005-scfilter
Executable file
17
test/system/005-scfilter
Executable file
@@ -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
|
||||||
17
test/system/006-privdrop
Executable file
17
test/system/006-privdrop
Executable file
@@ -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
|
||||||
69
test/system/007-cmdmon
Executable file
69
test/system/007-cmdmon
Executable file
@@ -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
|
||||||
30
test/system/100-clockupdate
Executable file
30
test/system/100-clockupdate
Executable file
@@ -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
|
||||||
19
test/system/101-rtc
Executable file
19
test/system/101-rtc
Executable file
@@ -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
|
||||||
28
test/system/102-hwtimestamp
Executable file
28
test/system/102-hwtimestamp
Executable file
@@ -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
|
||||||
19
test/system/103-refclock
Executable file
19
test/system/103-refclock
Executable file
@@ -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
|
||||||
19
test/system/104-systemdirs
Executable file
19
test/system/104-systemdirs
Executable file
@@ -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
|
||||||
64
test/system/run
Executable file
64
test/system/run
Executable file
@@ -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 ]
|
||||||
339
test/system/test.common
Normal file
339
test/system/test.common
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
#include <local.h>
|
#include <local.h>
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
#ifdef FEAT_NTP
|
||||||
|
|
||||||
static struct timespec current_time;
|
static struct timespec current_time;
|
||||||
static NTP_Receive_Buffer req_buffer, res_buffer;
|
static NTP_Receive_Buffer req_buffer, res_buffer;
|
||||||
static int req_length, res_length;
|
static int req_length, res_length;
|
||||||
@@ -332,10 +334,8 @@ test_unit(void)
|
|||||||
CPS_ParseNTPSourceAdd(source_line, &source);
|
CPS_ParseNTPSourceAdd(source_line, &source);
|
||||||
|
|
||||||
for (i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
if (random() % 2)
|
source.params.interleaved = random() % 2;
|
||||||
source.params.interleaved = 1;
|
source.params.authkey = random() % 2 ? get_random_key_id() : INACTIVE_AUTHKEY;
|
||||||
if (random() % 2)
|
|
||||||
source.params.authkey = get_random_key_id();
|
|
||||||
source.params.version = random() % 4 + 1;
|
source.params.version = random() % 4 + 1;
|
||||||
|
|
||||||
UTI_ZeroTimespec(¤t_time);
|
UTI_ZeroTimespec(¤t_time);
|
||||||
@@ -475,3 +475,11 @@ test_unit(void)
|
|||||||
CNF_Finalise();
|
CNF_Finalise();
|
||||||
HSH_Finalise();
|
HSH_Finalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
test_unit(void)
|
||||||
|
{
|
||||||
|
TEST_REQUIRE(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -18,10 +18,14 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
#ifdef FEAT_NTP
|
||||||
|
|
||||||
#include <ntp_sources.c>
|
#include <ntp_sources.c>
|
||||||
#include <conf.h>
|
#include <conf.h>
|
||||||
#include <ntp_io.h>
|
#include <ntp_io.h>
|
||||||
#include "test.h"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
test_unit(void)
|
test_unit(void)
|
||||||
@@ -98,3 +102,11 @@ test_unit(void)
|
|||||||
CNF_Finalise();
|
CNF_Finalise();
|
||||||
HSH_Finalise();
|
HSH_Finalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
test_unit(void)
|
||||||
|
{
|
||||||
|
TEST_REQUIRE(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <sysincl.h>
|
#include <sysincl.h>
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <localp.h>
|
#include <localp.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
@@ -32,6 +33,13 @@ TST_Fail(int line)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TST_Skip(int line)
|
||||||
|
{
|
||||||
|
printf("SKIP (on line %d)\n", line);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,16 @@ extern void test_unit(void);
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} 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_Fail(int line);
|
||||||
|
extern void TST_Skip(int line);
|
||||||
|
|
||||||
extern void TST_SuspendLogging(void);
|
extern void TST_SuspendLogging(void);
|
||||||
extern void TST_ResumeLogging(void);
|
extern void TST_ResumeLogging(void);
|
||||||
|
|||||||
95
util.c
95
util.c
@@ -1179,6 +1179,101 @@ UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static int
|
||||||
|
join_path(const char *basedir, const char *name, const char *suffix,
|
||||||
|
char *buffer, size_t length, LOG_Severity severity)
|
||||||
|
{
|
||||||
|
const char *sep;
|
||||||
|
|
||||||
|
if (!basedir) {
|
||||||
|
basedir = "";
|
||||||
|
sep = "";
|
||||||
|
} else {
|
||||||
|
sep = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!suffix)
|
||||||
|
suffix = "";
|
||||||
|
|
||||||
|
if (snprintf(buffer, length, "%s%s%s%s", basedir, sep, name, suffix) >= length) {
|
||||||
|
LOG(severity, "File path %s%s%s%s too long", basedir, sep, name, suffix);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
FILE *
|
||||||
|
UTI_OpenFile(const char *basedir, const char *name, const char *suffix,
|
||||||
|
char mode, mode_t perm)
|
||||||
|
{
|
||||||
|
const char *file_mode;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
LOG_Severity severity;
|
||||||
|
int fd, flags;
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
severity = mode >= 'A' && mode <= 'Z' ? LOGS_FATAL : LOGS_ERR;
|
||||||
|
|
||||||
|
if (!join_path(basedir, name, suffix, path, sizeof (path), severity))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
flags = O_RDONLY;
|
||||||
|
file_mode = "r";
|
||||||
|
if (severity != LOGS_FATAL)
|
||||||
|
severity = LOGS_DEBUG;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||||
|
file_mode = "w";
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||||
|
file_mode = "a";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
try_again:
|
||||||
|
fd = open(path, flags, perm);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
if (unlink(path) < 0) {
|
||||||
|
LOG(severity, "Could not remove %s : %s", path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DEBUG_LOG("Removed %s", path);
|
||||||
|
goto try_again;
|
||||||
|
}
|
||||||
|
LOG(severity, "Could not open %s : %s", path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTI_FdSetCloexec(fd);
|
||||||
|
|
||||||
|
file = fdopen(fd, file_mode);
|
||||||
|
if (!file) {
|
||||||
|
LOG(severity, "Could not open %s : %s", path, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG("Opened %s fd=%d mode=%c", path, fd, mode);
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
UTI_DropRoot(uid_t uid, gid_t gid)
|
UTI_DropRoot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
|
|||||||
11
util.h
11
util.h
@@ -176,6 +176,17 @@ extern int UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid
|
|||||||
permissions and its uid/gid must match the specified values. */
|
permissions and its uid/gid must match the specified values. */
|
||||||
extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid);
|
extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
|
/* Open a file. The full path of the file is constructed from the basedir
|
||||||
|
(may be NULL), '/' (if basedir is not NULL), name, and suffix (may be NULL).
|
||||||
|
Created files have specified permissions (umasked). Returns NULL on error.
|
||||||
|
The following modes are supported (if the mode is an uppercase character,
|
||||||
|
errors are fatal):
|
||||||
|
r/R - open an existing file for reading
|
||||||
|
w/W - open a new file for writing (remove existing file)
|
||||||
|
a/A - open an existing file for appending (create if does not exist) */
|
||||||
|
extern FILE *UTI_OpenFile(const char *basedir, const char *name, const char *suffix,
|
||||||
|
char mode, mode_t perm);
|
||||||
|
|
||||||
/* Set process user/group IDs and drop supplementary groups */
|
/* Set process user/group IDs and drop supplementary groups */
|
||||||
extern void UTI_DropRoot(uid_t uid, gid_t gid);
|
extern void UTI_DropRoot(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user