mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 14:05:08 -05:00
Compare commits
221 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01965d147a | ||
|
|
6a84126c28 | ||
|
|
32f8bec92d | ||
|
|
00a6394b48 | ||
|
|
ca5a791d09 | ||
|
|
6a9c756cf0 | ||
|
|
1714d3e8ae | ||
|
|
25b7d47b34 | ||
|
|
9e8b4bae11 | ||
|
|
a466395a19 | ||
|
|
a3cb3fc490 | ||
|
|
3396778061 | ||
|
|
01cef64070 | ||
|
|
a9bfaf9e54 | ||
|
|
cec7c44f61 | ||
|
|
38ac2b39ce | ||
|
|
967e358dbc | ||
|
|
60721d2cc1 | ||
|
|
b698184939 | ||
|
|
c6c833fb9c | ||
|
|
3eb43f4619 | ||
|
|
440c159217 | ||
|
|
b49dcfbef7 | ||
|
|
a4d9cfaaeb | ||
|
|
7b2430fc3c | ||
|
|
bd8be7133d | ||
|
|
692ef0549b | ||
|
|
d6fdae5f1d | ||
|
|
8feb37df2b | ||
|
|
1d2b481069 | ||
|
|
c062fa2fa9 | ||
|
|
f444561a10 | ||
|
|
046f219a0e | ||
|
|
3cd32ed660 | ||
|
|
4f172f6f9f | ||
|
|
22fc0a6846 | ||
|
|
71e596b443 | ||
|
|
98c245ed7b | ||
|
|
bf57222e96 | ||
|
|
c075c070f0 | ||
|
|
4bc6950632 | ||
|
|
bde279c093 | ||
|
|
4f6ab8ac93 | ||
|
|
d2d82e2e5f | ||
|
|
1b2510e4b2 | ||
|
|
e735be59a7 | ||
|
|
5190539ce1 | ||
|
|
5776eb35b6 | ||
|
|
f102acd423 | ||
|
|
06486f3162 | ||
|
|
1619453b2b | ||
|
|
5a40950ffd | ||
|
|
16eb18e797 | ||
|
|
7bf0684557 | ||
|
|
961c490436 | ||
|
|
d8b0a4a288 | ||
|
|
76d12ac136 | ||
|
|
434faeecb8 | ||
|
|
ea2858b323 | ||
|
|
3391d5f846 | ||
|
|
7d6de7afe6 | ||
|
|
67ce6bd279 | ||
|
|
770db1fe02 | ||
|
|
d73394dde1 | ||
|
|
eb0c7e33d2 | ||
|
|
b9cfdaf666 | ||
|
|
5039f959e0 | ||
|
|
b7a54f8cd8 | ||
|
|
7b6435b2b8 | ||
|
|
8854c00d48 | ||
|
|
c0867b58f5 | ||
|
|
05183748a8 | ||
|
|
e56154a687 | ||
|
|
e5784c1ca8 | ||
|
|
282a9c7d7c | ||
|
|
b11ca92ca6 | ||
|
|
49846b3e68 | ||
|
|
0887824324 | ||
|
|
fbe65f2c71 | ||
|
|
eb5a412bed | ||
|
|
0cc8f68754 | ||
|
|
7079ca2718 | ||
|
|
70ad0bc573 | ||
|
|
22345c5ddf | ||
|
|
28b0a23949 | ||
|
|
1b57a796b1 | ||
|
|
0abb470022 | ||
|
|
b7a4b84f0a | ||
|
|
794a1e6cfe | ||
|
|
7c4db99d44 | ||
|
|
30b6213910 | ||
|
|
b6a27df5b9 | ||
|
|
18d514d552 | ||
|
|
f1ed08abf0 | ||
|
|
6d42dd8603 | ||
|
|
e7100e106d | ||
|
|
6402350c83 | ||
|
|
236576c124 | ||
|
|
9a83cab2f8 | ||
|
|
92706b158e | ||
|
|
ad34b26955 | ||
|
|
12c434fdc0 | ||
|
|
9ceaef6479 | ||
|
|
abb56bded2 | ||
|
|
0bcd10560a | ||
|
|
46b7148f3b | ||
|
|
37732130e1 | ||
|
|
7a3b1414cd | ||
|
|
a4a21c1dca | ||
|
|
206e597b04 | ||
|
|
ceef8ad2d8 | ||
|
|
2d581a6a86 | ||
|
|
82f7fa3887 | ||
|
|
f88a01e8c7 | ||
|
|
ca8e03b785 | ||
|
|
15932c9d7b | ||
|
|
0fc0f906e1 | ||
|
|
7f58852ec0 | ||
|
|
85a9a53e69 | ||
|
|
aa0c0fc401 | ||
|
|
0e694e08fc | ||
|
|
c2ddcc9f36 | ||
|
|
7a7cf6a5ce | ||
|
|
c2f83bd8a4 | ||
|
|
1f0e6296c6 | ||
|
|
ab1f01bacd | ||
|
|
b9b896d8e7 | ||
|
|
6be54f366c | ||
|
|
802cdb3230 | ||
|
|
7e27880cb6 | ||
|
|
d3ad85aa43 | ||
|
|
59192fc695 | ||
|
|
9095b80c5b | ||
|
|
ed5b78bf09 | ||
|
|
d6aafa3f64 | ||
|
|
8de04a808d | ||
|
|
2a299233b3 | ||
|
|
64f83c8861 | ||
|
|
1009fe3d9c | ||
|
|
ba341fe81a | ||
|
|
36e8cb6530 | ||
|
|
273da62aec | ||
|
|
41788184a7 | ||
|
|
fb9c2c7dc8 | ||
|
|
43116be122 | ||
|
|
ee038d5de5 | ||
|
|
ea7fae5277 | ||
|
|
70b108ab69 | ||
|
|
08b152d6a2 | ||
|
|
83c6213c67 | ||
|
|
4253075a97 | ||
|
|
0abdc2a350 | ||
|
|
31669f343a | ||
|
|
438b881ab4 | ||
|
|
27863146a3 | ||
|
|
cd4b73612b | ||
|
|
3c217a9e37 | ||
|
|
cde3a003ea | ||
|
|
2c35f56612 | ||
|
|
4295db25d7 | ||
|
|
3c06e57f24 | ||
|
|
e949cf5967 | ||
|
|
4eeaf34295 | ||
|
|
2212a90698 | ||
|
|
dc52b61dad | ||
|
|
bbf4c3186b | ||
|
|
f72016a78e | ||
|
|
29b587a9c5 | ||
|
|
cec4f2b140 | ||
|
|
05278c3b4c | ||
|
|
1769b8ea0f | ||
|
|
5686bd87d7 | ||
|
|
1cda2db45d | ||
|
|
fdf9640349 | ||
|
|
8f2d5d99f1 | ||
|
|
61272e7ce8 | ||
|
|
88b76f49cc | ||
|
|
ad942e352d | ||
|
|
39c2bcd462 | ||
|
|
ae10664b24 | ||
|
|
074dac4195 | ||
|
|
a8239b865a | ||
|
|
f6a9c5c1b7 | ||
|
|
42774ee851 | ||
|
|
4e26f48781 | ||
|
|
aec97397e8 | ||
|
|
183a648d01 | ||
|
|
27f8ad7fd1 | ||
|
|
a79fbef21e | ||
|
|
565976acbe | ||
|
|
54bbd2b1c0 | ||
|
|
10b2b53aa7 | ||
|
|
e18ee0bb46 | ||
|
|
857d51ea8e | ||
|
|
ba85544611 | ||
|
|
293806d52d | ||
|
|
7f45eb7957 | ||
|
|
f0c48680fe | ||
|
|
78283dd822 | ||
|
|
bbdf708d1a | ||
|
|
08195d7e41 | ||
|
|
9ff0dbb7a4 | ||
|
|
6ba97f9161 | ||
|
|
4eca60e7dc | ||
|
|
2af6f8cf78 | ||
|
|
d9a84d24cf | ||
|
|
09ce631e21 | ||
|
|
f93f2a15af | ||
|
|
47839b7701 | ||
|
|
41e99afe54 | ||
|
|
80af04040a | ||
|
|
3caa1e2f71 | ||
|
|
ddbbe30b9e | ||
|
|
802a98e7fc | ||
|
|
bb21841659 | ||
|
|
3f9691baff | ||
|
|
f8db832491 | ||
|
|
c68a92ba80 | ||
|
|
e5cf4645fe | ||
|
|
fad97e12da | ||
|
|
2f6152a580 |
31
.gitignore
vendored
31
.gitignore
vendored
@@ -2,20 +2,23 @@
|
|||||||
.vimrc
|
.vimrc
|
||||||
*.o
|
*.o
|
||||||
*.swp
|
*.swp
|
||||||
RELEASES
|
*.dSYM
|
||||||
Makefile
|
*.DS_Store
|
||||||
chrony.conf.5
|
|
||||||
chrony.info
|
|
||||||
chrony.html
|
|
||||||
chrony.texi
|
|
||||||
chrony.txt
|
|
||||||
chronyc
|
|
||||||
chronyc.1
|
|
||||||
chronyd
|
|
||||||
chronyd.8
|
|
||||||
config.h
|
|
||||||
config.log
|
|
||||||
tags
|
tags
|
||||||
version.h
|
/RELEASES
|
||||||
|
/Makefile
|
||||||
|
/chrony.conf.5
|
||||||
|
/chrony.info
|
||||||
|
/chrony.html
|
||||||
|
/chrony.texi
|
||||||
|
/chrony.txt
|
||||||
|
/chronyc
|
||||||
|
/chronyc.1
|
||||||
|
/chronyd
|
||||||
|
/chronyd.8
|
||||||
|
/config.h
|
||||||
|
/config.log
|
||||||
|
/getdate.c
|
||||||
|
/version.h
|
||||||
/test/simulation/clknetsim
|
/test/simulation/clknetsim
|
||||||
/test/simulation/tmp
|
/test/simulation/tmp
|
||||||
|
|||||||
28
Makefile.in
28
Makefile.in
@@ -38,13 +38,13 @@ DESTDIR=
|
|||||||
|
|
||||||
HASH_OBJ = @HASH_OBJ@
|
HASH_OBJ = @HASH_OBJ@
|
||||||
|
|
||||||
OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o mkdirpp.o \
|
OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \
|
||||||
reference.o regress.o rtc.o sched.o sources.o sourcestats.o stubs.o \
|
reference.o regress.o rtc.o sched.o sources.o sourcestats.o stubs.o \
|
||||||
sys.o tempcomp.o util.o $(HASH_OBJ)
|
sys.o smooth.o tempcomp.o util.o $(HASH_OBJ)
|
||||||
|
|
||||||
EXTRA_OBJS=@EXTRA_OBJECTS@
|
EXTRA_OBJS=@EXTRA_OBJECTS@
|
||||||
|
|
||||||
CLI_OBJS = client.o nameserv.o getdate.o cmdparse.o \
|
CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \
|
||||||
pktlength.o util.o $(HASH_OBJ)
|
pktlength.o util.o $(HASH_OBJ)
|
||||||
|
|
||||||
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
|
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
|
||||||
@@ -73,14 +73,16 @@ $(HASH_OBJ) : $(patsubst %.o,%.c,$(HASH_OBJ))
|
|||||||
$(CC) $(CFLAGS) $(CPPFLAGS) @HASH_COMPILE@ -c $<
|
$(CC) $(CFLAGS) $(CPPFLAGS) @HASH_COMPILE@ -c $<
|
||||||
|
|
||||||
distclean : clean
|
distclean : clean
|
||||||
|
-rm -f .DS_Store
|
||||||
-rm -f Makefile
|
-rm -f Makefile
|
||||||
-rm -f chrony.conf.5 chrony.texi chronyc.1 chronyd.8
|
-rm -f chrony.conf.5 chrony.texi chronyc.1 chronyd.8
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
-rm -f *.o *.s chronyc chronyd core *~ chrony.info chrony.html chrony.txt
|
-rm -f *.o *.s chronyc chronyd core *~ chrony.info chrony.html chrony.txt
|
||||||
-rm -rf .deps
|
-rm -rf .deps
|
||||||
|
-rm -rf *.dSYM
|
||||||
|
|
||||||
getdate.c :
|
getdate.c : getdate.y
|
||||||
bison -o getdate.c getdate.y
|
bison -o getdate.c getdate.y
|
||||||
|
|
||||||
# This can be used to force regeneration of getdate.c
|
# This can be used to force regeneration of getdate.c
|
||||||
@@ -90,15 +92,13 @@ getdate :
|
|||||||
# For install, don't use the install command, because its switches
|
# For install, don't use the install command, because its switches
|
||||||
# seem to vary between systems.
|
# seem to vary between systems.
|
||||||
|
|
||||||
install: chronyd chronyc chrony.txt
|
install: chronyd chronyc
|
||||||
[ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR)
|
[ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR)
|
||||||
[ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR)
|
[ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR)
|
||||||
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
|
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
|
|
||||||
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
|
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
|
||||||
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
|
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
|
||||||
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
|
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||||
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
|
|
||||||
[ -d $(DESTDIR)$(CHRONYVARDIR) ] || mkdir -p $(DESTDIR)$(CHRONYVARDIR)
|
[ -d $(DESTDIR)$(CHRONYVARDIR) ] || mkdir -p $(DESTDIR)$(CHRONYVARDIR)
|
||||||
if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi
|
if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi
|
||||||
if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi
|
if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi
|
||||||
@@ -106,14 +106,6 @@ install: chronyd chronyc chrony.txt
|
|||||||
chmod 755 $(DESTDIR)$(SBINDIR)/chronyd
|
chmod 755 $(DESTDIR)$(SBINDIR)/chronyd
|
||||||
cp chronyc $(DESTDIR)$(BINDIR)/chronyc
|
cp chronyc $(DESTDIR)$(BINDIR)/chronyc
|
||||||
chmod 755 $(DESTDIR)$(BINDIR)/chronyc
|
chmod 755 $(DESTDIR)$(BINDIR)/chronyc
|
||||||
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
|
|
||||||
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
|
|
||||||
cp COPYING $(DESTDIR)$(DOCDIR)/COPYING
|
|
||||||
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
|
|
||||||
cp README $(DESTDIR)$(DOCDIR)/README
|
|
||||||
chmod 644 $(DESTDIR)$(DOCDIR)/README
|
|
||||||
cp chrony.1 $(DESTDIR)$(MANDIR)/man1
|
|
||||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1
|
|
||||||
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
|
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
|
||||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
|
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
|
||||||
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
|
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
|
||||||
@@ -152,6 +144,12 @@ chrony.html : chrony.texi
|
|||||||
chrony.info : chrony.texi
|
chrony.info : chrony.texi
|
||||||
makeinfo chrony.texi
|
makeinfo chrony.texi
|
||||||
|
|
||||||
|
Makefile : Makefile.in configure
|
||||||
|
@echo
|
||||||
|
@echo Makefile needs to be regenerated, run ./configure
|
||||||
|
@echo
|
||||||
|
@exit 1
|
||||||
|
|
||||||
.deps:
|
.deps:
|
||||||
@mkdir .deps
|
@mkdir .deps
|
||||||
|
|
||||||
|
|||||||
84
NEWS
84
NEWS
@@ -1,3 +1,64 @@
|
|||||||
|
New in version 2.2
|
||||||
|
==================
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
* Add support for configuration and monitoring over Unix domain socket
|
||||||
|
(accessible by root or chrony user when root privileges are dropped)
|
||||||
|
* Add support for system call filtering with seccomp on Linux (experimental)
|
||||||
|
* Add support for dropping root privileges on NetBSD
|
||||||
|
* Control frequency of system clock on FreeBSD, NetBSD, Solaris
|
||||||
|
* Add system leap second handling mode on FreeBSD, NetBSD, Solaris
|
||||||
|
* Add dynamic drift removal on Mac OS X
|
||||||
|
* Add support for setting real-time priority on Mac OS X
|
||||||
|
* Add maxdistance directive to limit source selection by root distance
|
||||||
|
* Add refresh command to get new addresses of NTP sources
|
||||||
|
* Allow wildcard patterns in include directive
|
||||||
|
* Restore time from driftfile with -s option if later than RTC time
|
||||||
|
* Add configure option to set default hwclockfile
|
||||||
|
* Add -d option to chronyc to enable debug messages
|
||||||
|
* Allow multiple addresses to be specified for chronyc with -h option
|
||||||
|
and reconnect when no valid reply is received
|
||||||
|
* Make check interval in waitsync command configurable
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
* Fix building on Solaris
|
||||||
|
* Restore time from driftfile with -s option if reading RTC failed
|
||||||
|
|
||||||
|
Removed features
|
||||||
|
----------------
|
||||||
|
* Drop support for authentication with command key (run-time configuration
|
||||||
|
is now allowed only for local users that can access the Unix domain socket)
|
||||||
|
|
||||||
|
New in version 2.1.1
|
||||||
|
====================
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
* Fix clock stepping by integer number of seconds on Linux
|
||||||
|
|
||||||
|
New in version 2.1
|
||||||
|
==================
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
* Add support for Mac OS X
|
||||||
|
* Try to replace unreachable and falseticker servers/peers specified
|
||||||
|
by name like pool sources
|
||||||
|
* Add leaponly option to smoothtime directive to allow synchronised
|
||||||
|
leap smear between multiple servers
|
||||||
|
* Use specific reference ID when smoothing served time
|
||||||
|
* Add smoothing command to report time smoothing status
|
||||||
|
* Add smoothtime command to activate or reset time smoothing
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
* Fix crash in source selection with preferred sources
|
||||||
|
* Fix resetting of time smoothing
|
||||||
|
* Include packet precision in peer dispersion
|
||||||
|
* Fix crash in chronyc on invalid command syntax
|
||||||
|
|
||||||
New in version 2.0
|
New in version 2.0
|
||||||
==================
|
==================
|
||||||
|
|
||||||
@@ -5,6 +66,8 @@ Enhancements
|
|||||||
------------
|
------------
|
||||||
* Update to NTP version 4 (RFC 5905)
|
* Update to NTP version 4 (RFC 5905)
|
||||||
* Add pool directive to specify pool of NTP servers
|
* Add pool directive to specify pool of NTP servers
|
||||||
|
* Add leapsecmode directive to select how to correct clock for leap second
|
||||||
|
* Add smoothtime directive to smooth served time and enable leap smear
|
||||||
* Add minsources directive to set required number of selectable sources
|
* Add minsources directive to set required number of selectable sources
|
||||||
* Add minsamples and maxsamples options for all sources
|
* Add minsamples and maxsamples options for all sources
|
||||||
* Add tempcomp configuration with list of points
|
* Add tempcomp configuration with list of points
|
||||||
@@ -13,8 +76,9 @@ Enhancements
|
|||||||
* Improve source selection
|
* Improve source selection
|
||||||
* Handle offline sources as unreachable
|
* Handle offline sources as unreachable
|
||||||
* Open NTP server port only when necessary (client access is allowed by
|
* Open NTP server port only when necessary (client access is allowed by
|
||||||
allow directive/command, peer or broadcast is configured)
|
allow directive/command or peer/broadcast is configured)
|
||||||
* Change default bindcmdaddress to loopback address
|
* Change default bindcmdaddress to loopback address
|
||||||
|
* Change default maxdelay to 3 seconds
|
||||||
* Change default stratumweight to 0.001
|
* Change default stratumweight to 0.001
|
||||||
* Update adjtimex synchronisation status
|
* Update adjtimex synchronisation status
|
||||||
* Use system headers for adjtimex
|
* Use system headers for adjtimex
|
||||||
@@ -25,9 +89,21 @@ Enhancements
|
|||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
---------
|
---------
|
||||||
* Fix accepting requests from configured sources when acquisitionport
|
* Add sanity checks for time and frequency offset
|
||||||
is equal to server port
|
* Don't report synchronised status during leap second
|
||||||
* Fix allocation of slots saving replies to authenticated commands
|
* Don't combine reference clocks with close NTP sources
|
||||||
|
* Fix accepting requests from configured sources
|
||||||
|
* Fix initial fallback drift setting
|
||||||
|
|
||||||
|
New in version 1.31.1
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Security fixes
|
||||||
|
--------------
|
||||||
|
* Protect authenticated symmetric NTP associations against DoS attacks
|
||||||
|
(CVE-2015-1853)
|
||||||
|
* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
|
||||||
|
* Fix initialization of reply slots for authenticated commands (CVE-2015-1822)
|
||||||
|
|
||||||
New in version 1.31
|
New in version 1.31
|
||||||
===================
|
===================
|
||||||
|
|||||||
90
README
90
README
@@ -3,67 +3,35 @@ This is the README for chrony.
|
|||||||
What is chrony?
|
What is chrony?
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Chrony is a pair of programs for maintaining the accuracy of computer
|
chrony is a versatile implementation of the Network Time Protocol (NTP).
|
||||||
clocks.
|
It can synchronize the system clock with NTP servers, reference clocks
|
||||||
|
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
|
||||||
|
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
|
||||||
|
a time service to other computers in the network.
|
||||||
|
|
||||||
chronyd is a (background) daemon program that can be started at boot
|
It is designed to perform well in a wide range of conditions, including
|
||||||
time. This does most of the work.
|
intermittent network connections, heavily congested networks, changing
|
||||||
|
temperatures (ordinary computer clocks are sensitive to temperature),
|
||||||
|
and systems that do not run continuosly, or run on a virtual machine.
|
||||||
|
|
||||||
chronyc is a command-line interface program which can be used to
|
Typical accuracy between two machines on a LAN is in tens, or a few
|
||||||
monitor chronyd's performance and to change various operating
|
hundreds, of microseconds; over the Internet, accuracy is typically
|
||||||
parameters whilst it is running.
|
within a few milliseconds. With a good hardware reference clock
|
||||||
|
sub-microsecond accuracy is possible.
|
||||||
chronyd's main function is to obtain measurements of the true (UTC)
|
|
||||||
time from one of several sources, and correct the system clock
|
|
||||||
accordingly. It also works out the rate at which the system clock
|
|
||||||
gains or loses time and uses this information to keep it accurate
|
|
||||||
between measurements from the reference.
|
|
||||||
|
|
||||||
The reference time can be derived from Network Time Protocol (NTP)
|
|
||||||
servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
|
|
||||||
The main source of information about the Network Time Protocol is
|
|
||||||
http://www.ntp.org.
|
|
||||||
|
|
||||||
It is designed so that it can work on computers which only have
|
|
||||||
intermittent access to reference sources, for example computers which
|
|
||||||
use a dial-up account to access the Internet or laptops. Of course, it
|
|
||||||
will work well on computers with permanent connections too.
|
|
||||||
|
|
||||||
In addition, on Linux it can monitor the system's real time clock
|
|
||||||
performance, so the system can maintain accurate time even across
|
|
||||||
reboots.
|
|
||||||
|
|
||||||
Typical accuracies available between 2 machines are
|
|
||||||
|
|
||||||
On an ethernet LAN : 100-200 microseconds, often much better
|
|
||||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
|
||||||
session to the next)
|
|
||||||
|
|
||||||
With a good reference clock the accuracy can reach one microsecond.
|
|
||||||
|
|
||||||
chronyd can also operate as an NTPv4 (RFC 5905) server, peer and broadcast
|
|
||||||
server.
|
|
||||||
|
|
||||||
|
Two programs are included in chrony, chronyd is a daemon that can be
|
||||||
|
started at boot time and chronyc is a command-line interface program
|
||||||
|
which can be used to monitor chronyd's performance and to change various
|
||||||
|
operating parameters whilst it is running.
|
||||||
|
|
||||||
What will chrony run on?
|
What will chrony run on?
|
||||||
========================
|
========================
|
||||||
|
|
||||||
Chrony can be successfully built and run on
|
The software is known to work on Linux, FreeBSD, NetBSD, Mac OS X and
|
||||||
|
Solaris. Closely related systems may work too. Any other system will
|
||||||
1. Linux 2.2.x, 2.3.x, 2.4.x, 2.6.x, 3.x
|
likely require a porting exercise. You would need to start from one
|
||||||
|
of the existing system-specific drivers and look into the quirks of
|
||||||
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
|
certain system calls and the kernel on your target system.
|
||||||
|
|
||||||
3. SunOS 4.1.4 (Sparc 2 and Sparc 20)
|
|
||||||
|
|
||||||
4. BSD/386 v1.1 has been reported to work using the SunOS 4.1 driver.
|
|
||||||
|
|
||||||
5. NetBSD.
|
|
||||||
|
|
||||||
Any other system will require a porting exercise. You would need to
|
|
||||||
start from one of the existing system-specific drivers and look into
|
|
||||||
the quirks of certain system calls and the kernel on your target
|
|
||||||
system.
|
|
||||||
|
|
||||||
How do I set it up?
|
How do I set it up?
|
||||||
===================
|
===================
|
||||||
@@ -116,6 +84,11 @@ chrony-dev-request@chrony.tuxfamily.org
|
|||||||
|
|
||||||
as applicable.
|
as applicable.
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
chrony is distributed under the GNU General Public License version 2.
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
======
|
======
|
||||||
@@ -155,6 +128,9 @@ Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
|||||||
Erik Bryer <ebryer@spots.ab.ca>
|
Erik Bryer <ebryer@spots.ab.ca>
|
||||||
Entries in contrib directory
|
Entries in contrib directory
|
||||||
|
|
||||||
|
Bryan Christianson <bryan@whatroute.net>
|
||||||
|
Support for Mac OS X
|
||||||
|
|
||||||
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
||||||
Fix install rule in Makefile if chronyd file is in use.
|
Fix install rule in Makefile if chronyd file is in use.
|
||||||
|
|
||||||
@@ -169,6 +145,9 @@ Alexander Gretencord <arutha@gmx.de>
|
|||||||
Changes to installation directory system to make it easier for
|
Changes to installation directory system to make it easier for
|
||||||
package builders.
|
package builders.
|
||||||
|
|
||||||
|
Andrew Griffiths <agriffit@redhat.com>
|
||||||
|
Patch to add support for seccomp filter
|
||||||
|
|
||||||
Walter Haidinger <walter.haidinger@gmx.at>
|
Walter Haidinger <walter.haidinger@gmx.at>
|
||||||
Providing me with login access to a Linux installation where v1.12
|
Providing me with login access to a Linux installation where v1.12
|
||||||
wouldn't compile, so I could develop the fixes for v1.13. Also, for
|
wouldn't compile, so I could develop the fixes for v1.13. Also, for
|
||||||
@@ -228,6 +207,9 @@ Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
|||||||
Frank Otto <sandwichmacher@web.de>
|
Frank Otto <sandwichmacher@web.de>
|
||||||
Handling arbitrary HZ values
|
Handling arbitrary HZ values
|
||||||
|
|
||||||
|
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
|
Patch to make chronyc use the readline library if available
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
|
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
|
||||||
* Copyright (C) Miroslav Lichvar 2009
|
* Copyright (C) Miroslav Lichvar 2009, 2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -199,7 +199,10 @@ set_subnet(TableNode *start_node,
|
|||||||
|
|
||||||
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
|
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
|
||||||
N = 1 << (NBITS-bits_to_go);
|
N = 1 << (NBITS-bits_to_go);
|
||||||
subnet = get_subnet(ip, bits_consumed);
|
|
||||||
|
subnet = get_subnet(ip, bits_consumed) & ~(N - 1);
|
||||||
|
assert(subnet + N <= TABLE_SIZE);
|
||||||
|
|
||||||
if (!(node->extended)) {
|
if (!(node->extended)) {
|
||||||
open_node(node);
|
open_node(node);
|
||||||
}
|
}
|
||||||
|
|||||||
12
array.c
12
array.c
@@ -44,6 +44,8 @@ ARR_CreateInstance(unsigned int elem_size)
|
|||||||
{
|
{
|
||||||
ARR_Instance array;
|
ARR_Instance array;
|
||||||
|
|
||||||
|
assert(elem_size > 0);
|
||||||
|
|
||||||
array = MallocNew(struct ARR_Instance_Record);
|
array = MallocNew(struct ARR_Instance_Record);
|
||||||
|
|
||||||
array->data = NULL;
|
array->data = NULL;
|
||||||
@@ -64,6 +66,9 @@ ARR_DestroyInstance(ARR_Instance array)
|
|||||||
static void
|
static void
|
||||||
realloc_array(ARR_Instance array, unsigned int min_size)
|
realloc_array(ARR_Instance array, unsigned int min_size)
|
||||||
{
|
{
|
||||||
|
size_t data_size;
|
||||||
|
|
||||||
|
assert(min_size <= 2 * min_size);
|
||||||
if (array->allocated >= min_size && array->allocated <= 2 * min_size)
|
if (array->allocated >= min_size && array->allocated <= 2 * min_size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -74,7 +79,10 @@ realloc_array(ARR_Instance array, unsigned int min_size)
|
|||||||
array->allocated = min_size;
|
array->allocated = min_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
array->data = Realloc(array->data, array->elem_size * array->allocated);
|
data_size = (size_t)array->elem_size * array->allocated;
|
||||||
|
assert(data_size / array->elem_size == array->allocated);
|
||||||
|
|
||||||
|
array->data = Realloc(array->data, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@@ -89,7 +97,7 @@ void *
|
|||||||
ARR_GetElement(ARR_Instance array, unsigned int index)
|
ARR_GetElement(ARR_Instance array, unsigned int index)
|
||||||
{
|
{
|
||||||
assert(index < array->used);
|
assert(index < array->used);
|
||||||
return (void *)((char *)array->data + index * array->elem_size);
|
return (void *)((char *)array->data + (size_t)index * array->elem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
|||||||
130
candm.h
130
candm.h
@@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include "sysincl.h"
|
#include "sysincl.h"
|
||||||
#include "addressing.h"
|
#include "addressing.h"
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
/* This is the default port to use for CANDM, if no alternative is
|
/* This is the default port to use for CANDM, if no alternative is
|
||||||
defined */
|
defined */
|
||||||
@@ -89,7 +88,10 @@
|
|||||||
#define REQ_RESELECT 48
|
#define REQ_RESELECT 48
|
||||||
#define REQ_RESELECTDISTANCE 49
|
#define REQ_RESELECTDISTANCE 49
|
||||||
#define REQ_MODIFY_MAKESTEP 50
|
#define REQ_MODIFY_MAKESTEP 50
|
||||||
#define N_REQUEST_TYPES 51
|
#define REQ_SMOOTHING 51
|
||||||
|
#define REQ_SMOOTHTIME 52
|
||||||
|
#define REQ_REFRESH 53
|
||||||
|
#define N_REQUEST_TYPES 54
|
||||||
|
|
||||||
/* Special utoken value used to log on with first exchange being the
|
/* Special utoken value used to log on with first exchange being the
|
||||||
password. (This time value has long since gone by) */
|
password. (This time value has long since gone by) */
|
||||||
@@ -116,6 +118,10 @@ typedef struct {
|
|||||||
pktlength.c, to get the number of bytes that ought to be
|
pktlength.c, to get the number of bytes that ought to be
|
||||||
transmitted for each packet type. */
|
transmitted for each packet type. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t EOR;
|
||||||
|
} REQ_Null;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr mask;
|
IPAddr mask;
|
||||||
IPAddr address;
|
IPAddr address;
|
||||||
@@ -215,19 +221,11 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_Manual;
|
} REQ_Manual;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_N_Sources;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t index;
|
int32_t index;
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_Source_Data;
|
} REQ_Source_Data;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_Rekey;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr ip;
|
IPAddr ip;
|
||||||
int32_t subnet_bits;
|
int32_t subnet_bits;
|
||||||
@@ -264,10 +262,6 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_Del_Source;
|
} REQ_Del_Source;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_WriteRtc;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Float dfreq;
|
Float dfreq;
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
@@ -279,32 +273,11 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_Doffset;
|
} REQ_Doffset;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_Tracking;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_Sourcestats;
|
} REQ_Sourcestats;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_RTCReport;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_TrimRTC;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_CycleLogs;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
IPAddr ip;
|
|
||||||
uint32_t bits_specd;
|
|
||||||
} REQ_SubnetsAccessed_Subnet;
|
|
||||||
|
|
||||||
/* This is based on the response size rather than the
|
/* This is based on the response size rather than the
|
||||||
request size */
|
request size */
|
||||||
#define MAX_CLIENT_ACCESSES 8
|
#define MAX_CLIENT_ACCESSES 8
|
||||||
@@ -315,32 +288,24 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_ClientAccessesByIndex;
|
} REQ_ClientAccessesByIndex;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_ManualList;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t index;
|
int32_t index;
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_ManualDelete;
|
} REQ_ManualDelete;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_MakeStep;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_Activity;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t EOR;
|
|
||||||
} REQ_Reselect;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Float distance;
|
Float distance;
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} REQ_ReselectDistance;
|
} REQ_ReselectDistance;
|
||||||
|
|
||||||
|
#define REQ_SMOOTHTIME_RESET 0
|
||||||
|
#define REQ_SMOOTHTIME_ACTIVATE 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t option;
|
||||||
|
int32_t EOR;
|
||||||
|
} REQ_SmoothTime;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
#define PKT_TYPE_CMD_REQUEST 1
|
#define PKT_TYPE_CMD_REQUEST 1
|
||||||
@@ -370,7 +335,9 @@ typedef struct {
|
|||||||
|
|
||||||
Version 6 : added padding to requests to prevent amplification attack,
|
Version 6 : added padding to requests to prevent amplification attack,
|
||||||
changed maximum number of samples in manual list to 16, new commands: modify
|
changed maximum number of samples in manual list to 16, new commands: modify
|
||||||
makestep
|
makestep, smoothing report, smoothtime command
|
||||||
|
|
||||||
|
Authentication was removed later in version 6.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTO_VERSION_NUMBER 6
|
#define PROTO_VERSION_NUMBER 6
|
||||||
@@ -399,10 +366,11 @@ typedef struct {
|
|||||||
(count up from zero for same sequence
|
(count up from zero for same sequence
|
||||||
number) */
|
number) */
|
||||||
uint32_t sequence; /* Client's sequence number */
|
uint32_t sequence; /* Client's sequence number */
|
||||||
uint32_t utoken; /* Unique token per incarnation of daemon */
|
uint32_t pad1;
|
||||||
uint32_t token; /* Command token (to prevent replay attack) */
|
uint32_t pad2;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
REQ_Null null;
|
||||||
REQ_Online online;
|
REQ_Online online;
|
||||||
REQ_Offline offline;
|
REQ_Offline offline;
|
||||||
REQ_Burst burst;
|
REQ_Burst burst;
|
||||||
@@ -420,39 +388,24 @@ typedef struct {
|
|||||||
REQ_Settime settime;
|
REQ_Settime settime;
|
||||||
REQ_Local local;
|
REQ_Local local;
|
||||||
REQ_Manual manual;
|
REQ_Manual manual;
|
||||||
REQ_N_Sources n_sources;
|
|
||||||
REQ_Source_Data source_data;
|
REQ_Source_Data source_data;
|
||||||
REQ_Rekey rekey;
|
|
||||||
REQ_Allow_Deny allow_deny;
|
REQ_Allow_Deny allow_deny;
|
||||||
REQ_Ac_Check ac_check;
|
REQ_Ac_Check ac_check;
|
||||||
REQ_NTP_Source ntp_source;
|
REQ_NTP_Source ntp_source;
|
||||||
REQ_Del_Source del_source;
|
REQ_Del_Source del_source;
|
||||||
REQ_WriteRtc writertc;
|
|
||||||
REQ_Dfreq dfreq;
|
REQ_Dfreq dfreq;
|
||||||
REQ_Doffset doffset;
|
REQ_Doffset doffset;
|
||||||
REQ_Tracking tracking;
|
|
||||||
REQ_Sourcestats sourcestats;
|
REQ_Sourcestats sourcestats;
|
||||||
REQ_RTCReport rtcreport;
|
|
||||||
REQ_TrimRTC trimrtc;
|
|
||||||
REQ_CycleLogs cyclelogs;
|
|
||||||
REQ_ClientAccessesByIndex client_accesses_by_index;
|
REQ_ClientAccessesByIndex client_accesses_by_index;
|
||||||
REQ_ManualList manual_list;
|
|
||||||
REQ_ManualDelete manual_delete;
|
REQ_ManualDelete manual_delete;
|
||||||
REQ_MakeStep make_step;
|
|
||||||
REQ_Activity activity;
|
|
||||||
REQ_Reselect reselect;
|
|
||||||
REQ_ReselectDistance reselect_distance;
|
REQ_ReselectDistance reselect_distance;
|
||||||
|
REQ_SmoothTime smoothtime;
|
||||||
} data; /* Command specific parameters */
|
} data; /* Command specific parameters */
|
||||||
|
|
||||||
/* The following fields only set the maximum size of the packet.
|
/* Padding used to prevent traffic amplification. It only defines the
|
||||||
There are no holes between them and the actual data. */
|
maximum size of the packet, there is no hole after the data field. */
|
||||||
|
|
||||||
/* Padding used to prevent traffic amplification */
|
|
||||||
uint8_t padding[MAX_PADDING_LENGTH];
|
uint8_t padding[MAX_PADDING_LENGTH];
|
||||||
|
|
||||||
/* Authentication data */
|
|
||||||
uint8_t auth[MAX_HASH_LENGTH];
|
|
||||||
|
|
||||||
} CMD_Request;
|
} CMD_Request;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -477,7 +430,8 @@ typedef struct {
|
|||||||
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
|
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
|
||||||
#define RPY_MANUAL_LIST 11
|
#define RPY_MANUAL_LIST 11
|
||||||
#define RPY_ACTIVITY 12
|
#define RPY_ACTIVITY 12
|
||||||
#define N_REPLY_TYPES 13
|
#define RPY_SMOOTHING 13
|
||||||
|
#define N_REPLY_TYPES 14
|
||||||
|
|
||||||
/* Status codes */
|
/* Status codes */
|
||||||
#define STT_SUCCESS 0
|
#define STT_SUCCESS 0
|
||||||
@@ -589,12 +543,6 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} RPY_ManualTimestamp;
|
} RPY_ManualTimestamp;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
IPAddr ip;
|
|
||||||
uint32_t bits_specd;
|
|
||||||
uint32_t bitmap[8];
|
|
||||||
} RPY_SubnetsAccessed_Subnet;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr ip;
|
IPAddr ip;
|
||||||
uint32_t client_hits;
|
uint32_t client_hits;
|
||||||
@@ -638,6 +586,19 @@ typedef struct {
|
|||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} RPY_Activity;
|
} RPY_Activity;
|
||||||
|
|
||||||
|
#define RPY_SMT_FLAG_ACTIVE 0x1
|
||||||
|
#define RPY_SMT_FLAG_LEAPONLY 0x2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t flags;
|
||||||
|
Float offset;
|
||||||
|
Float freq_ppm;
|
||||||
|
Float wander_ppm;
|
||||||
|
Float last_update_ago;
|
||||||
|
Float remaining_time;
|
||||||
|
int32_t EOR;
|
||||||
|
} RPY_Smoothing;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t pkt_type;
|
uint8_t pkt_type;
|
||||||
@@ -650,9 +611,9 @@ typedef struct {
|
|||||||
uint16_t pad2;
|
uint16_t pad2;
|
||||||
uint16_t pad3;
|
uint16_t pad3;
|
||||||
uint32_t sequence; /* Echo of client's sequence number */
|
uint32_t sequence; /* Echo of client's sequence number */
|
||||||
uint32_t utoken; /* Unique token per incarnation of daemon */
|
uint32_t pad4;
|
||||||
uint32_t token; /* New command token (only if command was successfully
|
uint32_t pad5;
|
||||||
authenticated) */
|
|
||||||
union {
|
union {
|
||||||
RPY_Null null;
|
RPY_Null null;
|
||||||
RPY_N_Sources n_sources;
|
RPY_N_Sources n_sources;
|
||||||
@@ -664,12 +625,9 @@ typedef struct {
|
|||||||
RPY_ClientAccessesByIndex client_accesses_by_index;
|
RPY_ClientAccessesByIndex client_accesses_by_index;
|
||||||
RPY_ManualList manual_list;
|
RPY_ManualList manual_list;
|
||||||
RPY_Activity activity;
|
RPY_Activity activity;
|
||||||
|
RPY_Smoothing smoothing;
|
||||||
} data; /* Reply specific parameters */
|
} data; /* Reply specific parameters */
|
||||||
|
|
||||||
/* authentication of the packet, there is no hole after the actual data
|
|
||||||
from the data union, this field only sets the maximum auth size */
|
|
||||||
uint8_t auth[MAX_HASH_LENGTH];
|
|
||||||
|
|
||||||
} CMD_Reply;
|
} CMD_Reply;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
72
chrony.1
72
chrony.1
@@ -1,72 +0,0 @@
|
|||||||
.TH CHRONY 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
|
|
||||||
.SH NAME
|
|
||||||
chrony \- programs for keeping computer clocks accurate
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
\fBchronyc\fR [\fIOPTIONS\fR]
|
|
||||||
|
|
||||||
\fBchronyd\fR [\fIOPTIONS\fR]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
\fBchrony\fR is a pair of programs for keeping computer clocks accurate.
|
|
||||||
\fIchronyd\fR is a background (daemon) program and \fIchronyc\fR is a
|
|
||||||
command-line interface to it. Time reference sources for chronyd can be
|
|
||||||
NTP servers, human (via keyboard and \fIchronyc\fR), or the computer's
|
|
||||||
real-time clock at boot time (Linux only). chronyd can determine the rate at
|
|
||||||
which the computer gains or loses time and compensate for it while no external
|
|
||||||
reference is present. Its use of NTP servers can be switched on and off
|
|
||||||
(through \fIchronyc\fR) to support computers with dial-up/intermittent access
|
|
||||||
to the Internet, and it can also act as an NTP server.
|
|
||||||
|
|
||||||
.SH USAGE
|
|
||||||
\fIchronyc\fR is a command-line interface program which can be used to
|
|
||||||
monitor \fIchronyd\fR's performance and to change various operating
|
|
||||||
parameters whilst it is running.
|
|
||||||
|
|
||||||
\fIchronyd\fR's main function is to obtain measurements of the true (UTC)
|
|
||||||
time from one of several sources, and correct the system clock
|
|
||||||
accordingly. It also works out the rate at which the system clock
|
|
||||||
gains or loses time and uses this information to keep it accurate
|
|
||||||
between measurements from the reference.
|
|
||||||
|
|
||||||
The reference time can be derived from either Network Time Protocol
|
|
||||||
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
|
|
||||||
The main source of information about the Network Time Protocol is
|
|
||||||
\fIhttp://www.ntp.org\fR.
|
|
||||||
|
|
||||||
It is designed so that it can work on computers which only have
|
|
||||||
intermittent access to reference sources, for example computers which
|
|
||||||
use a dial-up account to access the Internet or laptops. Of course, it
|
|
||||||
will work well on computers with permanent connections too.
|
|
||||||
|
|
||||||
In addition, on Linux it can monitor the system's real time clock
|
|
||||||
performance, so the system can maintain accurate time even across
|
|
||||||
reboots.
|
|
||||||
|
|
||||||
Typical accuracies available between 2 machines are
|
|
||||||
|
|
||||||
On an ethernet LAN : 100-200 microseconds, often much better
|
|
||||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
|
||||||
session to the next)
|
|
||||||
|
|
||||||
With a good reference clock the accuracy can reach one microsecond.
|
|
||||||
|
|
||||||
\fIchronyd\fR can also operate as an NTPv4 (RFC 5905) server, peer and
|
|
||||||
broadcast server.
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR chronyc(1),
|
|
||||||
.BR chrony.conf(5),
|
|
||||||
.BR chronyd(8)
|
|
||||||
|
|
||||||
.I http://chrony.tuxfamily.org/
|
|
||||||
|
|
||||||
.SH AUTHOR
|
|
||||||
Richard Curnow <rc@rc0.org.uk>
|
|
||||||
|
|
||||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
|
|
||||||
of "The Missing Man Pages Project". Please see
|
|
||||||
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
|
|
||||||
|
|
||||||
The complete chrony documentation is supplied in texinfo format.
|
|
||||||
|
|
||||||
@@ -34,25 +34,23 @@ useful configuration file would look something like
|
|||||||
server bar.example.net iburst
|
server bar.example.net iburst
|
||||||
server baz.example.net iburst
|
server baz.example.net iburst
|
||||||
driftfile @CHRONYVARDIR@/drift
|
driftfile @CHRONYVARDIR@/drift
|
||||||
makestep 10 3
|
makestep 1.0 3
|
||||||
rtcsync
|
rtcsync
|
||||||
.EE
|
.EE
|
||||||
|
|
||||||
When using a pool of NTP servers (one name is used for multiple servers which
|
When using a pool of NTP servers (one name is used for multiple servers which
|
||||||
may change over time), it's better to specify them with the `pool' directive
|
may change over time), it's better to specify them with the `pool' directive
|
||||||
instead of multiple `server' directives in order to allow \fIchronyd\fR to
|
instead of multiple `server' directives. The configuration file could in this
|
||||||
replace unreachable or bad servers automatically. The configuration file could
|
case look like
|
||||||
in this case look like
|
|
||||||
|
|
||||||
.EX
|
.EX
|
||||||
pool pool.ntp.org iburst
|
pool pool.ntp.org iburst
|
||||||
driftfile @CHRONYVARDIR@/drift
|
driftfile @CHRONYVARDIR@/drift
|
||||||
makestep 10 3
|
makestep 1.0 3
|
||||||
rtcsync
|
rtcsync
|
||||||
.EE
|
.EE
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR chrony(1),
|
|
||||||
.BR chronyc(1),
|
.BR chronyc(1),
|
||||||
.BR chronyd(8)
|
.BR chronyd(8)
|
||||||
|
|
||||||
|
|||||||
1205
chrony.texi.in
1205
chrony.texi.in
File diff suppressed because it is too large
Load Diff
17
chronyc.1.in
17
chronyc.1.in
@@ -24,7 +24,8 @@ A summary of the options supported by \fBchronyc\fR is included below.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR \fIhostname\fR
|
\fB\-h\fR \fIhostname\fR
|
||||||
specify hostname (default 127.0.0.1)
|
specify hostname or comma-separated list of addresses
|
||||||
|
(default @CHRONYSOCKDIR@/chronyd.sock,127.0.0.1,::1)
|
||||||
.TP
|
.TP
|
||||||
\fB\-p\fR \fIport-number\fR
|
\fB\-p\fR \fIport-number\fR
|
||||||
specify port-number
|
specify port-number
|
||||||
@@ -32,6 +33,9 @@ specify port-number
|
|||||||
\fB\-n\fR
|
\fB\-n\fR
|
||||||
display raw IP addresses (don't attempt to look up hostnames)
|
display raw IP addresses (don't attempt to look up hostnames)
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-d\fR
|
||||||
|
print debugging messages (if compiled with debugging support)
|
||||||
|
.TP
|
||||||
\fB\-4\fR
|
\fB\-4\fR
|
||||||
resolve hostnames only to IPv4 addresses
|
resolve hostnames only to IPv4 addresses
|
||||||
.TP
|
.TP
|
||||||
@@ -43,14 +47,10 @@ allow multiple commands to be specified on the command line. Each argument
|
|||||||
will be interpreted as a whole command.
|
will be interpreted as a whole command.
|
||||||
.TP
|
.TP
|
||||||
\fB\-f\fR \fIconf-file\fR
|
\fB\-f\fR \fIconf-file\fR
|
||||||
This option can be used to specify an alternate location for the
|
this option is ignored and is provided only for compatibility.
|
||||||
configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR). The configuration file is
|
|
||||||
needed for the \fB-a\fR option.
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-a\fR
|
\fB\-a\fR
|
||||||
With this option chronyc will try to authenticate automatically on
|
this option is ignored and is provided only for compatibility.
|
||||||
start. It will read the configuration file, read the command key from the
|
|
||||||
keyfile and run the authhash and password commands.
|
|
||||||
.TP
|
.TP
|
||||||
\fIcommand\fR
|
\fIcommand\fR
|
||||||
specify command. If no command is given, chronyc will read commands
|
specify command. If no command is given, chronyc will read commands
|
||||||
@@ -60,8 +60,7 @@ interactively.
|
|||||||
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
|
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR chronyd(8),
|
.BR chronyd(8)
|
||||||
.BR chrony(1)
|
|
||||||
|
|
||||||
.I http://chrony.tuxfamily.org/
|
.I http://chrony.tuxfamily.org/
|
||||||
|
|
||||||
|
|||||||
48
chronyd.8.in
48
chronyd.8.in
@@ -40,9 +40,11 @@ A summary of the options supported by \fBchronyd\fR is included below.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-P\fR \fIpriority\fR
|
\fB\-P\fR \fIpriority\fR
|
||||||
This option will select the SCHED_FIFO real-time scheduler at the specified
|
On Linux, this option will select the SCHED_FIFO real-time scheduler at the
|
||||||
priority (which must be between 0 and 100). This mode is supported only on
|
specified priority (which must be between 0 and 100). On Mac OS X, this
|
||||||
Linux.
|
option must have either a value of 0 (the default) to disable the thread
|
||||||
|
time constraint policy or 1 for the policy to be enabled. Other systems do not
|
||||||
|
support this option.
|
||||||
.TP
|
.TP
|
||||||
.B \-m
|
.B \-m
|
||||||
This option will lock chronyd into RAM so that it will never be paged out.
|
This option will lock chronyd into RAM so that it will never be paged out.
|
||||||
@@ -67,11 +69,9 @@ This option will reload sample histories for each of the servers being used.
|
|||||||
These histories are created by using the \fIdump\fR command in \fIchronyc\fR,
|
These histories are created by using the \fIdump\fR command in \fIchronyc\fR,
|
||||||
or by setting the \fIdumponexit\fR directive in the configuration file. This
|
or by setting the \fIdumponexit\fR directive in the configuration file. This
|
||||||
option is useful if you want to stop and restart \fBchronyd\fR briefly for any
|
option is useful if you want to stop and restart \fBchronyd\fR briefly for any
|
||||||
reason, e.g. to install a new version. However, it only makes sense on
|
reason, e.g. to install a new version. However, it should be used only on
|
||||||
systems where the kernel can maintain clock compensation whilst not under
|
systems where the kernel can maintain clock compensation whilst not under
|
||||||
\fBchronyd\fR's control. The only version where this happens so far is Linux.
|
\fBchronyd\fR's control (i.e. Linux, FreeBSD, NetBSD and Solaris).
|
||||||
On systems where this is not the case, e.g. Solaris and SunOS the option
|
|
||||||
should not be used.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-R
|
.B \-R
|
||||||
When this option is used, the \fIinitstepslew\fR directive and the
|
When this option is used, the \fIinitstepslew\fR directive and the
|
||||||
@@ -80,13 +80,9 @@ option is useful when restarting \fBchronyd\fR and can be used in conjunction
|
|||||||
with the \fB-r\fR option.
|
with the \fB-r\fR option.
|
||||||
.TP
|
.TP
|
||||||
.B \-s
|
.B \-s
|
||||||
This option will set the system clock from the computer's real-time
|
This option will set the system clock from the computer's real-time clock or
|
||||||
clock. This is analogous to supplying the \fI-s\fR flag to the
|
to the last modification time of the file specified by the \fIdriftfile\fR
|
||||||
\fI/sbin/hwclock\fR program during the Linux boot sequence.
|
directive. Real-time clocks are supported only on Linux.
|
||||||
|
|
||||||
Support for real-time clocks is limited at present - the criteria
|
|
||||||
are described in the section on the \fIrtcfile\fR directive in the
|
|
||||||
documentation supplied with the distribution.
|
|
||||||
|
|
||||||
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
|
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
|
||||||
to preserve the old samples after setting the system clock from
|
to preserve the old samples after setting the system clock from
|
||||||
@@ -97,16 +93,23 @@ not in use. For this to work well, it relies on \fBchronyd\fR having
|
|||||||
been able to determine accurate statistics for the difference
|
been able to determine accurate statistics for the difference
|
||||||
between the RTC and system clock last time the computer was on.
|
between the RTC and system clock last time the computer was on.
|
||||||
|
|
||||||
If \fBchronyd\fR doesn't support the RTC on your computer or there is no RTC
|
If the last modification time of the drift file is later than the current time
|
||||||
installed, the system clock will be set with this option forward to the time of
|
and the RTC time, the system time will be set to it to restore the time when
|
||||||
the last modification of the drift file (specified by the \fIdriftfile\fR
|
\fBchronyd\fR was previously stopped. This is useful on computers that have no
|
||||||
directive) to restore the system time at which \fBchronyd\fR was previously
|
RTC or the RTC is broken (e.g. it has no battery).
|
||||||
stopped.
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-u\fR \fIuser\fR
|
\fB\-u\fR \fIuser\fR
|
||||||
This option sets the name of the user to which will \fBchronyd\fR switch to
|
This option sets the name of the system user to which \fBchronyd\fR will switch
|
||||||
drop root privileges if compiled with Linux capabilities support (default
|
after start in order to drop root privileges. It overrides the \fBuser\fR
|
||||||
\fB@DEFAULT_USER@\fR).
|
directive (default \fB@DEFAULT_USER@\fR). It may be set to a non-root user
|
||||||
|
only when \fBchronyd\fR is compiled with support for Linux capabilities
|
||||||
|
(libcap) or on NetBSD with the \fB/dev/clockctl\fR device.
|
||||||
|
.TP
|
||||||
|
\fB\-F\fR \fIlevel\fR
|
||||||
|
This option configures a system call filter when \fBchronyd\fR is compiled with
|
||||||
|
support for the Linux secure computing (seccomp) facility. In level 1 the
|
||||||
|
process is killed when a forbidden system call is made, in level -1 the SYSSIG
|
||||||
|
signal is thrown instead and in level 0 the filter is disabled (default 0).
|
||||||
.TP
|
.TP
|
||||||
.B \-q
|
.B \-q
|
||||||
When run in this mode, chronyd will set the system clock once
|
When run in this mode, chronyd will set the system clock once
|
||||||
@@ -135,7 +138,6 @@ To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
|
|||||||
\fBchronyd\fR is documented in detail in the documentation supplied with the
|
\fBchronyd\fR is documented in detail in the documentation supplied with the
|
||||||
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR).
|
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR).
|
||||||
|
|
||||||
.BR chrony(1),
|
|
||||||
.BR chronyc(1),
|
.BR chronyc(1),
|
||||||
.BR chrony.conf(5),
|
.BR chrony.conf(5),
|
||||||
.BR hwclock(8),
|
.BR hwclock(8),
|
||||||
|
|||||||
60
clientlog.c
60
clientlog.c
@@ -263,25 +263,31 @@ find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static Node *
|
||||||
|
get_node(IPAddr *ip)
|
||||||
|
{
|
||||||
|
uint32_t ip6[4];
|
||||||
|
|
||||||
|
switch (ip->family) {
|
||||||
|
case IPADDR_INET4:
|
||||||
|
return (Node *)find_subnet(&top_subnet4, &ip->addr.in4, 1, 0);
|
||||||
|
case IPADDR_INET6:
|
||||||
|
split_ip6(ip, ip6);
|
||||||
|
return (Node *)find_subnet(&top_subnet6, ip6, 4, 0);
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
CLG_LogNTPClientAccess (IPAddr *client, time_t now)
|
CLG_LogNTPClientAccess (IPAddr *client, time_t now)
|
||||||
{
|
{
|
||||||
uint32_t ip6[4];
|
|
||||||
Node *node;
|
Node *node;
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
switch (client->family) {
|
node = get_node(client);
|
||||||
case IPADDR_INET4:
|
|
||||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
|
||||||
break;
|
|
||||||
case IPADDR_INET6:
|
|
||||||
split_ip6(client, ip6);
|
|
||||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -296,22 +302,10 @@ CLG_LogNTPClientAccess (IPAddr *client, time_t now)
|
|||||||
void
|
void
|
||||||
CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
|
CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
|
||||||
{
|
{
|
||||||
uint32_t ip6[4];
|
|
||||||
Node *node;
|
Node *node;
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
switch (client->family) {
|
node = get_node(client);
|
||||||
case IPADDR_INET4:
|
|
||||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
|
||||||
break;
|
|
||||||
case IPADDR_INET6:
|
|
||||||
split_ip6(client, ip6);
|
|
||||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -326,22 +320,10 @@ CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
|
|||||||
void
|
void
|
||||||
CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
|
CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
|
||||||
{
|
{
|
||||||
uint32_t ip6[4];
|
|
||||||
Node *node;
|
Node *node;
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
switch (client->family) {
|
node = get_node(client);
|
||||||
case IPADDR_INET4:
|
|
||||||
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
|
|
||||||
break;
|
|
||||||
case IPADDR_INET6:
|
|
||||||
split_ip6(client, ip6);
|
|
||||||
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
1
cmdmon.h
1
cmdmon.h
@@ -33,6 +33,7 @@ extern void CAM_Initialise(int family);
|
|||||||
|
|
||||||
extern void CAM_Finalise(void);
|
extern void CAM_Finalise(void);
|
||||||
|
|
||||||
|
extern void CAM_OpenUnixSocket(void);
|
||||||
extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
|
extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
|
||||||
extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
|
extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2013
|
* Copyright (C) Miroslav Lichvar 2013-2014
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
201
conf.c
201
conf.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -47,7 +47,6 @@
|
|||||||
|
|
||||||
static int parse_string(char *line, char **result);
|
static int parse_string(char *line, char **result);
|
||||||
static int parse_int(char *line, int *result);
|
static int parse_int(char *line, int *result);
|
||||||
static int parse_uint32(char *, uint32_t *result);
|
|
||||||
static int parse_double(char *line, double *result);
|
static int parse_double(char *line, double *result);
|
||||||
static int parse_null(char *line);
|
static int parse_null(char *line);
|
||||||
|
|
||||||
@@ -63,6 +62,7 @@ static void parse_deny(char *);
|
|||||||
static void parse_fallbackdrift(char *);
|
static void parse_fallbackdrift(char *);
|
||||||
static void parse_include(char *);
|
static void parse_include(char *);
|
||||||
static void parse_initstepslew(char *);
|
static void parse_initstepslew(char *);
|
||||||
|
static void parse_leapsecmode(char *);
|
||||||
static void parse_local(char *);
|
static void parse_local(char *);
|
||||||
static void parse_log(char *);
|
static void parse_log(char *);
|
||||||
static void parse_mailonchange(char *);
|
static void parse_mailonchange(char *);
|
||||||
@@ -72,25 +72,25 @@ static void parse_peer(char *);
|
|||||||
static void parse_pool(char *);
|
static void parse_pool(char *);
|
||||||
static void parse_refclock(char *);
|
static void parse_refclock(char *);
|
||||||
static void parse_server(char *);
|
static void parse_server(char *);
|
||||||
|
static void parse_smoothtime(char *);
|
||||||
static void parse_tempcomp(char *);
|
static void parse_tempcomp(char *);
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Configuration variables */
|
/* Configuration variables */
|
||||||
|
|
||||||
static int restarted = 0;
|
static int restarted = 0;
|
||||||
static int generate_command_key = 0;
|
|
||||||
static char *rtc_device;
|
static char *rtc_device;
|
||||||
static int acquisition_port = -1;
|
static int acquisition_port = -1;
|
||||||
static int ntp_port = 123;
|
static int ntp_port = 123;
|
||||||
static char *keys_file = NULL;
|
static char *keys_file = NULL;
|
||||||
static char *drift_file = NULL;
|
static char *drift_file = NULL;
|
||||||
static char *rtc_file = NULL;
|
static char *rtc_file = NULL;
|
||||||
static uint32_t command_key_id;
|
|
||||||
static double max_update_skew = 1000.0;
|
static double max_update_skew = 1000.0;
|
||||||
static double correction_time_ratio = 3.0;
|
static double correction_time_ratio = 3.0;
|
||||||
static double max_clock_error = 1.0; /* in ppm */
|
static double max_clock_error = 1.0; /* in ppm */
|
||||||
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
|
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
|
||||||
|
|
||||||
|
static double max_distance = 3.0;
|
||||||
static double reselect_distance = 1e-4;
|
static double reselect_distance = 1e-4;
|
||||||
static double stratum_weight = 1e-3;
|
static double stratum_weight = 1e-3;
|
||||||
static double combine_limit = 3.0;
|
static double combine_limit = 3.0;
|
||||||
@@ -124,7 +124,7 @@ static int enable_manual=0;
|
|||||||
static int rtc_on_utc = 0;
|
static int rtc_on_utc = 0;
|
||||||
|
|
||||||
/* Filename used to read the hwclock(8) LOCAL/UTC setting */
|
/* Filename used to read the hwclock(8) LOCAL/UTC setting */
|
||||||
static char *hwclock_file = NULL;
|
static char *hwclock_file;
|
||||||
|
|
||||||
/* Flag set if the RTC should be automatically synchronised by kernel */
|
/* Flag set if the RTC should be automatically synchronised by kernel */
|
||||||
static int rtc_sync = 0;
|
static int rtc_sync = 0;
|
||||||
@@ -180,10 +180,18 @@ static IPAddr bind_acq_address4, bind_acq_address6;
|
|||||||
the loopback address will be used */
|
the loopback address will be used */
|
||||||
static IPAddr bind_cmd_address4, bind_cmd_address6;
|
static IPAddr bind_cmd_address4, bind_cmd_address6;
|
||||||
|
|
||||||
|
/* Path to the Unix domain command socket. */
|
||||||
|
static char *bind_cmd_path;
|
||||||
|
|
||||||
/* Filename to use for storing pid of running chronyd, to prevent multiple
|
/* Filename to use for storing pid of running chronyd, to prevent multiple
|
||||||
* chronyds being started. */
|
* chronyds being started. */
|
||||||
static char *pidfile;
|
static char *pidfile;
|
||||||
|
|
||||||
|
/* Smoothing constants */
|
||||||
|
static double smooth_max_freq = 0.0; /* in ppm */
|
||||||
|
static double smooth_max_wander = 0.0; /* in ppm/s */
|
||||||
|
static int smooth_leap_only = 0;
|
||||||
|
|
||||||
/* Temperature sensor, update interval and compensation coefficients */
|
/* Temperature sensor, update interval and compensation coefficients */
|
||||||
static char *tempcomp_sensor_file = NULL;
|
static char *tempcomp_sensor_file = NULL;
|
||||||
static char *tempcomp_point_file = NULL;
|
static char *tempcomp_point_file = NULL;
|
||||||
@@ -193,6 +201,9 @@ static double tempcomp_T0, tempcomp_k0, tempcomp_k1, tempcomp_k2;
|
|||||||
static int sched_priority = 0;
|
static int sched_priority = 0;
|
||||||
static int lock_memory = 0;
|
static int lock_memory = 0;
|
||||||
|
|
||||||
|
/* Leap second handling mode */
|
||||||
|
static REF_LeapMode leapsec_mode = REF_LeapModeSystem;
|
||||||
|
|
||||||
/* Name of a system timezone containing leap seconds occuring at midnight */
|
/* Name of a system timezone containing leap seconds occuring at midnight */
|
||||||
static char *leapsec_tz = NULL;
|
static char *leapsec_tz = NULL;
|
||||||
|
|
||||||
@@ -310,8 +321,10 @@ CNF_Initialise(int r)
|
|||||||
|
|
||||||
dumpdir = Strdup(".");
|
dumpdir = Strdup(".");
|
||||||
logdir = Strdup(".");
|
logdir = Strdup(".");
|
||||||
|
bind_cmd_path = Strdup(DEFAULT_COMMAND_SOCKET);
|
||||||
pidfile = Strdup("/var/run/chronyd.pid");
|
pidfile = Strdup("/var/run/chronyd.pid");
|
||||||
rtc_device = Strdup("/dev/rtc");
|
rtc_device = Strdup("/dev/rtc");
|
||||||
|
hwclock_file = Strdup(DEFAULT_HWCLOCK_FILE);
|
||||||
user = Strdup(DEFAULT_USER);
|
user = Strdup(DEFAULT_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,6 +352,7 @@ CNF_Finalise(void)
|
|||||||
Free(keys_file);
|
Free(keys_file);
|
||||||
Free(leapsec_tz);
|
Free(leapsec_tz);
|
||||||
Free(logdir);
|
Free(logdir);
|
||||||
|
Free(bind_cmd_path);
|
||||||
Free(pidfile);
|
Free(pidfile);
|
||||||
Free(rtc_device);
|
Free(rtc_device);
|
||||||
Free(rtc_file);
|
Free(rtc_file);
|
||||||
@@ -360,10 +374,13 @@ CNF_ReadFile(const char *filename)
|
|||||||
|
|
||||||
in = fopen(filename, "r");
|
in = fopen(filename, "r");
|
||||||
if (!in) {
|
if (!in) {
|
||||||
LOG_FATAL(LOGF_Configure, "Could not open configuration file %s", filename);
|
LOG_FATAL(LOGF_Configure, "Could not open configuration file %s : %s",
|
||||||
|
filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_Configure, "Reading %s", filename);
|
||||||
|
|
||||||
for (i = 1; fgets(line, sizeof(line), in); i++) {
|
for (i = 1; fgets(line, sizeof(line), in); i++) {
|
||||||
CNF_ParseLine(filename, i, line);
|
CNF_ParseLine(filename, i, line);
|
||||||
}
|
}
|
||||||
@@ -416,8 +433,6 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_int(p, &cmd_port);
|
parse_int(p, &cmd_port);
|
||||||
} else if (!strcasecmp(command, "combinelimit")) {
|
} else if (!strcasecmp(command, "combinelimit")) {
|
||||||
parse_double(p, &combine_limit);
|
parse_double(p, &combine_limit);
|
||||||
} else if (!strcasecmp(command, "commandkey")) {
|
|
||||||
parse_uint32(p, &command_key_id);
|
|
||||||
} else if (!strcasecmp(command, "corrtimeratio")) {
|
} else if (!strcasecmp(command, "corrtimeratio")) {
|
||||||
parse_double(p, &correction_time_ratio);
|
parse_double(p, &correction_time_ratio);
|
||||||
} else if (!strcasecmp(command, "deny")) {
|
} else if (!strcasecmp(command, "deny")) {
|
||||||
@@ -430,8 +445,6 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
do_dump_on_exit = parse_null(p);
|
do_dump_on_exit = parse_null(p);
|
||||||
} else if (!strcasecmp(command, "fallbackdrift")) {
|
} else if (!strcasecmp(command, "fallbackdrift")) {
|
||||||
parse_fallbackdrift(p);
|
parse_fallbackdrift(p);
|
||||||
} else if (!strcasecmp(command, "generatecommandkey")) {
|
|
||||||
generate_command_key = parse_null(p);
|
|
||||||
} else if (!strcasecmp(command, "hwclockfile")) {
|
} else if (!strcasecmp(command, "hwclockfile")) {
|
||||||
parse_string(p, &hwclock_file);
|
parse_string(p, &hwclock_file);
|
||||||
} else if (!strcasecmp(command, "include")) {
|
} else if (!strcasecmp(command, "include")) {
|
||||||
@@ -440,12 +453,10 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_initstepslew(p);
|
parse_initstepslew(p);
|
||||||
} else if (!strcasecmp(command, "keyfile")) {
|
} else if (!strcasecmp(command, "keyfile")) {
|
||||||
parse_string(p, &keys_file);
|
parse_string(p, &keys_file);
|
||||||
|
} else if (!strcasecmp(command, "leapsecmode")) {
|
||||||
|
parse_leapsecmode(p);
|
||||||
} else if (!strcasecmp(command, "leapsectz")) {
|
} else if (!strcasecmp(command, "leapsectz")) {
|
||||||
parse_string(p, &leapsec_tz);
|
parse_string(p, &leapsec_tz);
|
||||||
} else if (!strcasecmp(command, "linux_freq_scale")) {
|
|
||||||
LOG(LOGS_WARN, LOGF_Configure, "%s directive is no longer supported", command);
|
|
||||||
} else if (!strcasecmp(command, "linux_hz")) {
|
|
||||||
LOG(LOGS_WARN, LOGF_Configure, "%s directive is no longer supported", command);
|
|
||||||
} else if (!strcasecmp(command, "local")) {
|
} else if (!strcasecmp(command, "local")) {
|
||||||
parse_local(p);
|
parse_local(p);
|
||||||
} else if (!strcasecmp(command, "lock_all")) {
|
} else if (!strcasecmp(command, "lock_all")) {
|
||||||
@@ -468,6 +479,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_maxchange(p);
|
parse_maxchange(p);
|
||||||
} else if (!strcasecmp(command, "maxclockerror")) {
|
} else if (!strcasecmp(command, "maxclockerror")) {
|
||||||
parse_double(p, &max_clock_error);
|
parse_double(p, &max_clock_error);
|
||||||
|
} else if (!strcasecmp(command, "maxdistance")) {
|
||||||
|
parse_double(p, &max_distance);
|
||||||
} else if (!strcasecmp(command, "maxsamples")) {
|
} else if (!strcasecmp(command, "maxsamples")) {
|
||||||
parse_int(p, &max_samples);
|
parse_int(p, &max_samples);
|
||||||
} else if (!strcasecmp(command, "maxslewrate")) {
|
} else if (!strcasecmp(command, "maxslewrate")) {
|
||||||
@@ -506,12 +519,19 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||||||
parse_int(p, &sched_priority);
|
parse_int(p, &sched_priority);
|
||||||
} else if (!strcasecmp(command, "server")) {
|
} else if (!strcasecmp(command, "server")) {
|
||||||
parse_server(p);
|
parse_server(p);
|
||||||
|
} else if (!strcasecmp(command, "smoothtime")) {
|
||||||
|
parse_smoothtime(p);
|
||||||
} else if (!strcasecmp(command, "stratumweight")) {
|
} else if (!strcasecmp(command, "stratumweight")) {
|
||||||
parse_double(p, &stratum_weight);
|
parse_double(p, &stratum_weight);
|
||||||
} else if (!strcasecmp(command, "tempcomp")) {
|
} else if (!strcasecmp(command, "tempcomp")) {
|
||||||
parse_tempcomp(p);
|
parse_tempcomp(p);
|
||||||
} else if (!strcasecmp(command, "user")) {
|
} else if (!strcasecmp(command, "user")) {
|
||||||
parse_string(p, &user);
|
parse_string(p, &user);
|
||||||
|
} else if (!strcasecmp(command, "commandkey") ||
|
||||||
|
!strcasecmp(command, "generatecommandkey") ||
|
||||||
|
!strcasecmp(command, "linux_freq_scale") ||
|
||||||
|
!strcasecmp(command, "linux_hz")) {
|
||||||
|
LOG(LOGS_WARN, LOGF_Configure, "%s directive is no longer supported", command);
|
||||||
} else {
|
} else {
|
||||||
other_parse_error("Invalid command");
|
other_parse_error("Invalid command");
|
||||||
}
|
}
|
||||||
@@ -543,19 +563,6 @@ parse_int(char *line, int *result)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static int
|
|
||||||
parse_uint32(char *line, uint32_t *result)
|
|
||||||
{
|
|
||||||
check_number_of_args(line, 1);
|
|
||||||
if (sscanf(line, "%"SCNu32, result) != 1) {
|
|
||||||
command_parse_error();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_double(char *line, double *result)
|
parse_double(char *line, double *result)
|
||||||
{
|
{
|
||||||
@@ -830,6 +837,23 @@ parse_initstepslew(char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_leapsecmode(char *line)
|
||||||
|
{
|
||||||
|
if (!strcasecmp(line, "system"))
|
||||||
|
leapsec_mode = REF_LeapModeSystem;
|
||||||
|
else if (!strcasecmp(line, "slew"))
|
||||||
|
leapsec_mode = REF_LeapModeSlew;
|
||||||
|
else if (!strcasecmp(line, "step"))
|
||||||
|
leapsec_mode = REF_LeapModeStep;
|
||||||
|
else if (!strcasecmp(line, "ignore"))
|
||||||
|
leapsec_mode = REF_LeapModeIgnore;
|
||||||
|
else
|
||||||
|
command_parse_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_clientloglimit(char *line)
|
parse_clientloglimit(char *line)
|
||||||
{
|
{
|
||||||
@@ -1082,7 +1106,14 @@ parse_bindcmdaddress(char *line)
|
|||||||
IPAddr ip;
|
IPAddr ip;
|
||||||
|
|
||||||
check_number_of_args(line, 1);
|
check_number_of_args(line, 1);
|
||||||
if (UTI_StringToIP(line, &ip)) {
|
|
||||||
|
/* Address starting with / is for the Unix domain socket */
|
||||||
|
if (line[0] == '/') {
|
||||||
|
parse_string(line, &bind_cmd_path);
|
||||||
|
/* / disables the socket */
|
||||||
|
if (!strcmp(bind_cmd_path, "/"))
|
||||||
|
bind_cmd_path[0] = '\0';
|
||||||
|
} else if (UTI_StringToIP(line, &ip)) {
|
||||||
if (ip.family == IPADDR_INET4)
|
if (ip.family == IPADDR_INET4)
|
||||||
bind_cmd_address4 = ip;
|
bind_cmd_address4 = ip;
|
||||||
else if (ip.family == IPADDR_INET6)
|
else if (ip.family == IPADDR_INET6)
|
||||||
@@ -1141,6 +1172,29 @@ parse_broadcast(char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_smoothtime(char *line)
|
||||||
|
{
|
||||||
|
if (get_number_of_args(line) != 3)
|
||||||
|
check_number_of_args(line, 2);
|
||||||
|
|
||||||
|
if (sscanf(line, "%lf %lf", &smooth_max_freq, &smooth_max_wander) != 2) {
|
||||||
|
smooth_max_freq = 0.0;
|
||||||
|
command_parse_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
line = CPS_SplitWord(CPS_SplitWord(line));
|
||||||
|
smooth_leap_only = 0;
|
||||||
|
|
||||||
|
if (*line) {
|
||||||
|
if (!strcasecmp(line, "leaponly"))
|
||||||
|
smooth_leap_only = 1;
|
||||||
|
else
|
||||||
|
command_parse_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
static void
|
static void
|
||||||
parse_tempcomp(char *line)
|
parse_tempcomp(char *line)
|
||||||
{
|
{
|
||||||
@@ -1186,8 +1240,47 @@ parse_tempcomp(char *line)
|
|||||||
static void
|
static void
|
||||||
parse_include(char *line)
|
parse_include(char *line)
|
||||||
{
|
{
|
||||||
|
glob_t gl;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
check_number_of_args(line, 1);
|
check_number_of_args(line, 1);
|
||||||
CNF_ReadFile(line);
|
|
||||||
|
if (glob(line, 0, NULL, &gl)) {
|
||||||
|
DEBUG_LOG(LOGF_Configure, "glob of %s failed", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < gl.gl_pathc; i++)
|
||||||
|
CNF_ReadFile(gl.gl_pathv[i]);
|
||||||
|
|
||||||
|
globfree(&gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
CNF_CreateDirs(uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
char *dir;
|
||||||
|
|
||||||
|
UTI_CreateDirAndParents(logdir, 0755, uid, gid);
|
||||||
|
UTI_CreateDirAndParents(dumpdir, 0755, uid, gid);
|
||||||
|
|
||||||
|
/* Create a directory for the Unix domain command socket */
|
||||||
|
if (bind_cmd_path[0]) {
|
||||||
|
dir = UTI_PathToDir(bind_cmd_path);
|
||||||
|
UTI_CreateDirAndParents(dir, 0770, uid, gid);
|
||||||
|
|
||||||
|
/* Check the permissions and owner/group in case the directory already
|
||||||
|
existed. It MUST NOT be accessible by others as permissions on Unix
|
||||||
|
domain sockets are ignored on some systems (e.g. Solaris). */
|
||||||
|
if (!UTI_CheckDirPermissions(dir, 0770, uid, gid)) {
|
||||||
|
LOG(LOGS_WARN, LOGF_Configure, "Disabled command socket %s", bind_cmd_path);
|
||||||
|
bind_cmd_path[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Free(dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -1395,22 +1488,6 @@ CNF_GetRtcDevice(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
uint32_t
|
|
||||||
CNF_GetCommandKey(void)
|
|
||||||
{
|
|
||||||
return command_key_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
int
|
|
||||||
CNF_GetGenerateCommandKey(void)
|
|
||||||
{
|
|
||||||
return generate_command_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CNF_GetDumpOnExit(void)
|
CNF_GetDumpOnExit(void)
|
||||||
{
|
{
|
||||||
@@ -1451,6 +1528,14 @@ CNF_GetMaxSlewRate(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
double
|
||||||
|
CNF_GetMaxDistance(void)
|
||||||
|
{
|
||||||
|
return max_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
double
|
double
|
||||||
CNF_GetReselectDistance(void)
|
CNF_GetReselectDistance(void)
|
||||||
{
|
{
|
||||||
@@ -1643,6 +1728,14 @@ CNF_GetBindAcquisitionAddress(int family, IPAddr *addr)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
char *
|
||||||
|
CNF_GetBindCommandPath(void)
|
||||||
|
{
|
||||||
|
return bind_cmd_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
CNF_GetBindCommandAddress(int family, IPAddr *addr)
|
CNF_GetBindCommandAddress(int family, IPAddr *addr)
|
||||||
{
|
{
|
||||||
@@ -1664,6 +1757,14 @@ CNF_GetPidFile(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
REF_LeapMode
|
||||||
|
CNF_GetLeapSecMode(void)
|
||||||
|
{
|
||||||
|
return leapsec_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
CNF_GetLeapSecTimezone(void)
|
CNF_GetLeapSecTimezone(void)
|
||||||
{
|
{
|
||||||
@@ -1688,6 +1789,16 @@ CNF_GetLockMemory(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only)
|
||||||
|
{
|
||||||
|
*max_freq = smooth_max_freq;
|
||||||
|
*max_wander = smooth_max_wander;
|
||||||
|
*leap_only = smooth_leap_only;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2)
|
CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2)
|
||||||
{
|
{
|
||||||
|
|||||||
9
conf.h
9
conf.h
@@ -29,6 +29,7 @@
|
|||||||
#define GOT_CONF_H
|
#define GOT_CONF_H
|
||||||
|
|
||||||
#include "addressing.h"
|
#include "addressing.h"
|
||||||
|
#include "reference.h"
|
||||||
|
|
||||||
extern void CNF_Initialise(int restarted);
|
extern void CNF_Initialise(int restarted);
|
||||||
extern void CNF_Finalise(void);
|
extern void CNF_Finalise(void);
|
||||||
@@ -38,6 +39,8 @@ extern char *CNF_GetRtcDevice(void);
|
|||||||
extern void CNF_ReadFile(const char *filename);
|
extern void CNF_ReadFile(const char *filename);
|
||||||
extern void CNF_ParseLine(const char *filename, int number, char *line);
|
extern void CNF_ParseLine(const char *filename, int number, char *line);
|
||||||
|
|
||||||
|
extern void CNF_CreateDirs(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
extern void CNF_AddInitSources(void);
|
extern void CNF_AddInitSources(void);
|
||||||
extern void CNF_AddSources(void);
|
extern void CNF_AddSources(void);
|
||||||
extern void CNF_AddBroadcasts(void);
|
extern void CNF_AddBroadcasts(void);
|
||||||
@@ -57,8 +60,6 @@ extern int CNF_GetLogRefclocks(void);
|
|||||||
extern int CNF_GetLogTempComp(void);
|
extern int CNF_GetLogTempComp(void);
|
||||||
extern char *CNF_GetKeysFile(void);
|
extern char *CNF_GetKeysFile(void);
|
||||||
extern char *CNF_GetRtcFile(void);
|
extern char *CNF_GetRtcFile(void);
|
||||||
extern uint32_t CNF_GetCommandKey(void);
|
|
||||||
extern int CNF_GetGenerateCommandKey(void);
|
|
||||||
extern int CNF_GetDumpOnExit(void);
|
extern int CNF_GetDumpOnExit(void);
|
||||||
extern int CNF_GetManualEnabled(void);
|
extern int CNF_GetManualEnabled(void);
|
||||||
extern int CNF_GetCommandPort(void);
|
extern int CNF_GetCommandPort(void);
|
||||||
@@ -74,7 +75,9 @@ extern void CNF_GetFallbackDrifts(int *min, int *max);
|
|||||||
extern void CNF_GetBindAddress(int family, IPAddr *addr);
|
extern void CNF_GetBindAddress(int family, IPAddr *addr);
|
||||||
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
|
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
|
||||||
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
|
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
|
||||||
|
extern char *CNF_GetBindCommandPath(void);
|
||||||
extern char *CNF_GetPidFile(void);
|
extern char *CNF_GetPidFile(void);
|
||||||
|
extern REF_LeapMode CNF_GetLeapSecMode(void);
|
||||||
extern char *CNF_GetLeapSecTimezone(void);
|
extern char *CNF_GetLeapSecTimezone(void);
|
||||||
|
|
||||||
/* Value returned in ppm, as read from file */
|
/* Value returned in ppm, as read from file */
|
||||||
@@ -83,6 +86,7 @@ extern double CNF_GetMaxClockError(void);
|
|||||||
extern double CNF_GetCorrectionTimeRatio(void);
|
extern double CNF_GetCorrectionTimeRatio(void);
|
||||||
extern double CNF_GetMaxSlewRate(void);
|
extern double CNF_GetMaxSlewRate(void);
|
||||||
|
|
||||||
|
extern double CNF_GetMaxDistance(void);
|
||||||
extern double CNF_GetReselectDistance(void);
|
extern double CNF_GetReselectDistance(void);
|
||||||
extern double CNF_GetStratumWeight(void);
|
extern double CNF_GetStratumWeight(void);
|
||||||
extern double CNF_GetCombineLimit(void);
|
extern double CNF_GetCombineLimit(void);
|
||||||
@@ -94,6 +98,7 @@ extern void CNF_SetupAccessRestrictions(void);
|
|||||||
extern int CNF_GetSchedPriority(void);
|
extern int CNF_GetSchedPriority(void);
|
||||||
extern int CNF_GetLockMemory(void);
|
extern int CNF_GetLockMemory(void);
|
||||||
|
|
||||||
|
extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
|
||||||
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);
|
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);
|
||||||
|
|
||||||
extern char *CNF_GetUser(void);
|
extern char *CNF_GetUser(void);
|
||||||
|
|||||||
205
configure
vendored
205
configure
vendored
@@ -4,32 +4,12 @@
|
|||||||
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
#
|
#
|
||||||
# Copyright (C) Richard P. Curnow 1997-2003
|
# Copyright (C) Richard P. Curnow 1997-2003
|
||||||
# Copyright (C) Miroslav Lichvar 2009, 2012-2014
|
# Copyright (C) Miroslav Lichvar 2009, 2012-2015
|
||||||
#
|
#
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
# This configure script determines the operating system type and version
|
# This configure script determines the operating system type and version
|
||||||
|
|
||||||
if [ "x${CC}" = "x" ]; then
|
|
||||||
MYCC="gcc"
|
|
||||||
else
|
|
||||||
MYCC="${CC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "x${CFLAGS}" = "x" ]; then
|
|
||||||
MYCFLAGS="-O2 -g"
|
|
||||||
else
|
|
||||||
MYCFLAGS="${CFLAGS}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
MYCPPFLAGS="${CPPFLAGS}"
|
|
||||||
|
|
||||||
if [ "x${MYCC}" = "xgcc" ]; then
|
|
||||||
MYCFLAGS="${MYCFLAGS} -Wmissing-prototypes -Wall"
|
|
||||||
fi
|
|
||||||
|
|
||||||
MYLDFLAGS="${LDFLAGS}"
|
|
||||||
|
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
# FUNCTIONS
|
# FUNCTIONS
|
||||||
|
|
||||||
@@ -41,7 +21,7 @@ test_code () {
|
|||||||
ldflags=$4
|
ldflags=$4
|
||||||
code=$5
|
code=$5
|
||||||
|
|
||||||
echo -n "Checking for $name : "
|
printf "%s" "Checking for $name : "
|
||||||
|
|
||||||
(
|
(
|
||||||
for h in $headers; do
|
for h in $headers; do
|
||||||
@@ -113,12 +93,16 @@ For better control, use the options below.
|
|||||||
--disable-pps Disable PPS refclock driver
|
--disable-pps Disable PPS refclock driver
|
||||||
--disable-ipv6 Disable IPv6 support
|
--disable-ipv6 Disable IPv6 support
|
||||||
--disable-rtc Don't include RTC even on Linux
|
--disable-rtc Don't include RTC even on Linux
|
||||||
--disable-linuxcaps Disable libcap (Linux capabilities) support
|
--disable-privdrop Disable support for dropping root privileges
|
||||||
|
--without-libcap Don't use libcap even if it is available
|
||||||
|
--disable-scfilter Disable support for system call filtering
|
||||||
|
--without-seccomp Don't use seccomp even if it is available
|
||||||
--disable-asyncdns Disable asynchronous name resolving
|
--disable-asyncdns Disable asynchronous name resolving
|
||||||
--disable-forcednsretry Don't retry on permanent DNS error
|
--disable-forcednsretry Don't retry on permanent DNS error
|
||||||
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
||||||
since 1970-01-01 [50*365 days ago]
|
since 1970-01-01 [50*365 days ago]
|
||||||
--with-user=USER Specify default chronyd user [root]
|
--with-user=USER Specify default chronyd user [root]
|
||||||
|
--with-hwclockfile=PATH Specify default path to hwclock(8) adjtime file
|
||||||
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
|
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
|
||||||
--enable-debug Enable debugging support
|
--enable-debug Enable debugging support
|
||||||
|
|
||||||
@@ -131,6 +115,7 @@ Fine tuning of the installation directories:
|
|||||||
--mandir=DIR man documentation [DATAROOTDIR/man]
|
--mandir=DIR man documentation [DATAROOTDIR/man]
|
||||||
--docdir=DIR documentation root [DATAROOTDIR/doc/chrony]
|
--docdir=DIR documentation root [DATAROOTDIR/doc/chrony]
|
||||||
--localstatedir=DIR modifiable single-machine data [/var]
|
--localstatedir=DIR modifiable single-machine data [/var]
|
||||||
|
--chronysockdir=DIR location for chrony sockets [LOCALSTATEDIR/run/chrony]
|
||||||
--chronyvardir=DIR location for chrony data [LOCALSTATEDIR/lib/chrony]
|
--chronyvardir=DIR location for chrony data [LOCALSTATEDIR/lib/chrony]
|
||||||
|
|
||||||
Overriding system detection when cross-compiling:
|
Overriding system detection when cross-compiling:
|
||||||
@@ -174,12 +159,12 @@ get_features () {
|
|||||||
ff=1
|
ff=1
|
||||||
for f; do
|
for f; do
|
||||||
if [ "$ff" = "0" ]; then
|
if [ "$ff" = "0" ]; then
|
||||||
echo -n " "
|
printf " "
|
||||||
fi
|
fi
|
||||||
if grep "define FEAT_$f" config.h > /dev/null; then
|
if grep "define FEAT_$f" config.h > /dev/null; then
|
||||||
echo -n "+$f"
|
printf "%s" "+$f"
|
||||||
else
|
else
|
||||||
echo -n "-$f"
|
printf "%s" "-$f"
|
||||||
fi
|
fi
|
||||||
ff=0
|
ff=0
|
||||||
done
|
done
|
||||||
@@ -213,7 +198,10 @@ try_tomcrypt=1
|
|||||||
feat_rtc=1
|
feat_rtc=1
|
||||||
try_rtc=0
|
try_rtc=0
|
||||||
feat_droproot=1
|
feat_droproot=1
|
||||||
try_libcap=0
|
try_libcap=-1
|
||||||
|
try_clockctl=0
|
||||||
|
feat_scfilter=1
|
||||||
|
try_seccomp=-1
|
||||||
readline_lib=""
|
readline_lib=""
|
||||||
readline_inc=""
|
readline_inc=""
|
||||||
ncurses_lib=""
|
ncurses_lib=""
|
||||||
@@ -227,6 +215,7 @@ feat_asyncdns=1
|
|||||||
feat_forcednsretry=1
|
feat_forcednsretry=1
|
||||||
ntp_era_split=""
|
ntp_era_split=""
|
||||||
default_user="root"
|
default_user="root"
|
||||||
|
default_hwclockfile=""
|
||||||
mail_program="/usr/lib/sendmail"
|
mail_program="/usr/lib/sendmail"
|
||||||
|
|
||||||
for option
|
for option
|
||||||
@@ -283,6 +272,9 @@ do
|
|||||||
--localstatedir=* )
|
--localstatedir=* )
|
||||||
SETLOCALSTATEDIR=`echo $option | sed -e 's/^.*=//;'`
|
SETLOCALSTATEDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||||
;;
|
;;
|
||||||
|
--chronysockdir=* )
|
||||||
|
SETCHRONYSOCKDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||||
|
;;
|
||||||
--chronyvardir=* )
|
--chronyvardir=* )
|
||||||
SETCHRONYVARDIR=`echo $option | sed -e 's/^.*=//;'`
|
SETCHRONYVARDIR=`echo $option | sed -e 's/^.*=//;'`
|
||||||
;;
|
;;
|
||||||
@@ -307,9 +299,18 @@ do
|
|||||||
--disable-pps)
|
--disable-pps)
|
||||||
feat_pps=0
|
feat_pps=0
|
||||||
;;
|
;;
|
||||||
--disable-linuxcaps)
|
--disable-privdrop)
|
||||||
feat_droproot=0
|
feat_droproot=0
|
||||||
;;
|
;;
|
||||||
|
--without-libcap|--disable-linuxcaps)
|
||||||
|
try_libcap=0
|
||||||
|
;;
|
||||||
|
--disable-scfilter)
|
||||||
|
feat_scfilter=0
|
||||||
|
;;
|
||||||
|
--without-seccomp)
|
||||||
|
try_seccomp=0
|
||||||
|
;;
|
||||||
--disable-asyncdns)
|
--disable-asyncdns)
|
||||||
feat_asyncdns=0
|
feat_asyncdns=0
|
||||||
;;
|
;;
|
||||||
@@ -322,6 +323,9 @@ do
|
|||||||
--with-user=* )
|
--with-user=* )
|
||||||
default_user=`echo $option | sed -e 's/^.*=//;'`
|
default_user=`echo $option | sed -e 's/^.*=//;'`
|
||||||
;;
|
;;
|
||||||
|
--with-hwclockfile=* )
|
||||||
|
default_hwclockfile=`echo $option | sed -e 's/^.*=//;'`
|
||||||
|
;;
|
||||||
--with-sendmail=* )
|
--with-sendmail=* )
|
||||||
mail_program=`echo $option | sed -e 's/^.*=//;'`
|
mail_program=`echo $option | sed -e 's/^.*=//;'`
|
||||||
;;
|
;;
|
||||||
@@ -356,71 +360,50 @@ rm -f config.h config.log
|
|||||||
|
|
||||||
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
|
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
|
||||||
|
|
||||||
case $SYSTEM in
|
case $OPERATINGSYSTEM in
|
||||||
SunOS-sun4* )
|
Linux)
|
||||||
case $VERSION in
|
EXTRA_OBJECTS="sys_generic.o sys_linux.o sys_timex.o"
|
||||||
4.* )
|
[ $try_libcap != "0" ] && try_libcap=1
|
||||||
EXTRA_OBJECTS="sys_sunos.o strerror.o"
|
|
||||||
EXTRA_LIBS="-lkvm"
|
|
||||||
add_def SUNOS
|
|
||||||
echo "Configuring for SunOS (" $SYSTEM "version" $VERSION ")"
|
|
||||||
;;
|
|
||||||
5.* )
|
|
||||||
EXTRA_OBJECTS="sys_solaris.o"
|
|
||||||
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
|
|
||||||
EXTRA_CLI_LIBS="-lsocket -lnsl"
|
|
||||||
add_def SOLARIS
|
|
||||||
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
Linux* )
|
|
||||||
EXTRA_OBJECTS="sys_generic.o sys_linux.o wrap_adjtimex.o"
|
|
||||||
try_libcap=1
|
|
||||||
try_rtc=1
|
try_rtc=1
|
||||||
|
[ $try_seccomp != "0" ] && try_seccomp=1
|
||||||
try_setsched=1
|
try_setsched=1
|
||||||
try_lockmem=1
|
try_lockmem=1
|
||||||
try_phc=1
|
try_phc=1
|
||||||
add_def LINUX
|
add_def LINUX
|
||||||
echo "Configuring for " $SYSTEM
|
echo "Configuring for " $SYSTEM
|
||||||
if [ "${MACHINE}" = "alpha" ]; then
|
|
||||||
echo "Enabling -mieee"
|
|
||||||
# FIXME: Should really test for GCC
|
|
||||||
MYCFLAGS="$MYCFLAGS -mieee"
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
BSD/386-i[3456]86|FreeBSD-i386|FreeBSD-amd64 )
|
FreeBSD)
|
||||||
# Antti Jrvinen <costello@iki.fi> reported that this system can
|
EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
|
||||||
# be supported with the SunOS 4.x driver files.
|
add_def FREEBSD
|
||||||
EXTRA_OBJECTS="sys_sunos.o strerror.o"
|
|
||||||
EXTRA_LIBS="-lkvm"
|
|
||||||
add_def SUNOS
|
|
||||||
echo "Configuring for $SYSTEM (using SunOS driver)"
|
|
||||||
;;
|
|
||||||
NetBSD-* )
|
|
||||||
EXTRA_OBJECTS="sys_netbsd.o"
|
|
||||||
EXTRA_LIBS="-lkvm"
|
|
||||||
SYSDEFS=""
|
|
||||||
echo "Configuring for $SYSTEM"
|
echo "Configuring for $SYSTEM"
|
||||||
;;
|
;;
|
||||||
SunOS-i86pc* )
|
NetBSD)
|
||||||
# Doug Woodward <dougw@whistler.com> reported that this configuration
|
EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
|
||||||
# works for Solaris 2.8 / SunOS 5.8 on x86 platforms
|
try_clockctl=1
|
||||||
EXTRA_OBJECTS="sys_solaris.o"
|
add_def NETBSD
|
||||||
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
|
echo "Configuring for $SYSTEM"
|
||||||
EXTRA_CLI_LIBS="-lsocket -lnsl"
|
;;
|
||||||
|
Darwin)
|
||||||
|
EXTRA_OBJECTS="sys_macosx.o"
|
||||||
|
EXTRA_LIBS="-lresolv"
|
||||||
|
EXTRA_CLI_LIBS="-lresolv"
|
||||||
|
add_def MACOSX
|
||||||
|
echo "Configuring for MacOS X (" $SYSTEM "MacOS X version" $VERSION ")"
|
||||||
|
;;
|
||||||
|
SunOS)
|
||||||
|
EXTRA_OBJECTS="sys_generic.o sys_solaris.o sys_timex.o"
|
||||||
|
EXTRA_LIBS="-lsocket -lnsl -lresolv"
|
||||||
|
EXTRA_CLI_LIBS="-lsocket -lnsl -lresolv"
|
||||||
add_def SOLARIS
|
add_def SOLARIS
|
||||||
|
# These are needed to have msg_control in struct msghdr
|
||||||
|
add_def __EXTENSIONS__
|
||||||
|
add_def _XOPEN_SOURCE 1
|
||||||
|
add_def _XOPEN_SOURCE_EXTENDED 1
|
||||||
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
|
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
|
||||||
;;
|
;;
|
||||||
CYGWIN32_NT-i[3456]86 )
|
|
||||||
EXTRA_OBJECTS="sys_winnt.o"
|
|
||||||
EXTRA_LIBS=""
|
|
||||||
add_def WINNT
|
|
||||||
echo "Configuring for Windows NT (Cygwin32)"
|
|
||||||
;;
|
|
||||||
* )
|
* )
|
||||||
echo "Sorry, I don't know how to build this software on your system."
|
echo "error: $SYSTEM is not supported (yet?)"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -453,6 +436,35 @@ if [ $feat_refclock = "1" ]; then
|
|||||||
EXTRA_OBJECTS="$EXTRA_OBJECTS refclock.o refclock_phc.o refclock_pps.o refclock_shm.o refclock_sock.o"
|
EXTRA_OBJECTS="$EXTRA_OBJECTS refclock.o refclock_phc.o refclock_pps.o refclock_shm.o refclock_sock.o"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MYCC="$CC"
|
||||||
|
MYCFLAGS="$CFLAGS"
|
||||||
|
MYCPPFLAGS="$CPPFLAGS"
|
||||||
|
MYLDFLAGS="$LDFLAGS"
|
||||||
|
|
||||||
|
if [ "x$MYCC" = "x" ]; then
|
||||||
|
MYCC=gcc
|
||||||
|
if ! test_code "$MYCC" '' '' '' ''; then
|
||||||
|
MYCC=cc
|
||||||
|
if ! test_code "$MYCC" '' '' '' ''; then
|
||||||
|
echo "error: no C compiler found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! test_code "$MYCC" '' '' '' ''; then
|
||||||
|
echo "error: C compiler $MYCC cannot create executables"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$MYCFLAGS" = "x" ]; then
|
||||||
|
MYCFLAGS="-O2 -g"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$MYCC" = "xgcc" ]; then
|
||||||
|
MYCFLAGS="$MYCFLAGS -Wmissing-prototypes -Wall"
|
||||||
|
fi
|
||||||
|
|
||||||
if test_code '64-bit time_t' 'time.h' '' '' '
|
if test_code '64-bit time_t' 'time.h' '' '' '
|
||||||
char x[sizeof(time_t) > 4 ? 1 : -1] = {0};
|
char x[sizeof(time_t) > 4 ? 1 : -1] = {0};
|
||||||
return x[0];'
|
return x[0];'
|
||||||
@@ -465,7 +477,7 @@ then
|
|||||||
else
|
else
|
||||||
split_seconds=`date '+%s'`
|
split_seconds=`date '+%s'`
|
||||||
if [ "x$split_seconds" = "" ]; then
|
if [ "x$split_seconds" = "" ]; then
|
||||||
echo "Could not get current time, --with-ntp-era option is needed"
|
echo "error: could not get current time, --with-ntp-era option is needed"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
split_days=$((50 * 365))
|
split_days=$((50 * 365))
|
||||||
@@ -494,7 +506,7 @@ else
|
|||||||
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
|
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
|
||||||
LIBS="-lm"
|
LIBS="-lm"
|
||||||
else
|
else
|
||||||
echo "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out"
|
echo "error: could not compile/link a program which uses sqrt(), log(), pow()"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -508,7 +520,7 @@ if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $feat_ipv6 = "1" ] && \
|
if [ $feat_ipv6 = "1" ] && \
|
||||||
test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' '' '
|
test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' "$EXTRA_LIBS" '
|
||||||
struct sockaddr_in6 n;
|
struct sockaddr_in6 n;
|
||||||
char p[100];
|
char p[100];
|
||||||
n.sin6_addr = in6addr_any;
|
n.sin6_addr = in6addr_any;
|
||||||
@@ -529,7 +541,7 @@ then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test_code 'getaddrinfo()' 'sys/types.h sys/socket.h netdb.h' '' '' \
|
if test_code 'getaddrinfo()' 'sys/types.h sys/socket.h netdb.h' '' "$EXTRA_LIBS" \
|
||||||
'return getaddrinfo(0, 0, 0, 0);'
|
'return getaddrinfo(0, 0, 0, 0);'
|
||||||
then
|
then
|
||||||
add_def HAVE_GETADDRINFO
|
add_def HAVE_GETADDRINFO
|
||||||
@@ -579,6 +591,20 @@ then
|
|||||||
EXTRA_LIBS="$EXTRA_LIBS -lcap"
|
EXTRA_LIBS="$EXTRA_LIBS -lcap"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $feat_droproot = "1" ] && [ $try_clockctl = "1" ] && \
|
||||||
|
test_code '<sys/clockctl.h>' 'sys/clockctl.h' '' '' ''
|
||||||
|
then
|
||||||
|
add_def FEAT_PRIVDROP
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $feat_scfilter = "1" ] && [ $try_seccomp = "1" ] && \
|
||||||
|
test_code seccomp 'seccomp.h' '' '-lseccomp' \
|
||||||
|
'seccomp_init(SCMP_ACT_KILL);'
|
||||||
|
then
|
||||||
|
add_def FEAT_SCFILTER
|
||||||
|
EXTRA_LIBS="$EXTRA_LIBS -lseccomp"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \
|
if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \
|
||||||
test_code '<linux/rtc.h>' 'sys/ioctl.h linux/rtc.h' '' '' \
|
test_code '<linux/rtc.h>' 'sys/ioctl.h linux/rtc.h' '' '' \
|
||||||
'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);'
|
'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);'
|
||||||
@@ -752,18 +778,25 @@ if [ "x$SETLOCALSTATEDIR" != "x" ]; then
|
|||||||
LOCALSTATEDIR=$SETLOCALSTATEDIR
|
LOCALSTATEDIR=$SETLOCALSTATEDIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
CHRONYSOCKDIR=${LOCALSTATEDIR}/run/chrony
|
||||||
|
if [ "x$SETCHRONYSOCKDIR" != "x" ]; then
|
||||||
|
CHRONYSOCKDIR=$SETCHRONYSOCKDIR
|
||||||
|
fi
|
||||||
|
|
||||||
CHRONYVARDIR=${LOCALSTATEDIR}/lib/chrony
|
CHRONYVARDIR=${LOCALSTATEDIR}/lib/chrony
|
||||||
if [ "x$SETCHRONYVARDIR" != "x" ]; then
|
if [ "x$SETCHRONYVARDIR" != "x" ]; then
|
||||||
CHRONYVARDIR=$SETCHRONYVARDIR
|
CHRONYVARDIR=$SETCHRONYVARDIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
add_def DEFAULT_CONF_FILE "\"$SYSCONFDIR/chrony.conf\""
|
add_def DEFAULT_CONF_FILE "\"$SYSCONFDIR/chrony.conf\""
|
||||||
|
add_def DEFAULT_HWCLOCK_FILE "\"$default_hwclockfile\""
|
||||||
add_def DEFAULT_USER "\"$default_user\""
|
add_def DEFAULT_USER "\"$default_user\""
|
||||||
|
add_def DEFAULT_COMMAND_SOCKET "\"$CHRONYSOCKDIR/chronyd.sock\""
|
||||||
add_def MAIL_PROGRAM "\"$mail_program\""
|
add_def MAIL_PROGRAM "\"$mail_program\""
|
||||||
|
|
||||||
common_features="`get_features ASYNCDNS IPV6 SECHASH`"
|
common_features="`get_features IPV6 DEBUG`"
|
||||||
chronyc_features="`get_features READLINE`"
|
chronyc_features="`get_features READLINE`"
|
||||||
chronyd_features="`get_features CMDMON NTP REFCLOCK RTC PRIVDROP DEBUG`"
|
chronyd_features="`get_features CMDMON NTP REFCLOCK RTC PRIVDROP SCFILTER SECHASH ASYNCDNS`"
|
||||||
add_def CHRONYC_FEATURES "\"$chronyc_features $common_features\""
|
add_def CHRONYC_FEATURES "\"$chronyc_features $common_features\""
|
||||||
add_def CHRONYD_FEATURES "\"$chronyd_features $common_features\""
|
add_def CHRONYD_FEATURES "\"$chronyd_features $common_features\""
|
||||||
echo "Features : $chronyd_features $chronyc_features $common_features"
|
echo "Features : $chronyd_features $chronyc_features $common_features"
|
||||||
@@ -795,7 +828,9 @@ do
|
|||||||
s%@MANDIR@%${MANDIR}%;\
|
s%@MANDIR@%${MANDIR}%;\
|
||||||
s%@INFODIR@%${INFODIR}%;\
|
s%@INFODIR@%${INFODIR}%;\
|
||||||
s%@LOCALSTATEDIR@%${LOCALSTATEDIR}%;\
|
s%@LOCALSTATEDIR@%${LOCALSTATEDIR}%;\
|
||||||
|
s%@CHRONYSOCKDIR@%${CHRONYSOCKDIR}%;\
|
||||||
s%@CHRONYVARDIR@%${CHRONYVARDIR}%;\
|
s%@CHRONYVARDIR@%${CHRONYVARDIR}%;\
|
||||||
|
s%@DEFAULT_HWCLOCK_FILE@%${default_hwclockfile}%;\
|
||||||
s%@DEFAULT_USER@%${default_user}%;"\
|
s%@DEFAULT_USER@%${default_user}%;"\
|
||||||
< ${f}.in > $f
|
< ${f}.in > $f
|
||||||
done
|
done
|
||||||
|
|||||||
103
contrib/bryan_christianson_1/README.txt
Normal file
103
contrib/bryan_christianson_1/README.txt
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
Notes for installing chrony on MacOS X
|
||||||
|
Author: Bryan Christianson (bryan@whatroute.net)
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
These files are for those admins/users who would prefer to install chrony
|
||||||
|
from the source distribution and are intended as guidelines rather than
|
||||||
|
being definitive. They can be edited with a plain text editor, such as
|
||||||
|
vi, emacs or your favourite IDE (xcode)
|
||||||
|
|
||||||
|
It is assumed you are comfortable with installing software from the
|
||||||
|
terminal command line and know how to use sudo to acquire root access.
|
||||||
|
|
||||||
|
If you are not familiar with the MacOS X command line then
|
||||||
|
please consider using ChronyControl from http://whatroute.net/chronycontrol.html
|
||||||
|
|
||||||
|
ChronyControl provides a gui wrapper for installing these files and sets the
|
||||||
|
necessary permissions on each file.
|
||||||
|
|
||||||
|
|
||||||
|
Install the chrony software
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
You will need xcode and the commandline additions to build and install chrony.
|
||||||
|
These can be obtained from Apple's website via the App Store.
|
||||||
|
|
||||||
|
cd to the chrony directory
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
chrony is now installed in default locations (/usr/local/sbin/chronyd,
|
||||||
|
/usr/local/bin/chronyc)
|
||||||
|
|
||||||
|
Create a chrony.conf file - see the chrony website for details
|
||||||
|
|
||||||
|
The support files here assume the following directives are specified in the
|
||||||
|
chrony.conf file
|
||||||
|
|
||||||
|
keyfile /etc/chrony.d/chrony.keys
|
||||||
|
driftfile /var/db/chrony/chrony.drift
|
||||||
|
bindcmdaddress /var/db/chrony/chronyd.sock
|
||||||
|
logdir /var/log/chrony
|
||||||
|
dumpdir /var/db/chrony
|
||||||
|
|
||||||
|
Install this file as /etc/chrony.d/chrony.conf and create
|
||||||
|
the directories specified in the above directives if they don't exist.
|
||||||
|
You will need root permissions to create the directories.
|
||||||
|
|
||||||
|
|
||||||
|
Running chronyd
|
||||||
|
---------------
|
||||||
|
At this point chronyd *could* be run as a daemon. Apple discourage running
|
||||||
|
daemons and their preferred method uses the launchd facility. The
|
||||||
|
support files here provide a launchd configuration file for chronyd and also
|
||||||
|
a shell script and launchd configuration file to rotate the chronyd logs on a daily basis.
|
||||||
|
|
||||||
|
|
||||||
|
Support files
|
||||||
|
-------------
|
||||||
|
Dates and sizes may differ
|
||||||
|
-rw-r--r-- 1 yourname staff 2084 4 Aug 22:54 README.txt
|
||||||
|
-rwxr-xr-x 1 yourname staff 676 4 Aug 21:18 chronylogrotate.sh
|
||||||
|
-rw-r--r-- 1 yourname staff 543 18 Jul 20:10 org.tuxfamily.chronyc.plist
|
||||||
|
-rw-r--r-- 1 yourname staff 511 19 Jun 18:30 org.tuxfamily.chronyd.plist
|
||||||
|
|
||||||
|
If you have used chrony support directories other than those suggested, you
|
||||||
|
will need to edit each file and make the appropriate changes.
|
||||||
|
|
||||||
|
|
||||||
|
Installing the support files
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
1. chronylogrotate.sh
|
||||||
|
This is a simple shell script that deletes old log files. Unfortunately because
|
||||||
|
of the need to run chronyc, the standard MacOS X logrotation does not work with
|
||||||
|
chrony logs.
|
||||||
|
|
||||||
|
This script runs on a daily basis under control of launchd and should be
|
||||||
|
installed in the /usr/local/bin directory
|
||||||
|
|
||||||
|
sudo cp chronylogrotate.sh /usr/local/bin
|
||||||
|
sudo chmod +x /usr/local/bin/chronylogrotate.sh
|
||||||
|
sudo chown root:wheel /usr/local/bin/chronylogrotate.sh
|
||||||
|
|
||||||
|
|
||||||
|
2. org.tuxfamily.chronyc.plist
|
||||||
|
This file is the launchd plist that runs logrotation each day. You may
|
||||||
|
wish to edit this file to change the time of day at which the rotation
|
||||||
|
will run, currently 04:05 am
|
||||||
|
|
||||||
|
sudo cp org.tuxfamily.chronyc.plist /Library/LaunchDaemons
|
||||||
|
sudo chown root:wheel /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||||
|
sudo chmod 0644 /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||||
|
sudo launchctl load -w /Library/LaunchDaemons/org.tuxfamily.chronyc.plist
|
||||||
|
|
||||||
|
|
||||||
|
3. org.tuxfamily.chronyd.plist
|
||||||
|
This file is the launchd plist that runs chronyd when the Macintosh starts.
|
||||||
|
|
||||||
|
sudo cp org.tuxfamily.chronyd.plist /Library/LaunchDaemons
|
||||||
|
sudo chown root:wheel /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||||
|
sudo chmod 0644 /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||||
|
sudo launchctl load -w /Library/LaunchDaemons/org.tuxfamily.chronyd.plist
|
||||||
45
contrib/bryan_christianson_1/chronylogrotate.sh
Executable file
45
contrib/bryan_christianson_1/chronylogrotate.sh
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# chronylogrotate.sh
|
||||||
|
# ChronyControl
|
||||||
|
#
|
||||||
|
# Created by Bryan Christianson on 12/07/15.
|
||||||
|
#
|
||||||
|
|
||||||
|
LOGDIR=/var/log/chrony
|
||||||
|
|
||||||
|
if [ ! -e "$LOGDIR" ]; then
|
||||||
|
echo "missing directory: $LOGDIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $LOGDIR
|
||||||
|
|
||||||
|
rotate () {
|
||||||
|
prefix=$1
|
||||||
|
|
||||||
|
rm -f $prefix.log.10
|
||||||
|
|
||||||
|
for (( count=9; count>= 0; count-- ))
|
||||||
|
do
|
||||||
|
next=$(( $count+1 ))
|
||||||
|
if [ -f $prefix.log.$count ]; then
|
||||||
|
mv $prefix.log.$count $prefix.log.$next
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -f $prefix.log ]; then
|
||||||
|
mv $prefix.log $prefix.log.0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate measurements
|
||||||
|
rotate statistics
|
||||||
|
rotate tracking
|
||||||
|
|
||||||
|
#
|
||||||
|
# signal chronyd via chronyc
|
||||||
|
|
||||||
|
/usr/local/bin/chronyc -a -f /etc/chrony.d/chrony.conf cyclelogs > /dev/null
|
||||||
|
|
||||||
|
exit $?
|
||||||
22
contrib/bryan_christianson_1/org.tuxfamily.chronyc.plist
Normal file
22
contrib/bryan_christianson_1/org.tuxfamily.chronyc.plist
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>org.tuxfamily.logrotate</string>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<false/>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/bin/sh</string>
|
||||||
|
<string>/usr/local/bin/chronylogrotate.sh</string>
|
||||||
|
</array>
|
||||||
|
<key>StartCalendarInterval</key>
|
||||||
|
<dict>
|
||||||
|
<key>Minute</key>
|
||||||
|
<integer>5</integer>
|
||||||
|
<key>Hour</key>
|
||||||
|
<integer>4</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
19
contrib/bryan_christianson_1/org.tuxfamily.chronyd.plist
Normal file
19
contrib/bryan_christianson_1/org.tuxfamily.chronyd.plist
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>org.tuxfamily.chronyd</string>
|
||||||
|
<key>Program</key>
|
||||||
|
<string>/usr/local/sbin/chronyd</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>chronyd</string>
|
||||||
|
<string>-n</string>
|
||||||
|
<string>-f</string>
|
||||||
|
<string>/private/etc/chrony.d/chrony.conf</string>
|
||||||
|
</array>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
341
doc/faq.adoc
Normal file
341
doc/faq.adoc
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
:toc:
|
||||||
|
:numbered:
|
||||||
|
|
||||||
|
Frequently Asked Questions
|
||||||
|
==========================
|
||||||
|
|
||||||
|
== +chrony+ compared to other programs
|
||||||
|
|
||||||
|
=== How does +chrony+ compare to +ntpd+?
|
||||||
|
|
||||||
|
+chronyd+ was designed to work well in a wide range of conditions and it can
|
||||||
|
usually synchronise the system clock faster and with better time accuracy. It
|
||||||
|
doesn't implement some of the less useful NTP modes like broadcast client or
|
||||||
|
multicast server/client.
|
||||||
|
|
||||||
|
For a more detailed comparison of features and performance, see the
|
||||||
|
http://chrony.tuxfamily.org/comparison.html[comparison page] on the +chrony+
|
||||||
|
website and the
|
||||||
|
http://chrony.tuxfamily.org/manual.html#Comparison-with-ntpd[Comparison with
|
||||||
|
ntpd] section in the manual.
|
||||||
|
|
||||||
|
If your computer is connected to the internet only for few minutes at a time,
|
||||||
|
the network connection is often congested, you turn your computer off or
|
||||||
|
suspend it frequently, the clock is not very stable (e.g. there are rapid
|
||||||
|
changes in the temperature or it's a virtual machine), or you want to use NTP
|
||||||
|
on an isolated network with no hardware reference clocks in sight, +chrony+
|
||||||
|
will probably work much better for you.
|
||||||
|
|
||||||
|
The original reason +chrony+ was written was that +ntpd+ (called +xntpd+ at the
|
||||||
|
time) could not to do anything sensible on a PC which was connected to the 'net
|
||||||
|
only for about 5 minutes once or twice a day, mainly to upload/download email
|
||||||
|
and news. The requirements were
|
||||||
|
|
||||||
|
* slew the time to correct it when going online and NTP servers
|
||||||
|
become visible
|
||||||
|
* determine the rate at which the computer gains or loses time and
|
||||||
|
use this information to keep it reasonably correct between connects
|
||||||
|
to the 'net. This has to be done using a method that does not care
|
||||||
|
about the intermittent availability of the references or the fact
|
||||||
|
the computer is turned off between groups of measurements.
|
||||||
|
* maintain the time across reboots, by working out the error and
|
||||||
|
drift rate of the computer's real-time clock and using this
|
||||||
|
information to set the system clock correctly at boot up.
|
||||||
|
|
||||||
|
Also, when working with isolated networks with no true time references at all
|
||||||
|
+ntpd+ was found to give no help with managing the local clock's gain/loss rate
|
||||||
|
on the NTP master node (which was set from watch). Some automated support was
|
||||||
|
added to +chrony+ to deal with this.
|
||||||
|
|
||||||
|
== Configuration issues
|
||||||
|
|
||||||
|
=== I have several computers on a LAN. Should be all clients of an external server?
|
||||||
|
|
||||||
|
The best configuration is usually to make one computer the master, with
|
||||||
|
the others as clients of it. Add a +local+ directive to the master's
|
||||||
|
'chrony.conf' file. This configuration will be better because
|
||||||
|
|
||||||
|
* the load on the external connection is less
|
||||||
|
* the load on the external NTP server(s) is less
|
||||||
|
* if your external connection goes down, the computers on the LAN
|
||||||
|
will maintain a common time with each other.
|
||||||
|
|
||||||
|
=== Must I specify servers by IP address if DNS is not available on chronyd start?
|
||||||
|
|
||||||
|
No. Starting from version 1.25, +chronyd+ will keep trying to resolve
|
||||||
|
the hostnames specified in the +server+ and +peer+ directives in
|
||||||
|
increasing intervals until it succeeds. The +online+ command can be
|
||||||
|
issued from +chronyc+ to try to resolve them immediately.
|
||||||
|
|
||||||
|
=== How can I make +chronyd+ more secure?
|
||||||
|
|
||||||
|
If you don't need to serve time to NTP clients or peers, you can add +port 0+
|
||||||
|
to the 'chrony.conf' file to completely disable the NTP server functionality
|
||||||
|
and prevent NTP requests from reaching +chronyd+. Starting from version 2.0,
|
||||||
|
the NTP server port is open only when client access is allowed by the +allow+
|
||||||
|
directive or command, an NTP peer is configured, or the +broadcast+ directive
|
||||||
|
is used.
|
||||||
|
|
||||||
|
If you don't need to use +chronyc+ remotely, you can add the following
|
||||||
|
directives to the configuration file to bind the command sockets to the
|
||||||
|
loopback interface. This is done by default since version 2.0.
|
||||||
|
|
||||||
|
----
|
||||||
|
bindcmdaddress 127.0.0.1
|
||||||
|
bindcmdaddress ::1
|
||||||
|
----
|
||||||
|
|
||||||
|
If you don't need to use +chronyc+ at all or you need to run +chronyc+ only
|
||||||
|
under the root or chrony user (which can access +chronyd+ through a Unix domain
|
||||||
|
socket since version 2.2), you can disable the internet command sockets
|
||||||
|
completely by adding +cmdport 0+ to the configuration file.
|
||||||
|
|
||||||
|
On Linux, if +chronyd+ is compiled with support for Linux capabilities
|
||||||
|
(available in the libcap library), or on NetBSD with the +/dev/clockctl+
|
||||||
|
device, you can specify an unprivileged user with the +-u+ option or +user+
|
||||||
|
directive in the 'chrony.conf' file to drop root privileges after start. The
|
||||||
|
configure option +--with-user+ can be used to drop the privileges by default.
|
||||||
|
|
||||||
|
Also, if +chronyd+ is compiled with support for the Linux secure computing
|
||||||
|
(seccomp) facility, you can enable a system call filter with the +-F+ option.
|
||||||
|
It will significantly reduce the kernel attack surface and possibly prevent
|
||||||
|
kernel exploits from the +chronyd+ process if compromised. The filter
|
||||||
|
shouldn't be enabled without testing that it allows all system calls needed
|
||||||
|
with the specific configuration and libraries that +chronyd+ is using (e.g.
|
||||||
|
libc and its NSS configuration). If +chronyd+ is getting killed, some system
|
||||||
|
call is missing and the filter has to be disabled until it's patched to allow
|
||||||
|
that call.
|
||||||
|
|
||||||
|
=== How can I improve the accuracy of the system clock with NTP sources?
|
||||||
|
|
||||||
|
Select NTP servers that are well synchronised, stable and close to your
|
||||||
|
network. It's better to use more than one server, three or four is usually
|
||||||
|
recommended as the minimum, so +chronyd+ can detect falsetickers and combine
|
||||||
|
measurements from multiple sources.
|
||||||
|
|
||||||
|
There are also useful options which can be set in the +server+ directive, they
|
||||||
|
are +minpoll+, +maxpoll+, +polltarget+, +maxdelay+, +maxdelayratio+ and
|
||||||
|
+maxdelaydevratio+.
|
||||||
|
|
||||||
|
The first three options set the minimum and maximum allowed polling interval,
|
||||||
|
and how should be the actual interval adjusted in the specified range. Their
|
||||||
|
default values are 6 (64 seconds) for +minpoll+, 10 (1024 seconds) for
|
||||||
|
+maxpoll+ and 6 (samples) for +polltarget+. The default values should be used
|
||||||
|
for general servers on the internet. With your own NTP servers or if have
|
||||||
|
permission to poll some servers more frequently, setting these options for
|
||||||
|
shorter polling intervals may significantly improve the accuracy of the system
|
||||||
|
clock.
|
||||||
|
|
||||||
|
The optimal polling interval depends on many factors, including the ratio
|
||||||
|
between the wander of the clock and the network jitter (sometimes expressed in
|
||||||
|
NTP documents as the Allan intercept), the temperature sensitivity of the
|
||||||
|
crystal oscillator and the maximum rate of change of the temperature.
|
||||||
|
|
||||||
|
An example of the directive for an NTP server on the internet that you are
|
||||||
|
allowed to poll frequently could be
|
||||||
|
|
||||||
|
----
|
||||||
|
server foo.example.net minpoll 4 maxpoll 6 polltarget 16
|
||||||
|
----
|
||||||
|
|
||||||
|
An example using very short polling intervals for a server located in the same
|
||||||
|
LAN could be
|
||||||
|
|
||||||
|
----
|
||||||
|
server ntp.local minpoll 2 maxpoll 4 polltarget 30
|
||||||
|
----
|
||||||
|
|
||||||
|
The maxdelay options are useful to ignore measurements with larger delay (e.g.
|
||||||
|
due to congestion in the network) and improve the stability of the
|
||||||
|
synchronisation. The +maxdelaydevratio+ option could be added to the example
|
||||||
|
with local NTP server
|
||||||
|
|
||||||
|
----
|
||||||
|
server ntp.local minpoll 2 maxpoll 4 polltarget 30 maxdelaydevratio 2
|
||||||
|
----
|
||||||
|
|
||||||
|
=== What happened to the +commandkey+ and +generatecommandkey+ directives?
|
||||||
|
|
||||||
|
They were removed in version 2.2. Authentication is no longer supported in the
|
||||||
|
command protocol. Commands that required authentication are now allowed only
|
||||||
|
through a Unix domain socket, which is accessible only by the root and chrony
|
||||||
|
users. If you need to configure +chronyd+ remotely or locally without the root
|
||||||
|
password, please consider using ssh and/or sudo to run +chronyc+ under the root
|
||||||
|
or chrony user on the same host as +chronyd+ is running.
|
||||||
|
|
||||||
|
== Computer is not synchronising
|
||||||
|
|
||||||
|
This is the most common problem. There are a number of reasons, see the
|
||||||
|
following questions.
|
||||||
|
|
||||||
|
=== Behind a firewall?
|
||||||
|
|
||||||
|
If there is a firewall between you and the NTP server you're trying to use, the
|
||||||
|
packets may be blocked. Try using a tool like +wireshark+ or +tcpdump+ to see if
|
||||||
|
you're getting responses from the server. If you have an external modem, see
|
||||||
|
if the receive light blinks straight after the transmit light (when the link is
|
||||||
|
quiet apart from the NTP traffic.) Try adding +log measurements+ to the
|
||||||
|
'chrony.conf' file and look in the 'measurements.log' file after +chronyd+ has
|
||||||
|
been running for a short period. See if any measurements appear.
|
||||||
|
|
||||||
|
=== Are NTP servers specified with the +offline+ option?
|
||||||
|
|
||||||
|
Check that you're using +chronyc+\'s +online+ and +offline+ commands
|
||||||
|
appropriately. Again, check in 'measurements.log' to see if you're getting any
|
||||||
|
data back from the server.
|
||||||
|
|
||||||
|
=== Is +chronyd+ allowed to step the system clock?
|
||||||
|
|
||||||
|
By default, +chronyd+ adjusts the clock gradually by slowing it down or
|
||||||
|
speeding it up. If the clock is too far from the correct time, it will take
|
||||||
|
a long time to correct the error. The +System time+ value printed by the
|
||||||
|
+chronyc+'s +tracking+ command is the remaining correction that needs to be
|
||||||
|
applied to the system clock.
|
||||||
|
|
||||||
|
The +makestep+ directive can be used to allow +chronyd+ to step the clock. For
|
||||||
|
example, if 'chrony.conf' had
|
||||||
|
|
||||||
|
----
|
||||||
|
makestep 1 3
|
||||||
|
----
|
||||||
|
|
||||||
|
the clock would be stepped in the first three updates if its offset was larger
|
||||||
|
than one second. Normally, it's recommended to allow the step only in the
|
||||||
|
first few updates, but in some cases (e.g. a computer without RTC or virtual
|
||||||
|
machine which can be suspended and resumed with incorrect time) it may be
|
||||||
|
necessary to allow the step at any clock update. The example above would
|
||||||
|
change to
|
||||||
|
|
||||||
|
----
|
||||||
|
makestep 1 -1
|
||||||
|
----
|
||||||
|
|
||||||
|
== Issues with +chronyc+
|
||||||
|
|
||||||
|
=== I keep getting the error +506 Cannot talk to daemon+
|
||||||
|
|
||||||
|
When accessing +chronyd+ remotely, make sure that the 'chrony.conf' file (on
|
||||||
|
the computer where +chronyd+ is running) has a 'cmdallow' entry for the
|
||||||
|
computer you are running +chronyc+ on and an appropriate 'bindcmdaddress'
|
||||||
|
directive. This isn't necessary for localhost.
|
||||||
|
|
||||||
|
Perhaps +chronyd+ is not running. Try using the +ps+ command (e.g. on Linux,
|
||||||
|
+ps -auxw+) to see if it's running. Or try +netstat -a+ and see if the ports
|
||||||
|
123/udp and 323/udp are listening. If +chronyd+ is not running, you may have a
|
||||||
|
problem with the way you are trying to start it (e.g. at boot time).
|
||||||
|
|
||||||
|
Perhaps you have a firewall set up in a way that blocks packets on port
|
||||||
|
323/udp. You need to amend the firewall configuration in this case.
|
||||||
|
|
||||||
|
=== I keep getting the error +501 Not authorised+
|
||||||
|
|
||||||
|
Since version 2.2, the +password+ command doesn't do anything and +chronyc+
|
||||||
|
needs to run under the root or chrony user, which are allowed to access the
|
||||||
|
Unix domain command socket.
|
||||||
|
|
||||||
|
=== Is the +chronyc+ / +chronyd+ protocol documented anywhere?
|
||||||
|
|
||||||
|
Only by the source code :-) See 'cmdmon.c' (+chronyd+ side) and 'client.c'
|
||||||
|
(+chronyc+ side).
|
||||||
|
|
||||||
|
== Real-time clock issues
|
||||||
|
|
||||||
|
=== What is the real-time clock (RTC)?
|
||||||
|
|
||||||
|
This is the clock which keeps the time even when your computer is turned off.
|
||||||
|
It is used to initialize the system clock on boot. It normally doesn't drift
|
||||||
|
more than few seconds per day.
|
||||||
|
|
||||||
|
There are two approaches how +chronyd+ can work with it. One is to use the
|
||||||
|
+rtcsync+ directive, which tells +chronyd+ to enable a kernel mode which sets
|
||||||
|
the RTC from the system clock every 11 minutes. +chronyd+ itself won't touch
|
||||||
|
the RTC. If the computer is not turned off for a long time, the RTC should
|
||||||
|
still be close to the true time when the system clock will be initialized from
|
||||||
|
it on the next boot.
|
||||||
|
|
||||||
|
The other option is to use the +rtcfile+ directive, which will tell +chronyd+
|
||||||
|
to monitor the rate at which the RTC gains or loses time. When +chronyd+ is
|
||||||
|
started with the +-s+ option on the next boot, it will set the system time from
|
||||||
|
the RTC and also compensate for the drift it has measured previously. The
|
||||||
|
+rtcautotrim+ directive can be used to keep the RTC close to the true time, but
|
||||||
|
it's not strictly necessary if its only purpose is to set the system clock when
|
||||||
|
+chronyd+ is started on boot. See the documentation for details.
|
||||||
|
|
||||||
|
=== I want to use +chronyd+'s RTC support. Must I disable +hwclock+?
|
||||||
|
|
||||||
|
The +hwclock+ program is often set-up by default in the boot and shutdown
|
||||||
|
scripts with many Linux installations. With the kernel RTC synchronisation
|
||||||
|
(+rtcsync+ directive), the RTC will be set also every 11 minutes as long as the
|
||||||
|
system clock is synchronised. If you want to use +chronyd+'s RTC monitoring
|
||||||
|
(+rtcfile+ directive), it's important to disable +hwclock+ in the shutdown
|
||||||
|
procedure. If you don't, it will over-write the RTC with a new value, unknown
|
||||||
|
to +chronyd+. At the next reboot, +chronyd+ started with the +-s+ option will
|
||||||
|
compensate this (wrong) time with its estimate of how far the RTC has drifted
|
||||||
|
whilst the power was off, giving a meaningless initial system time.
|
||||||
|
|
||||||
|
There is no need to remove +hwclock+ from the boot process, as long as +chronyd+
|
||||||
|
is started after it has run.
|
||||||
|
|
||||||
|
=== I just keep getting the +513 RTC driver not running+ message
|
||||||
|
|
||||||
|
For the real time clock support to work, you need the following three
|
||||||
|
things
|
||||||
|
|
||||||
|
* a kernel that is supported (e.g. 2.2 onwards)
|
||||||
|
* enhanced RTC support compiled into the kernel
|
||||||
|
* an +rtcfile+ directive in your 'chrony.conf' file
|
||||||
|
|
||||||
|
== NTP-specific issues
|
||||||
|
|
||||||
|
=== Can +chronyd+ be driven from broadcast NTP servers?
|
||||||
|
|
||||||
|
No, the broadcast client mode is not supported and there is currently no plan
|
||||||
|
to implement it. The broadcast and multicast modes are inherently less
|
||||||
|
accurate and less secure (even with authentication) than the ordinary
|
||||||
|
server/client mode and they are not as useful as they used to be. Even with
|
||||||
|
very modest hardware a single NTP server can serve time to hundreds of
|
||||||
|
thousands of clients using the ordinary mode.
|
||||||
|
|
||||||
|
=== Can +chronyd+ transmit broadcast NTP packets?
|
||||||
|
|
||||||
|
Yes, the +broadcast+ directive can be used to enable the broadcast server mode
|
||||||
|
to serve time to clients in the network which support the broadcast client mode
|
||||||
|
(it's not supported in +chronyd+, see the previous question).
|
||||||
|
|
||||||
|
=== Can +chronyd+ keep the system clock a fixed offset away from real time?
|
||||||
|
|
||||||
|
This is not possible as the program currently stands.
|
||||||
|
|
||||||
|
=== What happens if the network connection is dropped without using +chronyc+'s +offline+ command first?
|
||||||
|
|
||||||
|
+chronyd+ will keep trying to access the server(s) that it thinks are online.
|
||||||
|
When the network is connected again, it will take some time (on average half of
|
||||||
|
the current polling interval) before new measurements are made and the clock is
|
||||||
|
corrected. If the servers were set to offline and the +online+ command was
|
||||||
|
issued when the network was connected, +chronyd+ would make new measurements
|
||||||
|
immediately.
|
||||||
|
|
||||||
|
The +auto_offline+ option to the +server+ entry in the 'chrony.conf' file may
|
||||||
|
be useful to switch the servers to the offline state automatically.
|
||||||
|
|
||||||
|
== Linux-specific issues
|
||||||
|
|
||||||
|
=== I get +Could not open /dev/rtc, Device or resource busy+ in my syslog file
|
||||||
|
|
||||||
|
Some other program running on the system may be using the device.
|
||||||
|
|
||||||
|
== Microsoft Windows
|
||||||
|
|
||||||
|
=== Does +chrony+ support Windows?
|
||||||
|
|
||||||
|
No. The +chronyc+ program (the command-line client used for configuring
|
||||||
|
+chronyd+ while it is running) has been successfully built and run under
|
||||||
|
Cygwin in the past. +chronyd+ is not portable, because part of it is
|
||||||
|
very system-dependent. It needs adapting to work with Windows'
|
||||||
|
equivalent of the adjtimex() call, and it needs to be made to work as a
|
||||||
|
service.
|
||||||
|
|
||||||
|
=== Are there any plans to support Windows?
|
||||||
|
|
||||||
|
We have no plans to do this. Anyone is welcome to pick this work up and
|
||||||
|
contribute it back to the project.
|
||||||
@@ -9,7 +9,7 @@ Wants=time-sync.target
|
|||||||
Type=oneshot
|
Type=oneshot
|
||||||
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
|
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
|
||||||
# clock correction to be less than 0.1 seconds
|
# clock correction to be less than 0.1 seconds
|
||||||
ExecStart=/usr/bin/chronyc waitsync 60 0.1
|
ExecStart=/usr/bin/chronyc waitsync 600 0.1 0.0 1
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
StandardOutput=null
|
StandardOutput=null
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ pool pool.ntp.org iburst
|
|||||||
driftfile /var/lib/chrony/drift
|
driftfile /var/lib/chrony/drift
|
||||||
|
|
||||||
# In first three updates step the system clock instead of slew
|
# In first three updates step the system clock instead of slew
|
||||||
# if the adjustment is larger than 10 seconds.
|
# if the adjustment is larger than 1 second.
|
||||||
makestep 10 3
|
makestep 1.0 3
|
||||||
|
|
||||||
# Enable kernel synchronization of the real-time clock (RTC).
|
# Enable kernel synchronization of the real-time clock (RTC).
|
||||||
rtcsync
|
rtcsync
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ pool pool.ntp.org iburst
|
|||||||
driftfile /var/lib/chrony/drift
|
driftfile /var/lib/chrony/drift
|
||||||
|
|
||||||
# In first three updates step the system clock instead of slew
|
# In first three updates step the system clock instead of slew
|
||||||
# if the adjustment is larger than 10 seconds.
|
# if the adjustment is larger than 1 second.
|
||||||
makestep 10 3
|
makestep 1.0 3
|
||||||
|
|
||||||
# Enable kernel synchronization of the real-time clock (RTC).
|
# Enable kernel synchronization of the real-time clock (RTC).
|
||||||
rtcsync
|
rtcsync
|
||||||
@@ -18,14 +18,8 @@ rtcsync
|
|||||||
# Serve time even if not synchronized to any NTP server.
|
# Serve time even if not synchronized to any NTP server.
|
||||||
#local stratum 10
|
#local stratum 10
|
||||||
|
|
||||||
# Specify file containing keys for NTP and command authentication.
|
# Specify file containing keys for NTP authentication.
|
||||||
keyfile /etc/chrony.keys
|
#keyfile /etc/chrony.keys
|
||||||
|
|
||||||
# Specify key number for command authentication.
|
|
||||||
commandkey 1
|
|
||||||
|
|
||||||
# Generate new command key on start if missing.
|
|
||||||
generatecommandkey
|
|
||||||
|
|
||||||
# Disable logging of client accesses.
|
# Disable logging of client accesses.
|
||||||
noclientlog
|
noclientlog
|
||||||
|
|||||||
@@ -95,24 +95,10 @@
|
|||||||
|
|
||||||
driftfile /var/lib/chrony/drift
|
driftfile /var/lib/chrony/drift
|
||||||
|
|
||||||
# If you want to use the program called chronyc to configure aspects of
|
# If you want to enable NTP authentication with symmetric keys, you will need
|
||||||
# chronyd's operation once it is running (e.g. tell it the Internet link
|
# to uncomment the following line and edit the file to set up the keys.
|
||||||
# has gone up or down), you need a password. This is stored in the
|
|
||||||
# following keys file. (You also need keys to support authenticated NTP
|
|
||||||
# exchanges between cooperating machines.) Again, this option is
|
|
||||||
# assumed by default.
|
|
||||||
|
|
||||||
keyfile /etc/chrony.keys
|
! keyfile /etc/chrony.keys
|
||||||
|
|
||||||
# Tell chronyd which numbered key in the file is used as the password
|
|
||||||
# for chronyc. (You can pick any integer up to 2**32-1. '1' is just a
|
|
||||||
# default. Using another value will _NOT_ increase security.)
|
|
||||||
|
|
||||||
commandkey 1
|
|
||||||
|
|
||||||
# With this directive a random password will be generated automatically.
|
|
||||||
|
|
||||||
generatecommandkey
|
|
||||||
|
|
||||||
# chronyd can save the measurement history for the servers to files when
|
# chronyd can save the measurement history for the servers to files when
|
||||||
# it it exits. This is useful in 2 situations:
|
# it it exits. This is useful in 2 situations:
|
||||||
@@ -142,15 +128,15 @@ generatecommandkey
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
### INITIAL CLOCK CORRECTION
|
### INITIAL CLOCK CORRECTION
|
||||||
# This option is useful to quickly correct the clock on start if it's
|
# This option is useful to quickly correct the clock on start if it's
|
||||||
# off by a large amount. The value '10' means that if the error is less
|
# off by a large amount. The value '1.0' means that if the error is less
|
||||||
# than 10 seconds, it will be gradually removed by speeding up or
|
# than 1 second, it will be gradually removed by speeding up or slowing
|
||||||
# slowing down your computer's clock until it is correct. If the error
|
# down your computer's clock until it is correct. If the error is above
|
||||||
# is above 10 seconds, an immediate time jump will be applied to correct
|
# 1 second, an immediate time jump will be applied to correct it. The
|
||||||
# it. The value '1' means the step is allowed only on the first update
|
# value '3' means the step is allowed only in the first three updates of
|
||||||
# of the clock. Some software can get upset if the system clock jumps
|
# the clock. Some software can get upset if the system clock jumps
|
||||||
# (especially backwards), so be careful!
|
# (especially backwards), so be careful!
|
||||||
|
|
||||||
! makestep 10 1
|
! makestep 1.0 3
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
### LOGGING
|
### LOGGING
|
||||||
@@ -262,11 +248,6 @@ generatecommandkey
|
|||||||
# syntax and meaning is the same as for 'allow' and 'deny', except that
|
# syntax and meaning is the same as for 'allow' and 'deny', except that
|
||||||
# 'cmdallow' and 'cmddeny' control access to the chronyd's command port.
|
# 'cmdallow' and 'cmddeny' control access to the chronyd's command port.
|
||||||
|
|
||||||
# NOTE, even if the host where you run chronyc is granted access, you
|
|
||||||
# still need a command key set up and you have to know the password to
|
|
||||||
# put into chronyc to allow you to modify chronyd's parameters. By
|
|
||||||
# default all you can do is view information about chronyd's operation.
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
### REAL TIME CLOCK
|
### REAL TIME CLOCK
|
||||||
# chronyd can characterise the system's real-time clock. This is the
|
# chronyd can characterise the system's real-time clock. This is the
|
||||||
|
|||||||
@@ -1,29 +1,15 @@
|
|||||||
#######################################################################
|
# This is an example chrony keys file. It is used for NTP authentication with
|
||||||
|
# symmetric keys. It should be readable only by root or the user to which
|
||||||
|
# chronyd is configured to switch to.
|
||||||
#
|
#
|
||||||
# This is an example chrony keys file. You should copy it to /etc/chrony.keys
|
# Don't use the example keys! The keys need to be random for maximum security.
|
||||||
# after editing it to set up the key(s) you want to use. It should be readable
|
# These shell commands can be used to generate random MD5 and SHA1 keys on
|
||||||
# only by root or the user chronyd drops the root privileges to. In most
|
# systems which have the /dev/urandom device:
|
||||||
# situations, you will require a single key (the 'commandkey') so that you can
|
# echo "1 MD5 HEX:$(tr -d -c '[:xdigit:]' < /dev/urandom | head -c 32)"
|
||||||
# supply a password to chronyc to enable you to modify chronyd's operation
|
# echo "1 SHA1 HEX:$(tr -d -c '[:xdigit:]' < /dev/urandom | head -c 40)"
|
||||||
# whilst it is running.
|
|
||||||
#
|
|
||||||
# Copyright 2002 Richard P. Curnow
|
|
||||||
#
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
# Examples of valid keys:
|
# Examples of valid keys:
|
||||||
|
|
||||||
#1 ALongAndRandomPassword
|
#1 ALongAndRandomPassword
|
||||||
#2 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC
|
#2 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC
|
||||||
#3 SHA1 HEX:1DC764E0791B11FA67EFC7ECBC4B0D73F68A070C
|
#3 SHA1 HEX:1DC764E0791B11FA67EFC7ECBC4B0D73F68A070C
|
||||||
|
|
||||||
# The keys should be random for maximum security. If you wanted to use a key
|
|
||||||
# with ID 1 as your commandkey (i.e. chronyc password) you would put
|
|
||||||
# "commandkey 1" into chrony.conf. If no commandkey is present in the keys
|
|
||||||
# file and the generatecommandkey directive is specified in chrony.conf,
|
|
||||||
# a random commandkey will be generated and added to the keys file
|
|
||||||
# automatically on chronyd start.
|
|
||||||
|
|
||||||
# You might want to define more keys if you use the authentication facility
|
|
||||||
# in the network time protocol to authenticate request/response packets between
|
|
||||||
# trusted clients and servers.
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
nocreate
|
nocreate
|
||||||
sharedscripts
|
sharedscripts
|
||||||
postrotate
|
postrotate
|
||||||
/usr/bin/chronyc -a cyclelogs > /dev/null 2>&1 || true
|
/usr/bin/chronyc cyclelogs > /dev/null 2>&1 || true
|
||||||
endscript
|
endscript
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ export LC_ALL=C
|
|||||||
|
|
||||||
if [ "$2" = "up" ]; then
|
if [ "$2" = "up" ]; then
|
||||||
/sbin/ip route list dev "$1" | grep -q '^default' &&
|
/sbin/ip route list dev "$1" | grep -q '^default' &&
|
||||||
/usr/bin/chronyc -a online > /dev/null 2>&1
|
/usr/bin/chronyc online > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$2" = "down" ]; then
|
if [ "$2" = "down" ]; then
|
||||||
/sbin/ip route list | grep -q '^default' ||
|
/sbin/ip route list | grep -q '^default' ||
|
||||||
/usr/bin/chronyc -a offline > /dev/null 2>&1
|
/usr/bin/chronyc offline > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
|||||||
%{_sbindir}/chronyd
|
%{_sbindir}/chronyd
|
||||||
%{_bindir}/chronyc
|
%{_bindir}/chronyc
|
||||||
%{_infodir}/chrony.info*
|
%{_infodir}/chrony.info*
|
||||||
%{_mandir}/man1/chrony.1.gz
|
|
||||||
%{_mandir}/man1/chronyc.1.gz
|
%{_mandir}/man1/chronyc.1.gz
|
||||||
%{_mandir}/man5/chrony.conf.5.gz
|
%{_mandir}/man5/chrony.conf.5.gz
|
||||||
%{_mandir}/man8/chronyd.8.gz
|
%{_mandir}/man8/chronyd.8.gz
|
||||||
|
|||||||
@@ -8,12 +8,7 @@
|
|||||||
** This code is in the public domain and has no copyright.
|
** This code is in the public domain and has no copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#include "config.h"
|
||||||
# include <config.h>
|
|
||||||
# ifdef HAVE_ALLOCA_H
|
|
||||||
# include <alloca.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Since the code of getdate.y is not included in the Emacs executable
|
/* Since the code of getdate.y is not included in the Emacs executable
|
||||||
itself, there is no need to #define static in this file. Even if
|
itself, there is no need to #define static in this file. Even if
|
||||||
|
|||||||
@@ -25,11 +25,12 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <nss.h>
|
#include <nss.h>
|
||||||
#include <hasht.h>
|
#include <hasht.h>
|
||||||
#include <nsslowhash.h>
|
#include <nsslowhash.h>
|
||||||
|
|
||||||
/* #include "config.h" */
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
static NSSLOWInitContext *ictx;
|
static NSSLOWInitContext *ictx;
|
||||||
|
|||||||
79
keys.c
79
keys.c
@@ -50,72 +50,12 @@ typedef struct {
|
|||||||
|
|
||||||
static ARR_Instance keys;
|
static ARR_Instance keys;
|
||||||
|
|
||||||
static int command_key_valid;
|
|
||||||
static uint32_t command_key_id;
|
|
||||||
static int cache_valid;
|
static int cache_valid;
|
||||||
static uint32_t cache_key_id;
|
static uint32_t cache_key_id;
|
||||||
static int cache_key_pos;
|
static int cache_key_pos;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static int
|
|
||||||
generate_key(uint32_t key_id)
|
|
||||||
{
|
|
||||||
#ifdef FEAT_SECHASH
|
|
||||||
unsigned char key[20];
|
|
||||||
const char *hashname = "SHA1";
|
|
||||||
#else
|
|
||||||
unsigned char key[16];
|
|
||||||
const char *hashname = "MD5";
|
|
||||||
#endif
|
|
||||||
const char *key_file, *rand_dev = "/dev/urandom";
|
|
||||||
FILE *f;
|
|
||||||
struct stat st;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
key_file = CNF_GetKeysFile();
|
|
||||||
|
|
||||||
if (!key_file)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
f = fopen(rand_dev, "r");
|
|
||||||
if (!f || fread(key, sizeof (key), 1, f) != 1) {
|
|
||||||
if (f)
|
|
||||||
fclose(f);
|
|
||||||
LOG_FATAL(LOGF_Keys, "Could not read %s", rand_dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
f = fopen(key_file, "a");
|
|
||||||
if (!f) {
|
|
||||||
LOG_FATAL(LOGF_Keys, "Could not open keyfile %s for writing", key_file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the keyfile is not world-readable */
|
|
||||||
if (stat(key_file, &st) || chmod(key_file, st.st_mode & 0770)) {
|
|
||||||
fclose(f);
|
|
||||||
LOG_FATAL(LOGF_Keys, "Could not change permissions of keyfile %s", key_file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f, "\n%"PRIu32" %s HEX:", key_id, hashname);
|
|
||||||
for (i = 0; i < sizeof (key); i++)
|
|
||||||
fprintf(f, "%02hhX", key[i]);
|
|
||||||
fprintf(f, "\n");
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
/* Erase the key from stack */
|
|
||||||
memset(key, 0, sizeof (key));
|
|
||||||
|
|
||||||
LOG(LOGS_INFO, LOGF_Keys, "Generated key %"PRIu32, key_id);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_keys(void)
|
free_keys(void)
|
||||||
{
|
{
|
||||||
@@ -125,7 +65,6 @@ free_keys(void)
|
|||||||
Free(((Key *)ARR_GetElement(keys, i))->val);
|
Free(((Key *)ARR_GetElement(keys, i))->val);
|
||||||
|
|
||||||
ARR_SetSize(keys, 0);
|
ARR_SetSize(keys, 0);
|
||||||
command_key_valid = 0;
|
|
||||||
cache_valid = 0;
|
cache_valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,14 +74,8 @@ void
|
|||||||
KEY_Initialise(void)
|
KEY_Initialise(void)
|
||||||
{
|
{
|
||||||
keys = ARR_CreateInstance(sizeof (Key));
|
keys = ARR_CreateInstance(sizeof (Key));
|
||||||
command_key_valid = 0;
|
|
||||||
cache_valid = 0;
|
cache_valid = 0;
|
||||||
KEY_Reload();
|
KEY_Reload();
|
||||||
|
|
||||||
if (CNF_GetGenerateCommandKey() && !KEY_KeyKnown(KEY_GetCommandKey())) {
|
|
||||||
if (generate_key(KEY_GetCommandKey()))
|
|
||||||
KEY_Reload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -334,18 +267,6 @@ get_key_by_id(uint32_t key_id)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
uint32_t
|
|
||||||
KEY_GetCommandKey(void)
|
|
||||||
{
|
|
||||||
if (!command_key_valid) {
|
|
||||||
command_key_id = CNF_GetCommandKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
return command_key_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
KEY_KeyKnown(uint32_t key_id)
|
KEY_KeyKnown(uint32_t key_id)
|
||||||
{
|
{
|
||||||
|
|||||||
2
keys.h
2
keys.h
@@ -34,8 +34,6 @@ extern void KEY_Finalise(void);
|
|||||||
|
|
||||||
extern void KEY_Reload(void);
|
extern void KEY_Reload(void);
|
||||||
|
|
||||||
extern uint32_t KEY_GetCommandKey(void);
|
|
||||||
|
|
||||||
extern int KEY_GetKey(uint32_t key_id, char **key, int *len);
|
extern int KEY_GetKey(uint32_t key_id, char **key, int *len);
|
||||||
extern int KEY_KeyKnown(uint32_t key_id);
|
extern int KEY_KeyKnown(uint32_t key_id);
|
||||||
extern int KEY_GetAuthDelay(uint32_t key_id);
|
extern int KEY_GetAuthDelay(uint32_t key_id);
|
||||||
|
|||||||
94
local.c
94
local.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2011, 2014
|
* Copyright (C) Miroslav Lichvar 2011, 2014-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -36,11 +36,16 @@
|
|||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "localp.h"
|
#include "localp.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "smooth.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
/* Maximum allowed frequency offset in ppm, the time must not stop
|
||||||
|
or run backwards */
|
||||||
|
#define MAX_FREQ 500000.0
|
||||||
|
|
||||||
/* Variable to store the current frequency, in ppm */
|
/* Variable to store the current frequency, in ppm */
|
||||||
static double current_freq_ppm;
|
static double current_freq_ppm;
|
||||||
|
|
||||||
@@ -397,6 +402,33 @@ LCL_ReadAbsoluteFrequency(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static double
|
||||||
|
clamp_freq(double freq)
|
||||||
|
{
|
||||||
|
if (freq <= MAX_FREQ && freq >= -MAX_FREQ)
|
||||||
|
return freq;
|
||||||
|
|
||||||
|
LOG(LOGS_WARN, LOGF_Local, "Frequency %.1f ppm exceeds allowed maximum", freq);
|
||||||
|
|
||||||
|
return freq >= MAX_FREQ ? MAX_FREQ : -MAX_FREQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_offset(struct timeval *now, double offset)
|
||||||
|
{
|
||||||
|
/* Check if the time will be still sane with accumulated offset */
|
||||||
|
if (UTI_IsTimeOffsetSane(now, -offset))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
LOG(LOGS_WARN, LOGF_Local, "Adjustment of %.1f seconds is invalid", -offset);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
/* This involves both setting the absolute frequency with the
|
/* This involves both setting the absolute frequency with the
|
||||||
system-specific driver, as well as calling all notify handlers */
|
system-specific driver, as well as calling all notify handlers */
|
||||||
|
|
||||||
@@ -406,6 +438,8 @@ LCL_SetAbsoluteFrequency(double afreq_ppm)
|
|||||||
struct timeval raw, cooked;
|
struct timeval raw, cooked;
|
||||||
double dfreq;
|
double dfreq;
|
||||||
|
|
||||||
|
afreq_ppm = clamp_freq(afreq_ppm);
|
||||||
|
|
||||||
/* Apply temperature compensation */
|
/* Apply temperature compensation */
|
||||||
if (temp_comp_ppm != 0.0) {
|
if (temp_comp_ppm != 0.0) {
|
||||||
afreq_ppm = afreq_ppm * (1.0 - 1.0e-6 * temp_comp_ppm) - temp_comp_ppm;
|
afreq_ppm = afreq_ppm * (1.0 - 1.0e-6 * temp_comp_ppm) - temp_comp_ppm;
|
||||||
@@ -443,6 +477,8 @@ LCL_AccumulateDeltaFrequency(double dfreq)
|
|||||||
|
|
||||||
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
||||||
|
|
||||||
|
current_freq_ppm = clamp_freq(current_freq_ppm);
|
||||||
|
|
||||||
/* Call the system-specific driver for setting the frequency */
|
/* Call the system-specific driver for setting the frequency */
|
||||||
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
|
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
|
||||||
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm);
|
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm);
|
||||||
@@ -467,6 +503,9 @@ LCL_AccumulateOffset(double offset, double corr_rate)
|
|||||||
LCL_ReadRawTime(&raw);
|
LCL_ReadRawTime(&raw);
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&cooked, offset))
|
||||||
|
return;
|
||||||
|
|
||||||
(*drv_accrue_offset)(offset, corr_rate);
|
(*drv_accrue_offset)(offset, corr_rate);
|
||||||
|
|
||||||
/* Dispatch to all handlers */
|
/* Dispatch to all handlers */
|
||||||
@@ -475,7 +514,7 @@ LCL_AccumulateOffset(double offset, double corr_rate)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
int
|
||||||
LCL_ApplyStepOffset(double offset)
|
LCL_ApplyStepOffset(double offset)
|
||||||
{
|
{
|
||||||
struct timeval raw, cooked;
|
struct timeval raw, cooked;
|
||||||
@@ -486,10 +525,21 @@ LCL_ApplyStepOffset(double offset)
|
|||||||
LCL_ReadRawTime(&raw);
|
LCL_ReadRawTime(&raw);
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
(*drv_apply_step_offset)(offset);
|
if (!check_offset(&raw, offset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(*drv_apply_step_offset)(offset)) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Local, "Could not step clock");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset smoothing on all clock steps */
|
||||||
|
SMT_Reset(&cooked);
|
||||||
|
|
||||||
/* Dispatch to all handlers */
|
/* Dispatch to all handlers */
|
||||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep);
|
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -506,6 +556,23 @@ LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
LCL_NotifyLeap(int leap)
|
||||||
|
{
|
||||||
|
struct timeval raw, cooked;
|
||||||
|
|
||||||
|
LCL_ReadRawTime(&raw);
|
||||||
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
/* Smooth the leap second out */
|
||||||
|
SMT_Leap(&cooked, leap);
|
||||||
|
|
||||||
|
/* Dispatch to all handlers as if the clock was stepped */
|
||||||
|
invoke_parameter_change_handlers(&raw, &cooked, 0.0, -leap, LCL_ChangeStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
||||||
{
|
{
|
||||||
@@ -517,6 +584,9 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
|||||||
to the change we are about to make */
|
to the change we are about to make */
|
||||||
LCL_CookTime(&raw, &cooked, NULL);
|
LCL_CookTime(&raw, &cooked, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&cooked, doffset))
|
||||||
|
return;
|
||||||
|
|
||||||
old_freq_ppm = current_freq_ppm;
|
old_freq_ppm = current_freq_ppm;
|
||||||
|
|
||||||
/* Work out new absolute frequency. Note that absolute frequencies
|
/* Work out new absolute frequency. Note that absolute frequencies
|
||||||
@@ -524,6 +594,8 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
|
|||||||
terms of the gradient of the (offset) v (local time) function. */
|
terms of the gradient of the (offset) v (local time) function. */
|
||||||
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm);
|
||||||
|
|
||||||
|
current_freq_ppm = clamp_freq(current_freq_ppm);
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
|
DEBUG_LOG(LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
|
||||||
old_freq_ppm, current_freq_ppm, doffset);
|
old_freq_ppm, current_freq_ppm, doffset);
|
||||||
|
|
||||||
@@ -587,9 +659,13 @@ LCL_MakeStep(void)
|
|||||||
LCL_ReadRawTime(&raw);
|
LCL_ReadRawTime(&raw);
|
||||||
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
LCL_GetOffsetCorrection(&raw, &correction, NULL);
|
||||||
|
|
||||||
|
if (!check_offset(&raw, -correction))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Cancel remaining slew and make the step */
|
/* Cancel remaining slew and make the step */
|
||||||
LCL_AccumulateOffset(correction, 0.0);
|
LCL_AccumulateOffset(correction, 0.0);
|
||||||
LCL_ApplyStepOffset(-correction);
|
if (!LCL_ApplyStepOffset(-correction))
|
||||||
|
return 0;
|
||||||
|
|
||||||
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.6f seconds", correction);
|
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.6f seconds", correction);
|
||||||
|
|
||||||
@@ -598,8 +674,16 @@ LCL_MakeStep(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
LCL_CanSystemLeap(void)
|
||||||
|
{
|
||||||
|
return drv_set_leap ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
LCL_SetLeap(int leap)
|
LCL_SetSystemLeap(int leap)
|
||||||
{
|
{
|
||||||
if (drv_set_leap) {
|
if (drv_set_leap) {
|
||||||
(drv_set_leap)(leap);
|
(drv_set_leap)(leap);
|
||||||
|
|||||||
18
local.h
18
local.h
@@ -159,13 +159,17 @@ extern void LCL_AccumulateOffset(double offset, double corr_rate);
|
|||||||
the system clock is fast on true time, i.e. it needs to be stepped
|
the system clock is fast on true time, i.e. it needs to be stepped
|
||||||
backwards. (Same convention as for AccumulateOffset routine). */
|
backwards. (Same convention as for AccumulateOffset routine). */
|
||||||
|
|
||||||
extern void LCL_ApplyStepOffset(double offset);
|
extern int LCL_ApplyStepOffset(double offset);
|
||||||
|
|
||||||
/* Routine to invoke notify handlers on an unexpected time jump
|
/* Routine to invoke notify handlers on an unexpected time jump
|
||||||
in system clock */
|
in system clock */
|
||||||
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
||||||
double offset, double dispersion);
|
double offset, double dispersion);
|
||||||
|
|
||||||
|
/* Routine to invoke notify handlers on leap second when the system clock
|
||||||
|
doesn't correct itself */
|
||||||
|
extern void LCL_NotifyLeap(int leap);
|
||||||
|
|
||||||
/* Perform the combination of modifying the frequency and applying
|
/* Perform the combination of modifying the frequency and applying
|
||||||
a slew, in one easy step */
|
a slew, in one easy step */
|
||||||
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
|
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
|
||||||
@@ -194,10 +198,14 @@ extern void LCL_Finalise(void);
|
|||||||
to a timezone problem. */
|
to a timezone problem. */
|
||||||
extern int LCL_MakeStep(void);
|
extern int LCL_MakeStep(void);
|
||||||
|
|
||||||
/* Routine to schedule a leap second. Leap second will be inserted
|
/* Check if the system driver supports leap seconds, i.e. LCL_SetSystemLeap
|
||||||
at the end of the day if argument is positive, deleted if negative,
|
does something */
|
||||||
and zero cancels scheduled leap second. */
|
extern int LCL_CanSystemLeap(void);
|
||||||
extern void LCL_SetLeap(int leap);
|
|
||||||
|
/* Routine to set the system clock to correct itself for a leap second if
|
||||||
|
supported. Leap second will be inserted at the end of the day if the
|
||||||
|
argument is positive, deleted if negative, and zero resets the setting. */
|
||||||
|
extern void LCL_SetSystemLeap(int leap);
|
||||||
|
|
||||||
/* Routine to set a frequency correction (in ppm) that should be applied
|
/* Routine to set a frequency correction (in ppm) that should be applied
|
||||||
to local clock to compensate for temperature changes. A positive
|
to local clock to compensate for temperature changes. A positive
|
||||||
|
|||||||
2
localp.h
2
localp.h
@@ -47,7 +47,7 @@ typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
|
|||||||
|
|
||||||
/* System driver to apply a step offset. A positive argument means step
|
/* System driver to apply a step offset. A positive argument means step
|
||||||
the clock forwards. */
|
the clock forwards. */
|
||||||
typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
|
typedef int (*lcl_ApplyStepOffsetDriver)(double offset);
|
||||||
|
|
||||||
/* System driver to convert a raw time to an adjusted (cooked) time.
|
/* System driver to convert a raw time to an adjusted (cooked) time.
|
||||||
The number of seconds returned in 'corr' have to be added to the
|
The number of seconds returned in 'corr' have to be added to the
|
||||||
|
|||||||
52
logging.c
52
logging.c
@@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "mkdirpp.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* This is used by DEBUG_LOG macro */
|
/* This is used by DEBUG_LOG macro */
|
||||||
@@ -49,10 +48,6 @@ static int parent_fd = 0;
|
|||||||
#define DEBUG_LEVEL_PRINT_DEBUG 2
|
#define DEBUG_LEVEL_PRINT_DEBUG 2
|
||||||
static int debug_level = 0;
|
static int debug_level = 0;
|
||||||
|
|
||||||
#ifdef WINNT
|
|
||||||
static FILE *logfile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct LogFile {
|
struct LogFile {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *banner;
|
const char *banner;
|
||||||
@@ -74,10 +69,6 @@ void
|
|||||||
LOG_Initialise(void)
|
LOG_Initialise(void)
|
||||||
{
|
{
|
||||||
initialised = 1;
|
initialised = 1;
|
||||||
|
|
||||||
#ifdef WINNT
|
|
||||||
logfile = fopen("./chronyd.err", "a");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -86,15 +77,9 @@ LOG_Initialise(void)
|
|||||||
void
|
void
|
||||||
LOG_Finalise(void)
|
LOG_Finalise(void)
|
||||||
{
|
{
|
||||||
#ifdef WINNT
|
|
||||||
if (logfile) {
|
|
||||||
fclose(logfile);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (system_log) {
|
if (system_log) {
|
||||||
closelog();
|
closelog();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
LOG_CycleLogFiles();
|
LOG_CycleLogFiles();
|
||||||
|
|
||||||
@@ -105,11 +90,6 @@ LOG_Finalise(void)
|
|||||||
|
|
||||||
static void log_message(int fatal, LOG_Severity severity, const char *message)
|
static void log_message(int fatal, LOG_Severity severity, const char *message)
|
||||||
{
|
{
|
||||||
#ifdef WINNT
|
|
||||||
if (logfile) {
|
|
||||||
fprintf(logfile, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (system_log) {
|
if (system_log) {
|
||||||
int priority;
|
int priority;
|
||||||
switch (severity) {
|
switch (severity) {
|
||||||
@@ -135,32 +115,33 @@ static void log_message(int fatal, LOG_Severity severity, const char *message)
|
|||||||
} else {
|
} else {
|
||||||
fprintf(stderr, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
fprintf(stderr, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void LOG_Message(LOG_Severity severity, LOG_Facility facility,
|
void LOG_Message(LOG_Severity severity,
|
||||||
int line_number, const char *filename,
|
#if DEBUG > 0
|
||||||
const char *function_name, const char *format, ...)
|
LOG_Facility facility, int line_number,
|
||||||
|
const char *filename, const char *function_name,
|
||||||
|
#endif
|
||||||
|
const char *format, ...)
|
||||||
{
|
{
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
va_list other_args;
|
va_list other_args;
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm stm;
|
struct tm stm;
|
||||||
|
|
||||||
#ifdef WINNT
|
|
||||||
#else
|
|
||||||
if (!system_log) {
|
if (!system_log) {
|
||||||
/* Don't clutter up syslog with timestamps and internal debugging info */
|
/* Don't clutter up syslog with timestamps and internal debugging info */
|
||||||
time(&t);
|
time(&t);
|
||||||
stm = *gmtime(&t);
|
stm = *gmtime(&t);
|
||||||
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &stm);
|
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &stm);
|
||||||
fprintf(stderr, "%s ", buf);
|
fprintf(stderr, "%s ", buf);
|
||||||
|
#if DEBUG > 0
|
||||||
if (debug_level >= DEBUG_LEVEL_PRINT_FUNCTION)
|
if (debug_level >= DEBUG_LEVEL_PRINT_FUNCTION)
|
||||||
fprintf(stderr, "%s:%d:(%s) ", filename, line_number, function_name);
|
fprintf(stderr, "%s:%d:(%s) ", filename, line_number, function_name);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
va_start(other_args, format);
|
va_start(other_args, format);
|
||||||
vsnprintf(buf, sizeof(buf), format, other_args);
|
vsnprintf(buf, sizeof(buf), format, other_args);
|
||||||
@@ -198,11 +179,8 @@ void LOG_Message(LOG_Severity severity, LOG_Facility facility,
|
|||||||
void
|
void
|
||||||
LOG_OpenSystemLog(void)
|
LOG_OpenSystemLog(void)
|
||||||
{
|
{
|
||||||
#ifdef WINNT
|
|
||||||
#else
|
|
||||||
system_log = 1;
|
system_log = 1;
|
||||||
openlog("chronyd", LOG_PID, LOG_DAEMON);
|
openlog("chronyd", LOG_PID, LOG_DAEMON);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -300,20 +278,6 @@ LOG_FileWrite(LOG_FileID id, const char *format, ...)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
|
||||||
LOG_CreateLogFileDir(void)
|
|
||||||
{
|
|
||||||
const char *logdir;
|
|
||||||
|
|
||||||
logdir = CNF_GetLogDir();
|
|
||||||
|
|
||||||
if (!mkdir_and_parents(logdir)) {
|
|
||||||
LOG(LOGS_ERR, LOGF_Logging, "Could not create directory %s", logdir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LOG_CycleLogFiles(void)
|
LOG_CycleLogFiles(void)
|
||||||
{
|
{
|
||||||
|
|||||||
30
logging.h
30
logging.h
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
* Copyright (C) Richard P. Curnow 1997-2002
|
||||||
* Copyright (C) Miroslav Lichvar 2013-2014
|
* Copyright (C) Miroslav Lichvar 2013-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -45,18 +45,28 @@ extern int log_debug_enabled;
|
|||||||
#define FORMAT_ATTRIBUTE_PRINTF(str, first)
|
#define FORMAT_ATTRIBUTE_PRINTF(str, first)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG > 0
|
||||||
|
#define LOG_MESSAGE(severity, facility, ...) \
|
||||||
|
LOG_Message(LOGS_DEBUG, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define LOG_MESSAGE(severity, facility, ...) \
|
||||||
|
LOG_Message(severity, __VA_ARGS__);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEBUG_LOG(facility, ...) \
|
#define DEBUG_LOG(facility, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (DEBUG && log_debug_enabled) \
|
if (DEBUG && log_debug_enabled) \
|
||||||
LOG_Message(LOGS_DEBUG, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__); \
|
LOG_MESSAGE(LOGS_DEBUG, facility, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define LOG(severity, facility, ...) LOG_Message(severity, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__)
|
|
||||||
#define LOG_FATAL(facility, ...) \
|
#define LOG_FATAL(facility, ...) \
|
||||||
do { \
|
do { \
|
||||||
LOG_Message(LOGS_FATAL, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__); \
|
LOG_MESSAGE(LOGS_FATAL, facility, __VA_ARGS__); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LOG(severity, facility, ...) LOG_MESSAGE(severity, facility, __VA_ARGS__)
|
||||||
|
|
||||||
/* Definition of severity */
|
/* Definition of severity */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LOGS_INFO,
|
LOGS_INFO,
|
||||||
@@ -81,6 +91,7 @@ typedef enum {
|
|||||||
LOGF_Util,
|
LOGF_Util,
|
||||||
LOGF_Main,
|
LOGF_Main,
|
||||||
LOGF_Memory,
|
LOGF_Memory,
|
||||||
|
LOGF_Client,
|
||||||
LOGF_ClientLog,
|
LOGF_ClientLog,
|
||||||
LOGF_Configure,
|
LOGF_Configure,
|
||||||
LOGF_CmdMon,
|
LOGF_CmdMon,
|
||||||
@@ -94,13 +105,16 @@ typedef enum {
|
|||||||
LOGF_Sys,
|
LOGF_Sys,
|
||||||
LOGF_SysGeneric,
|
LOGF_SysGeneric,
|
||||||
LOGF_SysLinux,
|
LOGF_SysLinux,
|
||||||
|
LOGF_SysMacOSX,
|
||||||
LOGF_SysNetBSD,
|
LOGF_SysNetBSD,
|
||||||
LOGF_SysSolaris,
|
LOGF_SysSolaris,
|
||||||
LOGF_SysSunOS,
|
LOGF_SysSunOS,
|
||||||
|
LOGF_SysTimex,
|
||||||
LOGF_SysWinnt,
|
LOGF_SysWinnt,
|
||||||
LOGF_TempComp,
|
LOGF_TempComp,
|
||||||
LOGF_RtcLinux,
|
LOGF_RtcLinux,
|
||||||
LOGF_Refclock
|
LOGF_Refclock,
|
||||||
|
LOGF_Smooth,
|
||||||
} LOG_Facility;
|
} LOG_Facility;
|
||||||
|
|
||||||
/* Init function */
|
/* Init function */
|
||||||
@@ -110,10 +124,15 @@ extern void LOG_Initialise(void);
|
|||||||
extern void LOG_Finalise(void);
|
extern void LOG_Finalise(void);
|
||||||
|
|
||||||
/* Line logging function */
|
/* Line logging function */
|
||||||
|
#if DEBUG > 0
|
||||||
FORMAT_ATTRIBUTE_PRINTF(6, 7)
|
FORMAT_ATTRIBUTE_PRINTF(6, 7)
|
||||||
extern void LOG_Message(LOG_Severity severity, LOG_Facility facility,
|
extern void LOG_Message(LOG_Severity severity, LOG_Facility facility,
|
||||||
int line_number, const char *filename,
|
int line_number, const char *filename,
|
||||||
const char *function_name, const char *format, ...);
|
const char *function_name, const char *format, ...);
|
||||||
|
#else
|
||||||
|
FORMAT_ATTRIBUTE_PRINTF(2, 3)
|
||||||
|
extern void LOG_Message(LOG_Severity severity, const char *format, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set debug level:
|
/* Set debug level:
|
||||||
0, 1 - only non-debug messages are logged
|
0, 1 - only non-debug messages are logged
|
||||||
@@ -140,7 +159,6 @@ extern LOG_FileID LOG_FileOpen(const char *name, const char *banner);
|
|||||||
FORMAT_ATTRIBUTE_PRINTF(2, 3)
|
FORMAT_ATTRIBUTE_PRINTF(2, 3)
|
||||||
extern void LOG_FileWrite(LOG_FileID id, const char *format, ...);
|
extern void LOG_FileWrite(LOG_FileID id, const char *format, ...);
|
||||||
|
|
||||||
extern void LOG_CreateLogFileDir(void);
|
|
||||||
extern void LOG_CycleLogFiles(void);
|
extern void LOG_CycleLogFiles(void);
|
||||||
|
|
||||||
#endif /* GOT_LOGGING_H */
|
#endif /* GOT_LOGGING_H */
|
||||||
|
|||||||
73
main.c
73
main.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) John G. Hasler 2009
|
* Copyright (C) John G. Hasler 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2012-2014
|
* Copyright (C) Miroslav Lichvar 2012-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -49,7 +49,9 @@
|
|||||||
#include "refclock.h"
|
#include "refclock.h"
|
||||||
#include "clientlog.h"
|
#include "clientlog.h"
|
||||||
#include "nameserv.h"
|
#include "nameserv.h"
|
||||||
|
#include "smooth.h"
|
||||||
#include "tempcomp.h"
|
#include "tempcomp.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -88,14 +90,15 @@ MAI_CleanupAndExit(void)
|
|||||||
/* Don't update clock when removing sources */
|
/* Don't update clock when removing sources */
|
||||||
REF_SetMode(REF_ModeIgnore);
|
REF_SetMode(REF_ModeIgnore);
|
||||||
|
|
||||||
|
SMT_Finalise();
|
||||||
TMC_Finalise();
|
TMC_Finalise();
|
||||||
MNL_Finalise();
|
MNL_Finalise();
|
||||||
CLG_Finalise();
|
CLG_Finalise();
|
||||||
NSR_Finalise();
|
NSR_Finalise();
|
||||||
NCR_Finalise();
|
|
||||||
CAM_Finalise();
|
|
||||||
NIO_Finalise();
|
|
||||||
SST_Finalise();
|
SST_Finalise();
|
||||||
|
NCR_Finalise();
|
||||||
|
NIO_Finalise();
|
||||||
|
CAM_Finalise();
|
||||||
KEY_Finalise();
|
KEY_Finalise();
|
||||||
RCL_Finalise();
|
RCL_Finalise();
|
||||||
SRC_Finalise();
|
SRC_Finalise();
|
||||||
@@ -262,7 +265,7 @@ write_lockfile(void)
|
|||||||
if (!out) {
|
if (!out) {
|
||||||
LOG_FATAL(LOGF_Main, "could not open lockfile %s for writing", pidfile);
|
LOG_FATAL(LOGF_Main, "could not open lockfile %s for writing", pidfile);
|
||||||
} else {
|
} else {
|
||||||
fprintf(out, "%d\n", getpid());
|
fprintf(out, "%d\n", (int)getpid());
|
||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,11 +275,6 @@ write_lockfile(void)
|
|||||||
static void
|
static void
|
||||||
go_daemon(void)
|
go_daemon(void)
|
||||||
{
|
{
|
||||||
#ifdef WINNT
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int pid, fd, pipefd[2];
|
int pid, fd, pipefd[2];
|
||||||
|
|
||||||
/* Create pipe which will the daemon use to notify the grandparent
|
/* Create pipe which will the daemon use to notify the grandparent
|
||||||
@@ -335,8 +333,6 @@ go_daemon(void)
|
|||||||
LOG_SetParentFd(pipefd[1]);
|
LOG_SetParentFd(pipefd[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -345,11 +341,13 @@ int main
|
|||||||
(int argc, char **argv)
|
(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *conf_file = DEFAULT_CONF_FILE;
|
const char *conf_file = DEFAULT_CONF_FILE;
|
||||||
|
const char *progname = argv[0];
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
|
struct passwd *pw;
|
||||||
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
|
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
|
||||||
int do_init_rtc = 0, restarted = 0;
|
int do_init_rtc = 0, restarted = 0;
|
||||||
int other_pid;
|
int other_pid;
|
||||||
int lock_memory = 0, sched_priority = 0;
|
int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
|
||||||
int system_log = 1;
|
int system_log = 1;
|
||||||
int config_args = 0;
|
int config_args = 0;
|
||||||
|
|
||||||
@@ -379,12 +377,16 @@ int main
|
|||||||
} else {
|
} else {
|
||||||
user = *argv;
|
user = *argv;
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp("-F", *argv)) {
|
||||||
|
++argv, --argc;
|
||||||
|
if (argc == 0 || sscanf(*argv, "%d", &scfilter_level) != 1)
|
||||||
|
LOG_FATAL(LOGF_Main, "Bad syscall filter level");
|
||||||
} else if (!strcmp("-s", *argv)) {
|
} else if (!strcmp("-s", *argv)) {
|
||||||
do_init_rtc = 1;
|
do_init_rtc = 1;
|
||||||
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
|
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
|
||||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||||
printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
|
printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
|
||||||
exit(0);
|
return 0;
|
||||||
} else if (!strcmp("-n", *argv)) {
|
} else if (!strcmp("-n", *argv)) {
|
||||||
nofork = 1;
|
nofork = 1;
|
||||||
} else if (!strcmp("-d", *argv)) {
|
} else if (!strcmp("-d", *argv)) {
|
||||||
@@ -403,6 +405,10 @@ int main
|
|||||||
address_family = IPADDR_INET4;
|
address_family = IPADDR_INET4;
|
||||||
} else if (!strcmp("-6", *argv)) {
|
} else if (!strcmp("-6", *argv)) {
|
||||||
address_family = IPADDR_INET6;
|
address_family = IPADDR_INET6;
|
||||||
|
} else if (!strcmp("-h", *argv) || !strcmp("--help", *argv)) {
|
||||||
|
printf("Usage: %s [-4|-6] [-n|-d] [-q|-Q] [-r] [-R] [-s] [-f FILE|COMMAND...]\n",
|
||||||
|
progname);
|
||||||
|
return 0;
|
||||||
} else if (*argv[0] == '-') {
|
} else if (*argv[0] == '-') {
|
||||||
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
||||||
} else {
|
} else {
|
||||||
@@ -415,7 +421,7 @@ int main
|
|||||||
if (getuid() != 0) {
|
if (getuid() != 0) {
|
||||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||||
fprintf(stderr,"Not superuser\n");
|
fprintf(stderr,"Not superuser\n");
|
||||||
exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn into a daemon */
|
/* Turn into a daemon */
|
||||||
@@ -465,6 +471,12 @@ int main
|
|||||||
RCL_Initialise();
|
RCL_Initialise();
|
||||||
KEY_Initialise();
|
KEY_Initialise();
|
||||||
|
|
||||||
|
/* Open privileged ports before dropping root */
|
||||||
|
CAM_Initialise(address_family);
|
||||||
|
NIO_Initialise(address_family);
|
||||||
|
NCR_Initialise();
|
||||||
|
CNF_SetupAccessRestrictions();
|
||||||
|
|
||||||
/* Command-line switch must have priority */
|
/* Command-line switch must have priority */
|
||||||
if (!sched_priority) {
|
if (!sched_priority) {
|
||||||
sched_priority = CNF_GetSchedPriority();
|
sched_priority = CNF_GetSchedPriority();
|
||||||
@@ -480,26 +492,34 @@ int main
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
user = CNF_GetUser();
|
user = CNF_GetUser();
|
||||||
}
|
}
|
||||||
if (user && strcmp(user, "root")) {
|
|
||||||
SYS_DropRoot(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_CreateLogFileDir();
|
if ((pw = getpwnam(user)) == NULL)
|
||||||
|
LOG_FATAL(LOGF_Main, "Could not get %s uid/gid", user);
|
||||||
|
|
||||||
|
/* Create all directories before dropping root */
|
||||||
|
CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
|
||||||
|
|
||||||
|
/* Drop root privileges if the user has non-zero uid or gid */
|
||||||
|
if (pw->pw_uid || pw->pw_gid)
|
||||||
|
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
||||||
|
|
||||||
REF_Initialise();
|
REF_Initialise();
|
||||||
SST_Initialise();
|
SST_Initialise();
|
||||||
NIO_Initialise(address_family);
|
|
||||||
CAM_Initialise(address_family);
|
|
||||||
NCR_Initialise();
|
|
||||||
NSR_Initialise();
|
NSR_Initialise();
|
||||||
CLG_Initialise();
|
CLG_Initialise();
|
||||||
MNL_Initialise();
|
MNL_Initialise();
|
||||||
TMC_Initialise();
|
TMC_Initialise();
|
||||||
|
SMT_Initialise();
|
||||||
|
|
||||||
/* From now on, it is safe to do finalisation on exit */
|
/* From now on, it is safe to do finalisation on exit */
|
||||||
initialised = 1;
|
initialised = 1;
|
||||||
|
|
||||||
CNF_SetupAccessRestrictions();
|
UTI_SetQuitSignalsHandler(signal_cleanup);
|
||||||
|
|
||||||
|
CAM_OpenUnixSocket();
|
||||||
|
|
||||||
|
if (scfilter_level)
|
||||||
|
SYS_EnableSystemCallFilter(scfilter_level);
|
||||||
|
|
||||||
if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
|
if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
|
||||||
ref_mode = REF_ModeInitStepSlew;
|
ref_mode = REF_ModeInitStepSlew;
|
||||||
@@ -514,13 +534,6 @@ int main
|
|||||||
post_init_rtc_hook(NULL);
|
post_init_rtc_hook(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGINT, signal_cleanup);
|
|
||||||
signal(SIGTERM, signal_cleanup);
|
|
||||||
#if !defined(WINNT)
|
|
||||||
signal(SIGQUIT, signal_cleanup);
|
|
||||||
signal(SIGHUP, signal_cleanup);
|
|
||||||
#endif /* WINNT */
|
|
||||||
|
|
||||||
/* The program normally runs under control of the main loop in
|
/* The program normally runs under control of the main loop in
|
||||||
the scheduler. */
|
the scheduler. */
|
||||||
SCH_MainLoop();
|
SCH_MainLoop();
|
||||||
|
|||||||
20
make_release
20
make_release
@@ -39,16 +39,13 @@ echo $version > version.txt
|
|||||||
|
|
||||||
sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec
|
sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec
|
||||||
|
|
||||||
for m in chrony.1 chronyc.1.in chrony.conf.5.in chronyd.8.in; do
|
for m in chronyc.1.in chrony.conf.5.in chronyd.8.in; do
|
||||||
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
|
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
|
||||||
< $m > ${m}_
|
< $m > ${m}_
|
||||||
mv -f ${m}_ $m
|
mv -f ${m}_ $m
|
||||||
done
|
done
|
||||||
|
|
||||||
./configure && make chrony.txt || exit 1
|
./configure && make chrony.txt getdate.c || exit 1
|
||||||
mv chrony.txt chrony.txt_
|
|
||||||
make distclean
|
|
||||||
mv chrony.txt_ chrony.txt
|
|
||||||
|
|
||||||
awk '/^[1-9] Installation$/{p=1}
|
awk '/^[1-9] Installation$/{p=1}
|
||||||
/^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \
|
/^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \
|
||||||
@@ -59,16 +56,11 @@ if [ $(wc -l < INSTALL) -gt 100 -o $(wc -l < INSTALL) -lt 85 ]; then
|
|||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
awk '/^[1-9] Frequently asked questions$/{p=1}
|
a2x --lynx -f text doc/faq.adoc || exit 1
|
||||||
/^Appendix A GNU General Public License$/{exit}; p' chrony.txt | \
|
mv doc/faq.text FAQ
|
||||||
tail -n +4 | sed 's/^[1-9]\.\([1-9]\)/\1/' | sed 's/^----/--/' | \
|
rm -rf doc
|
||||||
sed 's/^====/==/' > FAQ
|
|
||||||
|
|
||||||
if [ $(wc -l < FAQ) -gt 400 -o $(wc -l < FAQ) -lt 200 ]; then
|
|
||||||
echo "FAQ generated incorrectly?"
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
make distclean
|
||||||
rm -f config.h config.log make_release .gitignore
|
rm -f config.h config.log make_release .gitignore
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
26
manual.c
26
manual.c
@@ -54,6 +54,8 @@ typedef struct {
|
|||||||
(measured-predicted)) */
|
(measured-predicted)) */
|
||||||
} Sample;
|
} Sample;
|
||||||
|
|
||||||
|
#define MIN_SAMPLE_SEPARATION 1.0
|
||||||
|
|
||||||
#define MAX_SAMPLES 16
|
#define MAX_SAMPLES 16
|
||||||
|
|
||||||
static Sample samples[16];
|
static Sample samples[16];
|
||||||
@@ -174,14 +176,24 @@ int
|
|||||||
MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
|
MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
|
||||||
{
|
{
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
double offset;
|
double offset, diff;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
|
||||||
/* Check whether timestamp is within margin of old one */
|
|
||||||
LCL_ReadCookedTime(&now, NULL);
|
LCL_ReadCookedTime(&now, NULL);
|
||||||
|
|
||||||
|
/* Make sure the provided timestamp is sane and the sample
|
||||||
|
is not too close to the last one */
|
||||||
|
|
||||||
|
if (!UTI_IsTimeOffsetSane(ts, 0.0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (n_samples) {
|
||||||
|
UTI_DiffTimevalsToDouble(&diff, &now, &samples[n_samples - 1].when);
|
||||||
|
if (diff < MIN_SAMPLE_SEPARATION)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&offset, &now, ts);
|
UTI_DiffTimevalsToDouble(&offset, &now, ts);
|
||||||
|
|
||||||
/* Check if buffer full up */
|
/* Check if buffer full up */
|
||||||
@@ -258,6 +270,14 @@ MNL_Reset(void)
|
|||||||
n_samples = 0;
|
n_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
MNL_IsEnabled(void)
|
||||||
|
{
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Generate report data for the REQ_MANUAL_LIST command/monitoring
|
/* Generate report data for the REQ_MANUAL_LIST command/monitoring
|
||||||
protocol */
|
protocol */
|
||||||
|
|||||||
1
manual.h
1
manual.h
@@ -38,6 +38,7 @@ extern int MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfre
|
|||||||
extern void MNL_Enable(void);
|
extern void MNL_Enable(void);
|
||||||
extern void MNL_Disable(void);
|
extern void MNL_Disable(void);
|
||||||
extern void MNL_Reset(void);
|
extern void MNL_Reset(void);
|
||||||
|
extern int MNL_IsEnabled(void);
|
||||||
|
|
||||||
extern void MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n);
|
extern void MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n);
|
||||||
extern int MNL_DeleteSample(int index);
|
extern int MNL_DeleteSample(int index);
|
||||||
|
|||||||
135
mkdirpp.c
135
mkdirpp.c
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
|
||||||
|
|
||||||
**********************************************************************
|
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
A function for creating a directory and any parent directories that
|
|
||||||
don't exist.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "sysincl.h"
|
|
||||||
|
|
||||||
#include "memory.h"
|
|
||||||
#include "mkdirpp.h"
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_dir(char *p)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
#if defined(TEST)
|
|
||||||
fprintf(stderr, "do_dir(%s)\n", p);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* See if directory exists */
|
|
||||||
status = stat(p, &buf);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
/* Try to create directory */
|
|
||||||
status = mkdir(p, 0755);
|
|
||||||
return status;
|
|
||||||
} else {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISDIR(buf.st_mode)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
/* Return 0 if the directory couldn't be created, 1 if it could (or
|
|
||||||
already existed) */
|
|
||||||
|
|
||||||
int
|
|
||||||
mkdir_and_parents(const char *path)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int len;
|
|
||||||
int i, j, k, last;
|
|
||||||
len = strlen(path);
|
|
||||||
|
|
||||||
p = (char *)Malloc(1 + len);
|
|
||||||
|
|
||||||
i = k = 0;
|
|
||||||
while (1) {
|
|
||||||
p[i++] = path[k++];
|
|
||||||
|
|
||||||
if (path[k] == '/' || !path[k]) {
|
|
||||||
p[i] = 0;
|
|
||||||
|
|
||||||
if (do_dir(p) < 0) {
|
|
||||||
Free(p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!path[k]) {
|
|
||||||
/* End of the string */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check whether its a trailing / or group of / */
|
|
||||||
last = 1;
|
|
||||||
j = k+1;
|
|
||||||
while (path[j]) {
|
|
||||||
if (path[j] != '/') {
|
|
||||||
k = j - 1; /* Pick up a / into p[] thru the assignment at the top of the loop */
|
|
||||||
last = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!path[k]) break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Free(p);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
#if defined(TEST)
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
if (argc > 1) {
|
|
||||||
/* Invert sense of result */
|
|
||||||
return mkdir_and_parents(argv[1]) ? 0 : 1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
31
mkdirpp.h
31
mkdirpp.h
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
|
||||||
|
|
||||||
**********************************************************************
|
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GOT_MKDIRPP_H
|
|
||||||
#define GOT_MKDIRPP_H
|
|
||||||
|
|
||||||
extern int mkdir_and_parents(const char *path);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -34,8 +34,7 @@
|
|||||||
typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything);
|
typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything);
|
||||||
|
|
||||||
/* Request resolving of a name to IP address. The handler will be
|
/* Request resolving of a name to IP address. The handler will be
|
||||||
called when the result is available, but it may be also called
|
called when the result is available. */
|
||||||
directly from this function call. */
|
|
||||||
extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything);
|
extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
5
ntp.h
5
ntp.h
@@ -109,4 +109,9 @@ typedef struct {
|
|||||||
#define NTP_LVM(leap, version, mode) \
|
#define NTP_LVM(leap, version, mode) \
|
||||||
((((leap) << 6) & 0xc0) | (((version) << 3) & 0x38) | ((mode) & 0x07))
|
((((leap) << 6) & 0xc0) | (((version) << 3) & 0x38) | ((mode) & 0x07))
|
||||||
|
|
||||||
|
/* Special NTP reference IDs */
|
||||||
|
#define NTP_REFID_UNSYNC 0x0UL
|
||||||
|
#define NTP_REFID_LOCAL 0x7F7F0101UL /* 127.127.1.1 */
|
||||||
|
#define NTP_REFID_SMOOTH 0x7F7F01FFUL /* 127.127.1.255 */
|
||||||
|
|
||||||
#endif /* GOT_NTP_H */
|
#endif /* GOT_NTP_H */
|
||||||
|
|||||||
70
ntp_core.c
70
ntp_core.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
#include "reference.h"
|
#include "reference.h"
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
#include "smooth.h"
|
||||||
#include "sources.h"
|
#include "sources.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
@@ -216,8 +217,9 @@ static ARR_Instance broadcasts;
|
|||||||
/* Invalid stratum number */
|
/* Invalid stratum number */
|
||||||
#define NTP_INVALID_STRATUM 0
|
#define NTP_INVALID_STRATUM 0
|
||||||
|
|
||||||
/* Minimum allowed poll interval */
|
/* Minimum and maximum allowed poll interval */
|
||||||
#define MIN_POLL 0
|
#define MIN_POLL 0
|
||||||
|
#define MAX_POLL 24
|
||||||
|
|
||||||
/* Kiss-o'-Death codes */
|
/* Kiss-o'-Death codes */
|
||||||
#define KOD_RATE 0x52415445UL /* RATE */
|
#define KOD_RATE 0x52415445UL /* RATE */
|
||||||
@@ -314,7 +316,7 @@ NCR_Initialise(void)
|
|||||||
do_time_checks();
|
do_time_checks();
|
||||||
|
|
||||||
logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
|
logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
|
||||||
" Date (UTC) Time IP Address L St 123 567 ABCD LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
" Date (UTC) Time IP Address L St 123 567 ABCD LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||||
: -1;
|
: -1;
|
||||||
|
|
||||||
access_auth_table = ADF_CreateTable();
|
access_auth_table = ADF_CreateTable();
|
||||||
@@ -444,9 +446,13 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
|||||||
result->minpoll = params->minpoll;
|
result->minpoll = params->minpoll;
|
||||||
if (result->minpoll < MIN_POLL)
|
if (result->minpoll < MIN_POLL)
|
||||||
result->minpoll = SRC_DEFAULT_MINPOLL;
|
result->minpoll = SRC_DEFAULT_MINPOLL;
|
||||||
|
else if (result->minpoll > MAX_POLL)
|
||||||
|
result->minpoll = MAX_POLL;
|
||||||
result->maxpoll = params->maxpoll;
|
result->maxpoll = params->maxpoll;
|
||||||
if (result->maxpoll < MIN_POLL)
|
if (result->maxpoll < MIN_POLL)
|
||||||
result->maxpoll = SRC_DEFAULT_MAXPOLL;
|
result->maxpoll = SRC_DEFAULT_MAXPOLL;
|
||||||
|
else if (result->maxpoll > MAX_POLL)
|
||||||
|
result->maxpoll = MAX_POLL;
|
||||||
if (result->maxpoll < result->minpoll)
|
if (result->maxpoll < result->minpoll)
|
||||||
result->maxpoll = result->minpoll;
|
result->maxpoll = result->minpoll;
|
||||||
|
|
||||||
@@ -757,14 +763,14 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
{
|
{
|
||||||
NTP_Packet message;
|
NTP_Packet message;
|
||||||
int leap, auth_len, length, ret;
|
int leap, auth_len, length, ret;
|
||||||
struct timeval local_transmit;
|
struct timeval local_receive, local_transmit;
|
||||||
|
|
||||||
/* Parameters read from reference module */
|
/* Parameters read from reference module */
|
||||||
int are_we_synchronised, our_stratum;
|
int are_we_synchronised, our_stratum, smooth_time;
|
||||||
NTP_Leap leap_status;
|
NTP_Leap leap_status;
|
||||||
uint32_t our_ref_id, ts_fuzz;
|
uint32_t our_ref_id, ts_fuzz;
|
||||||
struct timeval our_ref_time;
|
struct timeval our_ref_time;
|
||||||
double our_root_delay, our_root_dispersion;
|
double our_root_delay, our_root_dispersion, smooth_offset;
|
||||||
|
|
||||||
/* Don't reply with version higher than ours */
|
/* Don't reply with version higher than ours */
|
||||||
if (version > NTP_VERSION) {
|
if (version > NTP_VERSION) {
|
||||||
@@ -781,6 +787,28 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
&our_ref_id, &our_ref_time,
|
&our_ref_id, &our_ref_time,
|
||||||
&our_root_delay, &our_root_dispersion);
|
&our_root_delay, &our_root_dispersion);
|
||||||
|
|
||||||
|
/* Get current smoothing offset when sending packet to a client */
|
||||||
|
if (SMT_IsEnabled() && (my_mode == MODE_SERVER || my_mode == MODE_BROADCAST)) {
|
||||||
|
smooth_offset = SMT_GetOffset(&local_transmit);
|
||||||
|
smooth_time = fabs(smooth_offset) > LCL_GetSysPrecisionAsQuantum();
|
||||||
|
|
||||||
|
/* Suppress leap second when smoothing and slew mode are enabled */
|
||||||
|
if (REF_GetLeapMode() == REF_LeapModeSlew &&
|
||||||
|
(leap_status == LEAP_InsertSecond || leap_status == LEAP_DeleteSecond))
|
||||||
|
leap_status = LEAP_Normal;
|
||||||
|
} else {
|
||||||
|
smooth_time = 0;
|
||||||
|
smooth_offset = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smooth_time) {
|
||||||
|
our_ref_id = NTP_REFID_SMOOTH;
|
||||||
|
UTI_AddDoubleToTimeval(&our_ref_time, smooth_offset, &our_ref_time);
|
||||||
|
UTI_AddDoubleToTimeval(local_rx, smooth_offset, &local_receive);
|
||||||
|
} else {
|
||||||
|
local_receive = *local_rx;
|
||||||
|
}
|
||||||
|
|
||||||
if (are_we_synchronised) {
|
if (are_we_synchronised) {
|
||||||
leap = (int) leap_status;
|
leap = (int) leap_status;
|
||||||
} else {
|
} else {
|
||||||
@@ -804,9 +832,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
message.root_delay = UTI_DoubleToInt32(our_root_delay);
|
message.root_delay = UTI_DoubleToInt32(our_root_delay);
|
||||||
message.root_dispersion = UTI_DoubleToInt32(our_root_dispersion);
|
message.root_dispersion = UTI_DoubleToInt32(our_root_dispersion);
|
||||||
|
|
||||||
message.reference_id = htonl((NTP_int32) our_ref_id);
|
message.reference_id = htonl(our_ref_id);
|
||||||
|
|
||||||
/* Now fill in timestamps */
|
/* Now fill in timestamps */
|
||||||
|
|
||||||
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, 0);
|
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, 0);
|
||||||
|
|
||||||
/* Originate - this comes from the last packet the source sent us */
|
/* Originate - this comes from the last packet the source sent us */
|
||||||
@@ -816,7 +845,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
This timestamp will have been adjusted so that it will now look to
|
This timestamp will have been adjusted so that it will now look to
|
||||||
the source like we have been running on our latest estimate of
|
the source like we have been running on our latest estimate of
|
||||||
frequency all along */
|
frequency all along */
|
||||||
UTI_TimevalToInt64(local_rx, &message.receive_ts, 0);
|
UTI_TimevalToInt64(&local_receive, &message.receive_ts, 0);
|
||||||
|
|
||||||
/* Prepare random bits which will be added to the transmit timestamp. */
|
/* Prepare random bits which will be added to the transmit timestamp. */
|
||||||
ts_fuzz = UTI_GetNTPTsFuzz(message.precision);
|
ts_fuzz = UTI_GetNTPTsFuzz(message.precision);
|
||||||
@@ -826,6 +855,9 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
from the source we're sending to now. */
|
from the source we're sending to now. */
|
||||||
LCL_ReadCookedTime(&local_transmit, NULL);
|
LCL_ReadCookedTime(&local_transmit, NULL);
|
||||||
|
|
||||||
|
if (smooth_time)
|
||||||
|
UTI_AddDoubleToTimeval(&local_transmit, smooth_offset, &local_transmit);
|
||||||
|
|
||||||
length = NTP_NORMAL_PACKET_LENGTH;
|
length = NTP_NORMAL_PACKET_LENGTH;
|
||||||
|
|
||||||
/* Authenticate */
|
/* Authenticate */
|
||||||
@@ -1151,6 +1183,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||||||
association if not properly 'up'. */
|
association if not properly 'up'. */
|
||||||
test3 = (message->originate_ts.hi || message->originate_ts.lo) &&
|
test3 = (message->originate_ts.hi || message->originate_ts.lo) &&
|
||||||
(message->receive_ts.hi || message->receive_ts.lo) &&
|
(message->receive_ts.hi || message->receive_ts.lo) &&
|
||||||
|
(message->reference_ts.hi || message->reference_ts.lo) &&
|
||||||
(message->transmit_ts.hi || message->transmit_ts.lo);
|
(message->transmit_ts.hi || message->transmit_ts.lo);
|
||||||
|
|
||||||
/* Test 4 would check for denied access. It would always pass as this
|
/* Test 4 would check for denied access. It would always pass as this
|
||||||
@@ -1185,18 +1218,21 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||||||
kod_rate = 1;
|
kod_rate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Regardless of any validity checks we apply, we are required to
|
/* The transmit timestamp and local receive timestamp must not be saved when
|
||||||
save these fields from the packet into the ntp source instance record.
|
the authentication test failed to prevent denial-of-service attacks on
|
||||||
Note we can't do this assignment before test 1 has been carried out. */
|
symmetric associations using authentication */
|
||||||
inst->remote_orig = message->transmit_ts;
|
if (test5) {
|
||||||
inst->local_rx = *now;
|
inst->remote_orig = message->transmit_ts;
|
||||||
|
inst->local_rx = *now;
|
||||||
|
}
|
||||||
|
|
||||||
/* This protects against replay of the last packet we sent */
|
/* This protects against replay of the last packet we sent */
|
||||||
if (test2)
|
if (test2)
|
||||||
inst->local_ntp_tx.hi = inst->local_ntp_tx.lo = 0;
|
inst->local_ntp_tx.hi = inst->local_ntp_tx.lo = 0;
|
||||||
|
|
||||||
if (valid_packet) {
|
if (valid_packet) {
|
||||||
precision = LCL_GetSysPrecisionAsQuantum();
|
precision = LCL_GetSysPrecisionAsQuantum() +
|
||||||
|
UTI_Log2ToDouble(message->precision);
|
||||||
|
|
||||||
SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
|
SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
|
||||||
|
|
||||||
@@ -1243,7 +1279,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||||||
minimum one currently in the stats data register is less than an
|
minimum one currently in the stats data register is less than an
|
||||||
administrator-defined value */
|
administrator-defined value */
|
||||||
testB = inst->max_delay_ratio <= 1.0 ||
|
testB = inst->max_delay_ratio <= 1.0 ||
|
||||||
delay / SRC_MinRoundTripDelay(inst->source) > inst->max_delay_ratio;
|
delay / SRC_MinRoundTripDelay(inst->source) <= inst->max_delay_ratio;
|
||||||
|
|
||||||
/* Test C requires that the ratio of the increase in delay from the minimum
|
/* Test C requires that the ratio of the increase in delay from the minimum
|
||||||
one in the stats data register to the standard deviation of the offsets
|
one in the stats data register to the standard deviation of the offsets
|
||||||
@@ -1707,7 +1743,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
|
|||||||
void
|
void
|
||||||
NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
|
NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
|
||||||
{
|
{
|
||||||
if (new_minpoll < MIN_POLL)
|
if (new_minpoll < MIN_POLL || new_minpoll > MAX_POLL)
|
||||||
return;
|
return;
|
||||||
inst->minpoll = new_minpoll;
|
inst->minpoll = new_minpoll;
|
||||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
|
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
|
||||||
@@ -1720,7 +1756,7 @@ NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
|
|||||||
void
|
void
|
||||||
NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
|
NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
|
||||||
{
|
{
|
||||||
if (new_maxpoll < MIN_POLL)
|
if (new_maxpoll < MIN_POLL || new_maxpoll > MAX_POLL)
|
||||||
return;
|
return;
|
||||||
inst->maxpoll = new_maxpoll;
|
inst->maxpoll = new_maxpoll;
|
||||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
|
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
|
||||||
|
|||||||
13
ntp_io.c
13
ntp_io.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Timo Teras 2009
|
* Copyright (C) Timo Teras 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2014
|
* Copyright (C) Miroslav Lichvar 2009, 2013-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -97,8 +97,13 @@ prepare_socket(int family, int port_number, int client_only)
|
|||||||
sock_fd = socket(family, SOCK_DGRAM, 0);
|
sock_fd = socket(family, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
if (sock_fd < 0) {
|
if (sock_fd < 0) {
|
||||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
if (!client_only) {
|
||||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||||
|
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG(LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||||
|
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||||
|
}
|
||||||
return INVALID_SOCK_FD;
|
return INVALID_SOCK_FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +221,7 @@ prepare_socket(int family, int port_number, int client_only)
|
|||||||
/* Bind the socket if a port or address was specified */
|
/* Bind the socket if a port or address was specified */
|
||||||
if (my_addr_len > 0 && bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
if (my_addr_len > 0 && bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
|
||||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
|
||||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
UTI_SockaddrFamilyToString(family), strerror(errno));
|
||||||
close(sock_fd);
|
close(sock_fd);
|
||||||
return INVALID_SOCK_FD;
|
return INVALID_SOCK_FD;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ typedef struct {
|
|||||||
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
|
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
|
||||||
means this slot in table is in use */
|
means this slot in table is in use */
|
||||||
NCR_Instance data; /* Data for the protocol engine for this source */
|
NCR_Instance data; /* Data for the protocol engine for this source */
|
||||||
|
char *name; /* Name of the source, may be NULL */
|
||||||
int pool; /* Number of the pool from which was this source
|
int pool; /* Number of the pool from which was this source
|
||||||
added or INVALID_POOL */
|
added or INVALID_POOL */
|
||||||
int tentative; /* Flag indicating there was no valid response
|
int tentative; /* Flag indicating there was no valid response
|
||||||
@@ -85,6 +86,7 @@ struct UnresolvedSource {
|
|||||||
#define RESOLVE_INTERVAL_UNIT 7
|
#define RESOLVE_INTERVAL_UNIT 7
|
||||||
#define MIN_RESOLVE_INTERVAL 2
|
#define MIN_RESOLVE_INTERVAL 2
|
||||||
#define MAX_RESOLVE_INTERVAL 9
|
#define MAX_RESOLVE_INTERVAL 9
|
||||||
|
#define MIN_REPLACEMENT_INTERVAL 8
|
||||||
|
|
||||||
static struct UnresolvedSource *unresolved_sources = NULL;
|
static struct UnresolvedSource *unresolved_sources = NULL;
|
||||||
static int resolving_interval = 0;
|
static int resolving_interval = 0;
|
||||||
@@ -92,15 +94,11 @@ static SCH_TimeoutID resolving_id;
|
|||||||
static struct UnresolvedSource *resolving_source = NULL;
|
static struct UnresolvedSource *resolving_source = NULL;
|
||||||
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
||||||
|
|
||||||
#define MIN_POOL_RESOLVE_INTERVAL 5
|
|
||||||
#define MAX_POOL_SOURCES 16
|
#define MAX_POOL_SOURCES 16
|
||||||
#define INVALID_POOL (-1)
|
#define INVALID_POOL (-1)
|
||||||
|
|
||||||
/* Pool of sources, the name is expected to resolve to multiple addresses
|
/* Pool of sources with the same name */
|
||||||
which change over time */
|
|
||||||
struct SourcePool {
|
struct SourcePool {
|
||||||
char *name;
|
|
||||||
int port;
|
|
||||||
/* Number of sources added from this pool (ignoring tentative sources) */
|
/* Number of sources added from this pool (ignoring tentative sources) */
|
||||||
int sources;
|
int sources;
|
||||||
/* Maximum number of sources */
|
/* Maximum number of sources */
|
||||||
@@ -115,6 +113,7 @@ static ARR_Instance pools;
|
|||||||
|
|
||||||
static void resolve_sources(void *arg);
|
static void resolve_sources(void *arg);
|
||||||
static void rehash_records(void);
|
static void rehash_records(void);
|
||||||
|
static void clean_source_record(SourceRecord *record);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slew_sources(struct timeval *raw,
|
slew_sources(struct timeval *raw,
|
||||||
@@ -162,16 +161,12 @@ NSR_Finalise(void)
|
|||||||
struct UnresolvedSource *us;
|
struct UnresolvedSource *us;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(pools); i++)
|
|
||||||
Free(((struct SourcePool *)ARR_GetElement(pools, i))->name);
|
|
||||||
ARR_DestroyInstance(pools);
|
ARR_DestroyInstance(pools);
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||||
record = get_record(i);
|
record = get_record(i);
|
||||||
if (!record->remote_addr)
|
if (record->remote_addr)
|
||||||
continue;
|
clean_source_record(record);
|
||||||
record->remote_addr = NULL;
|
|
||||||
NCR_DestroyInstance(record->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ARR_DestroyInstance(records);
|
ARR_DestroyInstance(records);
|
||||||
@@ -296,7 +291,7 @@ rehash_records(void)
|
|||||||
|
|
||||||
/* Procedure to add a new source */
|
/* Procedure to add a new source */
|
||||||
static NSR_Status
|
static NSR_Status
|
||||||
add_source(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params, int pool)
|
add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, SourceParameters *params, int pool)
|
||||||
{
|
{
|
||||||
SourceRecord *record;
|
SourceRecord *record;
|
||||||
int slot, found;
|
int slot, found;
|
||||||
@@ -323,6 +318,7 @@ add_source(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParamete
|
|||||||
record = get_record(slot);
|
record = get_record(slot);
|
||||||
record->data = NCR_GetInstance(remote_addr, type, params);
|
record->data = NCR_GetInstance(remote_addr, type, params);
|
||||||
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
||||||
|
record->name = name ? Strdup(name) : NULL;
|
||||||
record->pool = pool;
|
record->pool = pool;
|
||||||
record->tentative = pool != INVALID_POOL ? 1 : 0;
|
record->tentative = pool != INVALID_POOL ? 1 : 0;
|
||||||
|
|
||||||
@@ -373,7 +369,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
|||||||
int i, added;
|
int i, added;
|
||||||
|
|
||||||
for (i = added = 0; i < n_addrs; i++) {
|
for (i = added = 0; i < n_addrs; i++) {
|
||||||
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(&ip_addrs[i]));
|
DEBUG_LOG(LOGF_NtpSources, "(%d) %s", i + 1, UTI_IPToString(&ip_addrs[i]));
|
||||||
|
|
||||||
address.ip_addr = ip_addrs[i];
|
address.ip_addr = ip_addrs[i];
|
||||||
address.port = us->port;
|
address.port = us->port;
|
||||||
@@ -382,7 +378,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
|||||||
if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse)
|
if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (add_source(&address, us->new_source.type, &us->new_source.params,
|
if (add_source(&address, us->name, us->new_source.type, &us->new_source.params,
|
||||||
us->new_source.pool) == NSR_Success)
|
us->new_source.pool) == NSR_Success)
|
||||||
added++;
|
added++;
|
||||||
|
|
||||||
@@ -403,6 +399,8 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *any
|
|||||||
|
|
||||||
assert(us == resolving_source);
|
assert(us == resolving_source);
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %d addrs", us->name, n_addrs);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case DNS_TryAgain:
|
case DNS_TryAgain:
|
||||||
break;
|
break;
|
||||||
@@ -495,7 +493,7 @@ append_unresolved_source(struct UnresolvedSource *us)
|
|||||||
NSR_Status
|
NSR_Status
|
||||||
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params)
|
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params)
|
||||||
{
|
{
|
||||||
return add_source(remote_addr, type, params, INVALID_POOL);
|
return add_source(remote_addr, NULL, type, params, INVALID_POOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -505,6 +503,15 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
|
|||||||
{
|
{
|
||||||
struct UnresolvedSource *us;
|
struct UnresolvedSource *us;
|
||||||
struct SourcePool *sp;
|
struct SourcePool *sp;
|
||||||
|
NTP_Remote_Address remote_addr;
|
||||||
|
|
||||||
|
/* If the name is an IP address, don't bother with full resolving now
|
||||||
|
or later when trying to replace the source */
|
||||||
|
if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
|
||||||
|
remote_addr.port = port;
|
||||||
|
NSR_AddSource(&remote_addr, type, params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
us = MallocNew(struct UnresolvedSource);
|
us = MallocNew(struct UnresolvedSource);
|
||||||
us->name = Strdup(name);
|
us->name = Strdup(name);
|
||||||
@@ -518,8 +525,6 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
|
|||||||
us->new_source.max_new_sources = 1;
|
us->new_source.max_new_sources = 1;
|
||||||
} else {
|
} else {
|
||||||
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
||||||
sp->name = Strdup(name);
|
|
||||||
sp->port = port;
|
|
||||||
sp->sources = 0;
|
sp->sources = 0;
|
||||||
sp->max_sources = params->max_sources;
|
sp->max_sources = params->max_sources;
|
||||||
us->new_source.pool = ARR_GetSize(pools) - 1;
|
us->new_source.pool = ARR_GetSize(pools) - 1;
|
||||||
@@ -587,6 +592,8 @@ clean_source_record(SourceRecord *record)
|
|||||||
assert(record->remote_addr);
|
assert(record->remote_addr);
|
||||||
record->remote_addr = NULL;
|
record->remote_addr = NULL;
|
||||||
NCR_DestroyInstance(record->data);
|
NCR_DestroyInstance(record->data);
|
||||||
|
if (record->name)
|
||||||
|
Free(record->name);
|
||||||
|
|
||||||
n_sources--;
|
n_sources--;
|
||||||
}
|
}
|
||||||
@@ -640,15 +647,18 @@ NSR_RemoveAllSources(void)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
resolve_pool_replacement(struct SourcePool *sp, NTP_Remote_Address *addr)
|
resolve_source_replacement(SourceRecord *record)
|
||||||
{
|
{
|
||||||
struct UnresolvedSource *us;
|
struct UnresolvedSource *us;
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_NtpSources, "trying to replace %s",
|
||||||
|
UTI_IPToString(&record->remote_addr->ip_addr));
|
||||||
|
|
||||||
us = MallocNew(struct UnresolvedSource);
|
us = MallocNew(struct UnresolvedSource);
|
||||||
us->name = Strdup(sp->name);
|
us->name = Strdup(record->name);
|
||||||
us->port = sp->port;
|
us->port = record->remote_addr->port;
|
||||||
us->replacement = 1;
|
us->replacement = 1;
|
||||||
us->replace_source = *addr;
|
us->replace_source = *record->remote_addr;
|
||||||
|
|
||||||
append_unresolved_source(us);
|
append_unresolved_source(us);
|
||||||
NSR_ResolveSources();
|
NSR_ResolveSources();
|
||||||
@@ -662,32 +672,50 @@ NSR_HandleBadSource(IPAddr *address)
|
|||||||
static struct timeval last_replacement;
|
static struct timeval last_replacement;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
NTP_Remote_Address remote_addr;
|
NTP_Remote_Address remote_addr;
|
||||||
struct SourcePool *pool;
|
SourceRecord *record;
|
||||||
int pool_index, slot, found;
|
int slot, found;
|
||||||
double diff;
|
double diff;
|
||||||
|
|
||||||
remote_addr.ip_addr = *address;
|
remote_addr.ip_addr = *address;
|
||||||
remote_addr.port = 0;
|
remote_addr.port = 0;
|
||||||
|
|
||||||
/* Only sources from a pool can be replaced */
|
|
||||||
find_slot(&remote_addr, &slot, &found);
|
find_slot(&remote_addr, &slot, &found);
|
||||||
if (!found || (pool_index = get_record(slot)->pool) == INVALID_POOL)
|
if (!found)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pool = (struct SourcePool *)ARR_GetElement(pools, pool_index);
|
record = get_record(slot);
|
||||||
|
|
||||||
/* Don't resolve the pool name too frequently */
|
/* Only sources with a name can be replaced */
|
||||||
|
if (!record->name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Don't resolve names too frequently */
|
||||||
SCH_GetLastEventTime(NULL, NULL, &now);
|
SCH_GetLastEventTime(NULL, NULL, &now);
|
||||||
UTI_DiffTimevalsToDouble(&diff, &now, &last_replacement);
|
UTI_DiffTimevalsToDouble(&diff, &now, &last_replacement);
|
||||||
if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_POOL_RESOLVE_INTERVAL)) {
|
if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_REPLACEMENT_INTERVAL)) {
|
||||||
DEBUG_LOG(LOGF_NtpSources, "replacement postponed");
|
DEBUG_LOG(LOGF_NtpSources, "replacement postponed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
last_replacement = now;
|
last_replacement = now;
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_NtpSources, "pool replacement for %s", UTI_IPToString(address));
|
resolve_source_replacement(record);
|
||||||
|
}
|
||||||
|
|
||||||
resolve_pool_replacement(pool, &remote_addr);
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
NSR_RefreshAddresses(void)
|
||||||
|
{
|
||||||
|
SourceRecord *record;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||||
|
record = get_record(i);
|
||||||
|
if (!record->remote_addr || !record->name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
resolve_source_replacement(record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -741,7 +769,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP
|
|||||||
pool->sources++;
|
pool->sources++;
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_NtpSources, "pool %s has %d confirmed sources",
|
DEBUG_LOG(LOGF_NtpSources, "pool %s has %d confirmed sources",
|
||||||
pool->name, pool->sources);
|
record->name, pool->sources);
|
||||||
|
|
||||||
/* If the number of sources reached the configured maximum, remove
|
/* If the number of sources reached the configured maximum, remove
|
||||||
the tentative sources added from this pool */
|
the tentative sources added from this pool */
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ extern void NSR_RemoveAllSources(void);
|
|||||||
/* Procedure to try to find a replacement for a bad source */
|
/* Procedure to try to find a replacement for a bad source */
|
||||||
extern void NSR_HandleBadSource(IPAddr *address);
|
extern void NSR_HandleBadSource(IPAddr *address);
|
||||||
|
|
||||||
|
/* Procedure to resolve all names again */
|
||||||
|
extern void NSR_RefreshAddresses(void);
|
||||||
|
|
||||||
/* This routine is called by ntp_io when a new packet arrives off the network */
|
/* This routine is called by ntp_io when a new packet arrives off the network */
|
||||||
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
||||||
|
|
||||||
|
|||||||
62
pktlength.c
62
pktlength.c
@@ -44,9 +44,8 @@ command_unpadded_length(CMD_Request *r)
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case REQ_NULL:
|
case REQ_NULL:
|
||||||
return offsetof(CMD_Request, data);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_ONLINE:
|
case REQ_ONLINE:
|
||||||
return offsetof(CMD_Request, data.online.EOR);
|
return offsetof(CMD_Request, data.online.EOR);
|
||||||
case REQ_OFFLINE:
|
case REQ_OFFLINE:
|
||||||
@@ -78,11 +77,11 @@ command_unpadded_length(CMD_Request *r)
|
|||||||
case REQ_MANUAL :
|
case REQ_MANUAL :
|
||||||
return offsetof(CMD_Request, data.manual.EOR);
|
return offsetof(CMD_Request, data.manual.EOR);
|
||||||
case REQ_N_SOURCES :
|
case REQ_N_SOURCES :
|
||||||
return offsetof(CMD_Request, data.n_sources.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_SOURCE_DATA :
|
case REQ_SOURCE_DATA :
|
||||||
return offsetof(CMD_Request, data.source_data.EOR);
|
return offsetof(CMD_Request, data.source_data.EOR);
|
||||||
case REQ_REKEY :
|
case REQ_REKEY :
|
||||||
return offsetof(CMD_Request, data.rekey.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_ALLOW :
|
case REQ_ALLOW :
|
||||||
return offsetof(CMD_Request, data.allow_deny.EOR);
|
return offsetof(CMD_Request, data.allow_deny.EOR);
|
||||||
case REQ_ALLOWALL :
|
case REQ_ALLOWALL :
|
||||||
@@ -110,21 +109,21 @@ command_unpadded_length(CMD_Request *r)
|
|||||||
case REQ_DEL_SOURCE :
|
case REQ_DEL_SOURCE :
|
||||||
return offsetof(CMD_Request, data.del_source.EOR);
|
return offsetof(CMD_Request, data.del_source.EOR);
|
||||||
case REQ_WRITERTC :
|
case REQ_WRITERTC :
|
||||||
return offsetof(CMD_Request, data.writertc.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_DFREQ :
|
case REQ_DFREQ :
|
||||||
return offsetof(CMD_Request, data.dfreq.EOR);
|
return offsetof(CMD_Request, data.dfreq.EOR);
|
||||||
case REQ_DOFFSET :
|
case REQ_DOFFSET :
|
||||||
return offsetof(CMD_Request, data.doffset.EOR);
|
return offsetof(CMD_Request, data.doffset.EOR);
|
||||||
case REQ_TRACKING :
|
case REQ_TRACKING :
|
||||||
return offsetof(CMD_Request, data.tracking.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_SOURCESTATS :
|
case REQ_SOURCESTATS :
|
||||||
return offsetof(CMD_Request, data.sourcestats.EOR);
|
return offsetof(CMD_Request, data.sourcestats.EOR);
|
||||||
case REQ_RTCREPORT :
|
case REQ_RTCREPORT :
|
||||||
return offsetof(CMD_Request, data.rtcreport.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_TRIMRTC :
|
case REQ_TRIMRTC :
|
||||||
return offsetof(CMD_Request, data.trimrtc.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_CYCLELOGS :
|
case REQ_CYCLELOGS :
|
||||||
return offsetof(CMD_Request, data.cyclelogs.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_SUBNETS_ACCESSED :
|
case REQ_SUBNETS_ACCESSED :
|
||||||
case REQ_CLIENT_ACCESSES:
|
case REQ_CLIENT_ACCESSES:
|
||||||
/* No longer supported */
|
/* No longer supported */
|
||||||
@@ -132,21 +131,27 @@ command_unpadded_length(CMD_Request *r)
|
|||||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||||
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
||||||
case REQ_MANUAL_LIST:
|
case REQ_MANUAL_LIST:
|
||||||
return offsetof(CMD_Request, data.manual_list.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_MANUAL_DELETE:
|
case REQ_MANUAL_DELETE:
|
||||||
return offsetof(CMD_Request, data.manual_delete.EOR);
|
return offsetof(CMD_Request, data.manual_delete.EOR);
|
||||||
case REQ_MAKESTEP:
|
case REQ_MAKESTEP:
|
||||||
return offsetof(CMD_Request, data.make_step.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_ACTIVITY:
|
case REQ_ACTIVITY:
|
||||||
return offsetof(CMD_Request, data.activity.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_RESELECT:
|
case REQ_RESELECT:
|
||||||
return offsetof(CMD_Request, data.reselect.EOR);
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
case REQ_RESELECTDISTANCE:
|
case REQ_RESELECTDISTANCE:
|
||||||
return offsetof(CMD_Request, data.reselect_distance.EOR);
|
return offsetof(CMD_Request, data.reselect_distance.EOR);
|
||||||
case REQ_MODIFY_MINSTRATUM:
|
case REQ_MODIFY_MINSTRATUM:
|
||||||
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
||||||
case REQ_MODIFY_POLLTARGET:
|
case REQ_MODIFY_POLLTARGET:
|
||||||
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
||||||
|
case REQ_SMOOTHING:
|
||||||
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
|
case REQ_SMOOTHTIME:
|
||||||
|
return offsetof(CMD_Request, data.smoothtime.EOR);
|
||||||
|
case REQ_REFRESH:
|
||||||
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
default:
|
default:
|
||||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -228,11 +233,11 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
|||||||
case REQ_MANUAL:
|
case REQ_MANUAL:
|
||||||
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
|
||||||
case REQ_N_SOURCES:
|
case REQ_N_SOURCES:
|
||||||
return PADDING_LENGTH(data.n_sources.EOR, data.n_sources.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.n_sources.EOR);
|
||||||
case REQ_SOURCE_DATA:
|
case REQ_SOURCE_DATA:
|
||||||
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
|
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
|
||||||
case REQ_REKEY:
|
case REQ_REKEY:
|
||||||
return PADDING_LENGTH(data.rekey.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_ALLOW:
|
case REQ_ALLOW:
|
||||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||||
case REQ_ALLOWALL:
|
case REQ_ALLOWALL:
|
||||||
@@ -260,21 +265,21 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
|||||||
case REQ_DEL_SOURCE:
|
case REQ_DEL_SOURCE:
|
||||||
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
|
||||||
case REQ_WRITERTC:
|
case REQ_WRITERTC:
|
||||||
return PADDING_LENGTH(data.writertc.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_DFREQ:
|
case REQ_DFREQ:
|
||||||
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
|
||||||
case REQ_DOFFSET:
|
case REQ_DOFFSET:
|
||||||
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
|
||||||
case REQ_TRACKING:
|
case REQ_TRACKING:
|
||||||
return PADDING_LENGTH(data.tracking.EOR, data.tracking.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.tracking.EOR);
|
||||||
case REQ_SOURCESTATS:
|
case REQ_SOURCESTATS:
|
||||||
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
|
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
|
||||||
case REQ_RTCREPORT:
|
case REQ_RTCREPORT:
|
||||||
return PADDING_LENGTH(data.rtcreport.EOR, data.rtc.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.rtc.EOR);
|
||||||
case REQ_TRIMRTC:
|
case REQ_TRIMRTC:
|
||||||
return PADDING_LENGTH(data.trimrtc.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_CYCLELOGS:
|
case REQ_CYCLELOGS:
|
||||||
return PADDING_LENGTH(data.cyclelogs.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_SUBNETS_ACCESSED:
|
case REQ_SUBNETS_ACCESSED:
|
||||||
case REQ_CLIENT_ACCESSES:
|
case REQ_CLIENT_ACCESSES:
|
||||||
/* No longer supported */
|
/* No longer supported */
|
||||||
@@ -282,21 +287,27 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
|||||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||||
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
|
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
|
||||||
case REQ_MANUAL_LIST:
|
case REQ_MANUAL_LIST:
|
||||||
return PADDING_LENGTH(data.manual_list.EOR, data.manual_list.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.manual_list.EOR);
|
||||||
case REQ_MANUAL_DELETE:
|
case REQ_MANUAL_DELETE:
|
||||||
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
|
||||||
case REQ_MAKESTEP:
|
case REQ_MAKESTEP:
|
||||||
return PADDING_LENGTH(data.make_step.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_ACTIVITY:
|
case REQ_ACTIVITY:
|
||||||
return PADDING_LENGTH(data.activity.EOR, data.activity.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.activity.EOR);
|
||||||
case REQ_RESELECT:
|
case REQ_RESELECT:
|
||||||
return PADDING_LENGTH(data.reselect.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
case REQ_RESELECTDISTANCE:
|
case REQ_RESELECTDISTANCE:
|
||||||
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
|
||||||
case REQ_MODIFY_MINSTRATUM:
|
case REQ_MODIFY_MINSTRATUM:
|
||||||
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
||||||
case REQ_MODIFY_POLLTARGET:
|
case REQ_MODIFY_POLLTARGET:
|
||||||
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
||||||
|
case REQ_SMOOTHING:
|
||||||
|
return PADDING_LENGTH(data.null.EOR, data.smoothing.EOR);
|
||||||
|
case REQ_SMOOTHTIME:
|
||||||
|
return PADDING_LENGTH(data.smoothtime.EOR, data.null.EOR);
|
||||||
|
case REQ_REFRESH:
|
||||||
|
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||||
default:
|
default:
|
||||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -360,7 +371,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
|||||||
}
|
}
|
||||||
case RPY_ACTIVITY:
|
case RPY_ACTIVITY:
|
||||||
return offsetof(CMD_Reply, data.activity.EOR);
|
return offsetof(CMD_Reply, data.activity.EOR);
|
||||||
|
case RPY_SMOOTHING:
|
||||||
|
return offsetof(CMD_Reply, data.smoothing.EOR);
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|||||||
22
refclock.c
22
refclock.c
@@ -226,7 +226,7 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
inst->ref_id = params->ref_id;
|
inst->ref_id = params->ref_id;
|
||||||
else {
|
else {
|
||||||
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
|
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
|
||||||
unsigned int index = ARR_GetSize(refclocks);
|
unsigned int index = ARR_GetSize(refclocks) - 1;
|
||||||
|
|
||||||
snprintf((char *)ref, sizeof (ref), "%3.3s", params->driver_name);
|
snprintf((char *)ref, sizeof (ref), "%3.3s", params->driver_name);
|
||||||
ref[3] = index % 10 + '0';
|
ref[3] = index % 10 + '0';
|
||||||
@@ -367,7 +367,9 @@ RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset,
|
|||||||
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
|
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
|
||||||
dispersion += instance->precision;
|
dispersion += instance->precision;
|
||||||
|
|
||||||
if (!valid_sample_time(instance, sample_time))
|
/* Make sure the timestamp and offset provided by the driver are sane */
|
||||||
|
if (!UTI_IsTimeOffsetSane(sample_time, offset) ||
|
||||||
|
!valid_sample_time(instance, sample_time))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
|
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
|
||||||
@@ -407,7 +409,8 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
|
|||||||
UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
|
UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
|
||||||
dispersion += instance->precision;
|
dispersion += instance->precision;
|
||||||
|
|
||||||
if (!valid_sample_time(instance, pulse_time))
|
if (!UTI_IsTimeOffsetSane(pulse_time, 0.0) ||
|
||||||
|
!valid_sample_time(instance, pulse_time))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rate = instance->pps_rate;
|
rate = instance->pps_rate;
|
||||||
@@ -496,15 +499,6 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
|
||||||
poll_interval(int poll)
|
|
||||||
{
|
|
||||||
if (poll >= 0)
|
|
||||||
return 1 << poll;
|
|
||||||
else
|
|
||||||
return 1.0 / (1 << -poll);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
valid_sample_time(RCL_Instance instance, struct timeval *tv)
|
valid_sample_time(RCL_Instance instance, struct timeval *tv)
|
||||||
{
|
{
|
||||||
@@ -513,7 +507,7 @@ valid_sample_time(RCL_Instance instance, struct timeval *tv)
|
|||||||
|
|
||||||
LCL_ReadRawTime(&raw_time);
|
LCL_ReadRawTime(&raw_time);
|
||||||
UTI_DiffTimevalsToDouble(&diff, &raw_time, tv);
|
UTI_DiffTimevalsToDouble(&diff, &raw_time, tv);
|
||||||
if (diff < 0.0 || diff > poll_interval(instance->poll + 1)) {
|
if (diff < 0.0 || diff > UTI_Log2ToDouble(instance->poll + 1)) {
|
||||||
DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f tv=%s",
|
DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f tv=%s",
|
||||||
UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv));
|
UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -592,7 +586,7 @@ poll_timeout(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst->timeout_id = SCH_AddTimeoutByDelay(poll_interval(poll), poll_timeout, arg);
|
inst->timeout_id = SCH_AddTimeoutByDelay(UTI_Log2ToDouble(poll), poll_timeout, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
201
reference.c
201
reference.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -50,7 +50,7 @@ static int our_leap_sec;
|
|||||||
static int our_stratum;
|
static int our_stratum;
|
||||||
static uint32_t our_ref_id;
|
static uint32_t our_ref_id;
|
||||||
static IPAddr our_ref_ip;
|
static IPAddr our_ref_ip;
|
||||||
struct timeval our_ref_time; /* Stored relative to reference, NOT local time */
|
struct timeval our_ref_time;
|
||||||
static double our_skew;
|
static double our_skew;
|
||||||
static double our_residual_freq;
|
static double our_residual_freq;
|
||||||
static double our_root_delay;
|
static double our_root_delay;
|
||||||
@@ -98,6 +98,17 @@ static double drift_file_age;
|
|||||||
|
|
||||||
static void update_drift_file(double, double);
|
static void update_drift_file(double, double);
|
||||||
|
|
||||||
|
/* Leap second handling mode */
|
||||||
|
static REF_LeapMode leap_mode;
|
||||||
|
|
||||||
|
/* Flag indicating the clock was recently corrected for leap second and it may
|
||||||
|
not have correct time yet (missing 23:59:60 in the UTC time scale) */
|
||||||
|
static int leap_in_progress;
|
||||||
|
|
||||||
|
/* Timer for the leap second handler */
|
||||||
|
static int leap_timer_running;
|
||||||
|
static SCH_TimeoutID leap_timeout_id;
|
||||||
|
|
||||||
/* Name of a system timezone containing leap seconds occuring at midnight */
|
/* Name of a system timezone containing leap seconds occuring at midnight */
|
||||||
static char *leap_tzname;
|
static char *leap_tzname;
|
||||||
static time_t last_tz_leap_check;
|
static time_t last_tz_leap_check;
|
||||||
@@ -109,11 +120,6 @@ static LOG_FileID logfileid;
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
/* Reference ID supplied when we are locally referenced */
|
|
||||||
#define LOCAL_REFERENCE_ID 0x7f7f0101UL
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* Exponential moving averages of absolute clock frequencies
|
/* Exponential moving averages of absolute clock frequencies
|
||||||
used as a fallback when synchronisation is lost. */
|
used as a fallback when synchronisation is lost. */
|
||||||
|
|
||||||
@@ -136,6 +142,7 @@ static double last_ref_update_interval;
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static NTP_Leap get_tz_leap(time_t when);
|
static NTP_Leap get_tz_leap(time_t when);
|
||||||
|
static void update_leap_status(NTP_Leap leap, time_t now, int reset);
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -148,6 +155,9 @@ handle_slew(struct timeval *raw,
|
|||||||
void *anything)
|
void *anything)
|
||||||
{
|
{
|
||||||
double delta;
|
double delta;
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
UTI_AdjustTimeval(&our_ref_time, cooked, &our_ref_time, &delta, dfreq, doffset);
|
||||||
|
|
||||||
if (change_type == LCL_ChangeUnknownStep) {
|
if (change_type == LCL_ChangeUnknownStep) {
|
||||||
last_ref_update.tv_sec = 0;
|
last_ref_update.tv_sec = 0;
|
||||||
@@ -155,6 +165,13 @@ handle_slew(struct timeval *raw,
|
|||||||
} else if (last_ref_update.tv_sec) {
|
} else if (last_ref_update.tv_sec) {
|
||||||
UTI_AdjustTimeval(&last_ref_update, cooked, &last_ref_update, &delta, dfreq, doffset);
|
UTI_AdjustTimeval(&last_ref_update, cooked, &last_ref_update, &delta, dfreq, doffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When the clock was stepped, check if that doesn't change our leap status
|
||||||
|
and also reset the leap timeout to undo the shift in the scheduler */
|
||||||
|
if (change_type != LCL_ChangeAdjust && our_leap_sec && !leap_in_progress) {
|
||||||
|
LCL_ReadRawTime(&now);
|
||||||
|
update_leap_status(our_leap_status, now.tv_sec, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -217,11 +234,18 @@ REF_Initialise(void)
|
|||||||
|
|
||||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
|
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
|
||||||
|
|
||||||
|
leap_timer_running = 0;
|
||||||
|
leap_in_progress = 0;
|
||||||
|
leap_mode = CNF_GetLeapSecMode();
|
||||||
|
/* Switch to step mode if the system driver doesn't support leap */
|
||||||
|
if (leap_mode == REF_LeapModeSystem && !LCL_CanSystemLeap())
|
||||||
|
leap_mode = REF_LeapModeStep;
|
||||||
|
|
||||||
leap_tzname = CNF_GetLeapSecTimezone();
|
leap_tzname = CNF_GetLeapSecTimezone();
|
||||||
if (leap_tzname) {
|
if (leap_tzname) {
|
||||||
/* Check that the timezone has good data for Jun 30 2008 and Dec 31 2008 */
|
/* Check that the timezone has good data for Jun 30 2012 and Dec 31 2012 */
|
||||||
if (get_tz_leap(1214784000) == LEAP_Normal &&
|
if (get_tz_leap(1341014400) == LEAP_InsertSecond &&
|
||||||
get_tz_leap(1230681600) == LEAP_InsertSecond) {
|
get_tz_leap(1356912000) == LEAP_Normal) {
|
||||||
LOG(LOGS_INFO, LOGF_Reference, "Using %s timezone to obtain leap second data", leap_tzname);
|
LOG(LOGS_INFO, LOGF_Reference, "Using %s timezone to obtain leap second data", leap_tzname);
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_Reference, "Timezone %s failed leap second check, ignoring", leap_tzname);
|
LOG(LOGS_WARN, LOGF_Reference, "Timezone %s failed leap second check, ignoring", leap_tzname);
|
||||||
@@ -263,9 +287,7 @@ REF_Initialise(void)
|
|||||||
void
|
void
|
||||||
REF_Finalise(void)
|
REF_Finalise(void)
|
||||||
{
|
{
|
||||||
if (our_leap_sec) {
|
update_leap_status(LEAP_Unsynchronised, 0, 0);
|
||||||
LCL_SetLeap(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drift_file) {
|
if (drift_file) {
|
||||||
update_drift_file(LCL_ReadAbsoluteFrequency(), our_skew);
|
update_drift_file(LCL_ReadAbsoluteFrequency(), our_skew);
|
||||||
@@ -301,6 +323,14 @@ REF_SetModeEndHandler(REF_ModeEndHandler handler)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
REF_LeapMode
|
||||||
|
REF_GetLeapMode(void)
|
||||||
|
{
|
||||||
|
return leap_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static double
|
static double
|
||||||
Sqr(double x)
|
Sqr(double x)
|
||||||
{
|
{
|
||||||
@@ -403,14 +433,10 @@ update_fb_drifts(double freq_ppm, double update_interval)
|
|||||||
fb_drift_timeout_id = -1;
|
fb_drift_timeout_id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_interval < 0.0 || update_interval > last_ref_update_interval * 4.0)
|
if (update_interval < 1.0 || update_interval > last_ref_update_interval * 4.0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < fb_drift_max - fb_drift_min + 1; i++) {
|
for (i = 0; i < fb_drift_max - fb_drift_min + 1; i++) {
|
||||||
/* Don't allow differences larger than 10 ppm */
|
|
||||||
if (fabs(freq_ppm - fb_drifts[i].freq) > 10.0)
|
|
||||||
fb_drifts[i].secs = 0.0;
|
|
||||||
|
|
||||||
secs = 1 << (i + fb_drift_min);
|
secs = 1 << (i + fb_drift_min);
|
||||||
if (fb_drifts[i].secs < secs) {
|
if (fb_drifts[i].secs < secs) {
|
||||||
/* Calculate average over 2 * secs interval before switching to
|
/* Calculate average over 2 * secs interval before switching to
|
||||||
@@ -436,11 +462,12 @@ update_fb_drifts(double freq_ppm, double update_interval)
|
|||||||
static void
|
static void
|
||||||
fb_drift_timeout(void *arg)
|
fb_drift_timeout(void *arg)
|
||||||
{
|
{
|
||||||
assert(are_we_synchronised == 0);
|
|
||||||
assert(next_fb_drift >= fb_drift_min && next_fb_drift <= fb_drift_max);
|
assert(next_fb_drift >= fb_drift_min && next_fb_drift <= fb_drift_max);
|
||||||
|
|
||||||
fb_drift_timeout_id = -1;
|
fb_drift_timeout_id = -1;
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_Reference, "Fallback drift %d active: %f ppm",
|
||||||
|
next_fb_drift, fb_drifts[next_fb_drift - fb_drift_min].freq);
|
||||||
LCL_SetAbsoluteFrequency(fb_drifts[next_fb_drift - fb_drift_min].freq);
|
LCL_SetAbsoluteFrequency(fb_drifts[next_fb_drift - fb_drift_min].freq);
|
||||||
REF_SetUnsynchronised();
|
REF_SetUnsynchronised();
|
||||||
}
|
}
|
||||||
@@ -657,7 +684,89 @@ get_tz_leap(time_t when)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_leap_status(NTP_Leap leap, time_t now)
|
leap_end_timeout(void *arg)
|
||||||
|
{
|
||||||
|
leap_timer_running = 0;
|
||||||
|
leap_in_progress = 0;
|
||||||
|
our_leap_sec = 0;
|
||||||
|
|
||||||
|
if (leap_mode == REF_LeapModeSystem)
|
||||||
|
LCL_SetSystemLeap(0);
|
||||||
|
|
||||||
|
if (our_leap_status == LEAP_InsertSecond ||
|
||||||
|
our_leap_status == LEAP_DeleteSecond)
|
||||||
|
our_leap_status = LEAP_Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
leap_start_timeout(void *arg)
|
||||||
|
{
|
||||||
|
leap_in_progress = 1;
|
||||||
|
|
||||||
|
switch (leap_mode) {
|
||||||
|
case REF_LeapModeSystem:
|
||||||
|
DEBUG_LOG(LOGF_Reference, "Waiting for system clock leap second correction");
|
||||||
|
break;
|
||||||
|
case REF_LeapModeSlew:
|
||||||
|
LCL_NotifyLeap(our_leap_sec);
|
||||||
|
LCL_AccumulateOffset(our_leap_sec, 0.0);
|
||||||
|
LOG(LOGS_WARN, LOGF_Reference, "Adjusting system clock for leap second");
|
||||||
|
break;
|
||||||
|
case REF_LeapModeStep:
|
||||||
|
LCL_NotifyLeap(our_leap_sec);
|
||||||
|
LCL_ApplyStepOffset(our_leap_sec);
|
||||||
|
LOG(LOGS_WARN, LOGF_Reference, "System clock was stepped for leap second");
|
||||||
|
break;
|
||||||
|
case REF_LeapModeIgnore:
|
||||||
|
LOG(LOGS_WARN, LOGF_Reference, "Ignoring leap second");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until the leap second is over with some extra room to be safe */
|
||||||
|
leap_timeout_id = SCH_AddTimeoutByDelay(2.0, leap_end_timeout, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_leap_timeout(time_t now)
|
||||||
|
{
|
||||||
|
struct timeval when;
|
||||||
|
|
||||||
|
/* Stop old timer if there is one */
|
||||||
|
if (leap_timer_running) {
|
||||||
|
SCH_RemoveTimeout(leap_timeout_id);
|
||||||
|
leap_timer_running = 0;
|
||||||
|
leap_in_progress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!our_leap_sec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Insert leap second at 0:00:00 UTC, delete at 23:59:59 UTC. If the clock
|
||||||
|
will be corrected by the system, timeout slightly sooner to be sure it
|
||||||
|
will happen before the system correction. */
|
||||||
|
when.tv_sec = (now / (24 * 3600) + 1) * (24 * 3600);
|
||||||
|
when.tv_usec = 0;
|
||||||
|
if (our_leap_sec < 0)
|
||||||
|
when.tv_sec--;
|
||||||
|
if (leap_mode == REF_LeapModeSystem) {
|
||||||
|
when.tv_sec--;
|
||||||
|
when.tv_usec = 500000;
|
||||||
|
}
|
||||||
|
|
||||||
|
leap_timeout_id = SCH_AddTimeout(&when, leap_start_timeout, NULL);
|
||||||
|
leap_timer_running = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_leap_status(NTP_Leap leap, time_t now, int reset)
|
||||||
{
|
{
|
||||||
int leap_sec;
|
int leap_sec;
|
||||||
|
|
||||||
@@ -681,8 +790,23 @@ update_leap_status(NTP_Leap leap, time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (leap_sec != our_leap_sec && !REF_IsLeapSecondClose()) {
|
if (leap_sec != our_leap_sec && !REF_IsLeapSecondClose()) {
|
||||||
LCL_SetLeap(leap_sec);
|
|
||||||
our_leap_sec = leap_sec;
|
our_leap_sec = leap_sec;
|
||||||
|
|
||||||
|
switch (leap_mode) {
|
||||||
|
case REF_LeapModeSystem:
|
||||||
|
LCL_SetSystemLeap(our_leap_sec);
|
||||||
|
/* Fall through */
|
||||||
|
case REF_LeapModeSlew:
|
||||||
|
case REF_LeapModeStep:
|
||||||
|
case REF_LeapModeIgnore:
|
||||||
|
set_leap_timeout(now);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (reset) {
|
||||||
|
set_leap_timeout(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
our_leap_status = leap;
|
our_leap_status = leap;
|
||||||
@@ -920,12 +1044,12 @@ REF_SetReference(int stratum,
|
|||||||
our_residual_freq = frequency;
|
our_residual_freq = frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_leap_status(leap, raw_now.tv_sec);
|
update_leap_status(leap, raw_now.tv_sec, 0);
|
||||||
maybe_log_offset(our_offset, raw_now.tv_sec);
|
maybe_log_offset(our_offset, raw_now.tv_sec);
|
||||||
|
|
||||||
if (step_offset != 0.0) {
|
if (step_offset != 0.0) {
|
||||||
LCL_ApplyStepOffset(step_offset);
|
if (LCL_ApplyStepOffset(step_offset))
|
||||||
LOG(LOGS_WARN, LOGF_Reference, "System clock was stepped by %.6f seconds", -step_offset);
|
LOG(LOGS_WARN, LOGF_Reference, "System clock was stepped by %.6f seconds", -step_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
LCL_SetSyncStatus(are_we_synchronised, offset_sd, offset_sd + root_delay / 2.0 + root_dispersion);
|
LCL_SetSyncStatus(are_we_synchronised, offset_sd, offset_sd + root_delay / 2.0 + root_dispersion);
|
||||||
@@ -955,6 +1079,7 @@ REF_SetReference(int stratum,
|
|||||||
/* Update fallback drifts */
|
/* Update fallback drifts */
|
||||||
if (fb_drifts) {
|
if (fb_drifts) {
|
||||||
update_fb_drifts(abs_freq_ppm, update_interval);
|
update_fb_drifts(abs_freq_ppm, update_interval);
|
||||||
|
schedule_fb_drift(&now);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_ref_update_interval = update_interval;
|
last_ref_update_interval = update_interval;
|
||||||
@@ -981,12 +1106,10 @@ REF_SetManualReference
|
|||||||
double skew
|
double skew
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint32_t manual_refid = 0x4D414E55; /* MANU */
|
|
||||||
|
|
||||||
/* We are not synchronised to an external source, as such. This is
|
/* We are not synchronised to an external source, as such. This is
|
||||||
only supposed to be used with the local source option, really
|
only supposed to be used with the local source option, really.
|
||||||
... */
|
Log as MANU in the tracking log, packets will have NTP_REFID_LOCAL. */
|
||||||
REF_SetReference(0, LEAP_Unsynchronised, 1, manual_refid, NULL,
|
REF_SetReference(0, LEAP_Unsynchronised, 1, 0x4D414E55UL, NULL,
|
||||||
ref_time, offset, 0.0, frequency, skew, 0.0, 0.0);
|
ref_time, offset, 0.0, frequency, skew, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,7 +1138,7 @@ REF_SetUnsynchronised(void)
|
|||||||
schedule_fb_drift(&now);
|
schedule_fb_drift(&now);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_leap_status(LEAP_Unsynchronised, 0);
|
update_leap_status(LEAP_Unsynchronised, 0, 0);
|
||||||
are_we_synchronised = 0;
|
are_we_synchronised = 0;
|
||||||
|
|
||||||
LCL_SetSyncStatus(0, 0.0, 0.0);
|
LCL_SetSyncStatus(0, 0.0, 0.0);
|
||||||
@@ -1061,7 +1184,7 @@ REF_GetReferenceParams
|
|||||||
UTI_DiffTimevalsToDouble(&elapsed, local_time, &our_ref_time);
|
UTI_DiffTimevalsToDouble(&elapsed, local_time, &our_ref_time);
|
||||||
extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed;
|
extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed;
|
||||||
|
|
||||||
*leap_status = our_leap_status;
|
*leap_status = !leap_in_progress ? our_leap_status : LEAP_Unsynchronised;
|
||||||
*ref_id = our_ref_id;
|
*ref_id = our_ref_id;
|
||||||
*ref_time = our_ref_time;
|
*ref_time = our_ref_time;
|
||||||
*root_delay = our_root_delay;
|
*root_delay = our_root_delay;
|
||||||
@@ -1072,7 +1195,7 @@ REF_GetReferenceParams
|
|||||||
*is_synchronised = 1;
|
*is_synchronised = 1;
|
||||||
|
|
||||||
*stratum = local_stratum;
|
*stratum = local_stratum;
|
||||||
*ref_id = LOCAL_REFERENCE_ID;
|
*ref_id = NTP_REFID_LOCAL;
|
||||||
/* Make the reference time be now less a second - this will
|
/* Make the reference time be now less a second - this will
|
||||||
scarcely affect the client, but will ensure that the transmit
|
scarcely affect the client, but will ensure that the transmit
|
||||||
timestamp cannot come before this (which would cause test 7 to
|
timestamp cannot come before this (which would cause test 7 to
|
||||||
@@ -1094,7 +1217,7 @@ REF_GetReferenceParams
|
|||||||
|
|
||||||
*leap_status = LEAP_Unsynchronised;
|
*leap_status = LEAP_Unsynchronised;
|
||||||
*stratum = NTP_MAX_STRATUM;
|
*stratum = NTP_MAX_STRATUM;
|
||||||
*ref_id = 0;
|
*ref_id = NTP_REFID_UNSYNC;
|
||||||
ref_time->tv_sec = ref_time->tv_usec = 0;
|
ref_time->tv_sec = ref_time->tv_usec = 0;
|
||||||
/* These values seem to be standard for a client, and
|
/* These values seem to be standard for a client, and
|
||||||
any peer or client of ours will ignore them anyway because
|
any peer or client of ours will ignore them anyway because
|
||||||
@@ -1121,6 +1244,14 @@ REF_GetOurStratum(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
double
|
||||||
|
REF_GetSkew(void)
|
||||||
|
{
|
||||||
|
return our_skew;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
REF_ModifyMaxupdateskew(double new_max_update_skew)
|
REF_ModifyMaxupdateskew(double new_max_update_skew)
|
||||||
{
|
{
|
||||||
@@ -1200,7 +1331,7 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
|
|||||||
LCL_GetOffsetCorrection(&now_raw, &correction, NULL);
|
LCL_GetOffsetCorrection(&now_raw, &correction, NULL);
|
||||||
UTI_AddDoubleToTimeval(&now_raw, correction, &now_cooked);
|
UTI_AddDoubleToTimeval(&now_raw, correction, &now_cooked);
|
||||||
|
|
||||||
rep->ref_id = 0;
|
rep->ref_id = NTP_REFID_UNSYNC;
|
||||||
rep->ip_addr.family = IPADDR_UNSPEC;
|
rep->ip_addr.family = IPADDR_UNSPEC;
|
||||||
rep->stratum = 0;
|
rep->stratum = 0;
|
||||||
rep->leap_status = our_leap_status;
|
rep->leap_status = our_leap_status;
|
||||||
@@ -1232,7 +1363,7 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
|
|||||||
|
|
||||||
} else if (enable_local_stratum) {
|
} else if (enable_local_stratum) {
|
||||||
|
|
||||||
rep->ref_id = LOCAL_REFERENCE_ID;
|
rep->ref_id = NTP_REFID_LOCAL;
|
||||||
rep->ip_addr.family = IPADDR_UNSPEC;
|
rep->ip_addr.family = IPADDR_UNSPEC;
|
||||||
rep->stratum = local_stratum;
|
rep->stratum = local_stratum;
|
||||||
rep->ref_time = now_cooked;
|
rep->ref_time = now_cooked;
|
||||||
|
|||||||
14
reference.h
14
reference.h
@@ -35,6 +35,14 @@
|
|||||||
#include "ntp.h"
|
#include "ntp.h"
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
|
|
||||||
|
/* Leap second handling modes */
|
||||||
|
typedef enum {
|
||||||
|
REF_LeapModeSystem,
|
||||||
|
REF_LeapModeSlew,
|
||||||
|
REF_LeapModeStep,
|
||||||
|
REF_LeapModeIgnore,
|
||||||
|
} REF_LeapMode;
|
||||||
|
|
||||||
/* Init function */
|
/* Init function */
|
||||||
extern void REF_Initialise(void);
|
extern void REF_Initialise(void);
|
||||||
|
|
||||||
@@ -61,6 +69,9 @@ typedef void (*REF_ModeEndHandler)(int result);
|
|||||||
/* Set the handler for being notified of mode ending */
|
/* Set the handler for being notified of mode ending */
|
||||||
extern void REF_SetModeEndHandler(REF_ModeEndHandler handler);
|
extern void REF_SetModeEndHandler(REF_ModeEndHandler handler);
|
||||||
|
|
||||||
|
/* Get leap second handling mode */
|
||||||
|
extern REF_LeapMode REF_GetLeapMode(void);
|
||||||
|
|
||||||
/* Function which takes a local cooked time and returns the estimated
|
/* Function which takes a local cooked time and returns the estimated
|
||||||
time of the reference. It also returns the other parameters
|
time of the reference. It also returns the other parameters
|
||||||
required for forming the outgoing NTP packet.
|
required for forming the outgoing NTP packet.
|
||||||
@@ -154,6 +165,9 @@ REF_SetUnsynchronised(void);
|
|||||||
synchronised */
|
synchronised */
|
||||||
extern int REF_GetOurStratum(void);
|
extern int REF_GetOurStratum(void);
|
||||||
|
|
||||||
|
/* Return the current skew */
|
||||||
|
extern double REF_GetSkew(void);
|
||||||
|
|
||||||
/* Modify the setting for the maximum skew we are prepared to allow updates on (in ppm). */
|
/* Modify the setting for the maximum skew we are prepared to allow updates on (in ppm). */
|
||||||
extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
|
extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
|
||||||
|
|
||||||
|
|||||||
10
reports.h
10
reports.h
@@ -112,4 +112,14 @@ typedef struct {
|
|||||||
int unresolved;
|
int unresolved;
|
||||||
} RPT_ActivityReport;
|
} RPT_ActivityReport;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int active;
|
||||||
|
int leap_only;
|
||||||
|
double offset;
|
||||||
|
double freq_ppm;
|
||||||
|
double wander_ppm;
|
||||||
|
double last_update_ago;
|
||||||
|
double remaining_time;
|
||||||
|
} RPT_SmoothingReport;
|
||||||
|
|
||||||
#endif /* GOT_REPORTS_H */
|
#endif /* GOT_REPORTS_H */
|
||||||
|
|||||||
62
rtc.c
62
rtc.c
@@ -39,11 +39,12 @@
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static int driver_initialised = 0;
|
static int driver_initialised = 0;
|
||||||
|
static int driver_preinit_ok = 0;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
int (*init)(void);
|
int (*init)(void);
|
||||||
void (*fini)(void);
|
void (*fini)(void);
|
||||||
int (*time_pre_init)(void);
|
int (*time_pre_init)(time_t driftfile_time);
|
||||||
void (*time_init)(void (*after_hook)(void*), void *anything);
|
void (*time_init)(void (*after_hook)(void*), void *anything);
|
||||||
void (*start_measurements)(void);
|
void (*start_measurements)(void);
|
||||||
int (*write_parameters)(void);
|
int (*write_parameters)(void);
|
||||||
@@ -73,29 +74,37 @@ static struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Set the system clock to the time of last modification of driftfile
|
/* Get the last modification time of the driftfile */
|
||||||
if it's in the future */
|
|
||||||
|
|
||||||
static void
|
static time_t
|
||||||
fallback_time_init(void)
|
get_driftfile_time(void)
|
||||||
{
|
{
|
||||||
struct timeval now;
|
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
char *drift_file;
|
char *drift_file;
|
||||||
|
|
||||||
drift_file = CNF_GetDriftFile();
|
drift_file = CNF_GetDriftFile();
|
||||||
if (!drift_file)
|
if (!drift_file)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (stat(drift_file, &buf))
|
if (stat(drift_file, &buf))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
|
return buf.st_mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
/* Set the system time to the driftfile time if it's in the future */
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_driftfile_time(time_t t)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
LCL_ReadCookedTime(&now, NULL);
|
LCL_ReadCookedTime(&now, NULL);
|
||||||
|
|
||||||
if (now.tv_sec < buf.st_mtime) {
|
if (now.tv_sec < t) {
|
||||||
LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
|
if (LCL_ApplyStepOffset(now.tv_sec - t))
|
||||||
LOG(LOGS_INFO, LOGF_Rtc,
|
LOG(LOGS_INFO, LOGF_Rtc, "System time restored from driftfile");
|
||||||
"System clock set from driftfile %s", drift_file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,15 +113,24 @@ fallback_time_init(void)
|
|||||||
void
|
void
|
||||||
RTC_Initialise(int initial_set)
|
RTC_Initialise(int initial_set)
|
||||||
{
|
{
|
||||||
|
time_t driftfile_time;
|
||||||
char *file_name;
|
char *file_name;
|
||||||
|
|
||||||
/* Do an initial read of the RTC and set the system time to it. This
|
/* If the -s option was specified, try to do an initial read of the RTC and
|
||||||
is analogous to what /sbin/hwclock -s would do on Linux. If that fails
|
set the system time to it. Also, read the last modification time of the
|
||||||
or RTC is not supported, set the clock to the time of the last
|
driftfile (i.e. system time when chronyd was previously stopped) and set
|
||||||
modification of driftfile, so we at least get closer to the truth. */
|
the system time to it if it's in the future to bring the clock closer to
|
||||||
|
the true time when the RTC is broken (e.g. it has no battery), is missing,
|
||||||
|
or there is no RTC driver. */
|
||||||
if (initial_set) {
|
if (initial_set) {
|
||||||
if (!driver.time_pre_init || !driver.time_pre_init()) {
|
driftfile_time = get_driftfile_time();
|
||||||
fallback_time_init();
|
|
||||||
|
if (driver.time_pre_init && driver.time_pre_init(driftfile_time)) {
|
||||||
|
driver_preinit_ok = 1;
|
||||||
|
} else {
|
||||||
|
driver_preinit_ok = 0;
|
||||||
|
if (driftfile_time)
|
||||||
|
apply_driftfile_time(driftfile_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,9 +168,9 @@ RTC_Finalise(void)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Start the processing to get a single measurement from the real time
|
/* Start the processing to get a single measurement from the real time
|
||||||
clock, and use it to trim the system time, based on knowing the
|
clock, and use it to trim the system time, based on knowing the
|
||||||
drift rate of the RTC and the error the last time we set it. The
|
drift rate of the RTC and the error the last time we set it. If the
|
||||||
TimePreInit routine has already run, so we can be sure that the
|
TimePreInit routine has succeeded, we can be sure that the trim required
|
||||||
trim required is not *too* large.
|
is not *too* large.
|
||||||
|
|
||||||
We are called with a hook to a function to be called after the
|
We are called with a hook to a function to be called after the
|
||||||
initialisation is complete. We also call this if we cannot do the
|
initialisation is complete. We also call this if we cannot do the
|
||||||
@@ -161,7 +179,7 @@ RTC_Finalise(void)
|
|||||||
void
|
void
|
||||||
RTC_TimeInit(void (*after_hook)(void *), void *anything)
|
RTC_TimeInit(void (*after_hook)(void *), void *anything)
|
||||||
{
|
{
|
||||||
if (driver_initialised) {
|
if (driver_initialised && driver_preinit_ok) {
|
||||||
(driver.time_init)(after_hook, anything);
|
(driver.time_init)(after_hook, anything);
|
||||||
} else {
|
} else {
|
||||||
(after_hook)(anything);
|
(after_hook)(anything);
|
||||||
|
|||||||
49
rtc_linux.c
49
rtc_linux.c
@@ -367,6 +367,9 @@ t_from_rtc(struct tm *stm) {
|
|||||||
t2 = mktime(&temp2);
|
t2 = mktime(&temp2);
|
||||||
diff = t2 - t1;
|
diff = t2 - t1;
|
||||||
|
|
||||||
|
if (t1 - diff == -1)
|
||||||
|
DEBUG_LOG(LOGF_RtcLinux, "Could not convert RTC time");
|
||||||
|
|
||||||
return t1 - diff;
|
return t1 - diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,13 +382,13 @@ read_hwclock_file(const char *hwclock_file)
|
|||||||
char line[256];
|
char line[256];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!hwclock_file)
|
if (!hwclock_file || !hwclock_file[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
in = fopen(hwclock_file, "r");
|
in = fopen(hwclock_file, "r");
|
||||||
if (!in) {
|
if (!in) {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not open hwclockfile %s",
|
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not open %s : %s",
|
||||||
hwclock_file);
|
hwclock_file, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +405,7 @@ read_hwclock_file(const char *hwclock_file)
|
|||||||
} else if (i == 3 && !strncmp(line, "UTC", 3)) {
|
} else if (i == 3 && !strncmp(line, "UTC", 3)) {
|
||||||
rtc_on_utc = 1;
|
rtc_on_utc = 1;
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read LOCAL/UTC setting from hwclockfile %s",
|
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read RTC LOCAL/UTC setting from %s",
|
||||||
hwclock_file);
|
hwclock_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +448,7 @@ read_coefs_from_file(void)
|
|||||||
&file_ref_offset,
|
&file_ref_offset,
|
||||||
&file_rate_ppm) == 4) {
|
&file_rate_ppm) == 4) {
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read coefficients from RTC file %s",
|
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read coefficients from %s",
|
||||||
coefs_file_name);
|
coefs_file_name);
|
||||||
}
|
}
|
||||||
fclose(in);
|
fclose(in);
|
||||||
@@ -607,14 +610,16 @@ switch_interrupts(int onoff)
|
|||||||
if (onoff) {
|
if (onoff) {
|
||||||
status = ioctl(fd, RTC_UIE_ON, 0);
|
status = ioctl(fd, RTC_UIE_ON, 0);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno));
|
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not %s RTC interrupt : %s",
|
||||||
|
"enable", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skip_interrupts = 1;
|
skip_interrupts = 1;
|
||||||
} else {
|
} else {
|
||||||
status = ioctl(fd, RTC_UIE_OFF, 0);
|
status = ioctl(fd, RTC_UIE_OFF, 0);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not stop measurement : %s", strerror(errno));
|
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not %s RTC interrupt : %s",
|
||||||
|
"disable", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,10 +699,11 @@ handle_initial_trim(void)
|
|||||||
/* sys_error_now is positive if the system clock is fast */
|
/* sys_error_now is positive if the system clock is fast */
|
||||||
sys_error_now = rtc_error_now - coef_seconds_fast;
|
sys_error_now = rtc_error_now - coef_seconds_fast;
|
||||||
|
|
||||||
LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now);
|
|
||||||
LCL_AccumulateOffset(sys_error_now, 0.0);
|
LCL_AccumulateOffset(sys_error_now, 0.0);
|
||||||
|
LOG(LOGS_INFO, LOGF_RtcLinux, "System clock off from RTC by %f seconds (slew)",
|
||||||
|
sys_error_now);
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time");
|
LOG(LOGS_WARN, LOGF_RtcLinux, "No valid rtcfile coefficients");
|
||||||
}
|
}
|
||||||
|
|
||||||
coefs_valid = 0;
|
coefs_valid = 0;
|
||||||
@@ -722,7 +728,7 @@ handle_relock_after_trim(void)
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
write_coefs_to_file(1,ref,fast,saved_coef_gain_rate);
|
write_coefs_to_file(1,ref,fast,saved_coef_gain_rate);
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not do regression after trim");
|
DEBUG_LOG(LOGF_RtcLinux, "Could not do regression after trim");
|
||||||
}
|
}
|
||||||
|
|
||||||
coefs_valid = 0;
|
coefs_valid = 0;
|
||||||
@@ -857,7 +863,6 @@ read_from_device(void *any)
|
|||||||
rtc_t = t_from_rtc(&rtc_tm);
|
rtc_t = t_from_rtc(&rtc_tm);
|
||||||
|
|
||||||
if (rtc_t == (time_t)(-1)) {
|
if (rtc_t == (time_t)(-1)) {
|
||||||
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not convert RTC time to timeval");
|
|
||||||
error = 1;
|
error = 1;
|
||||||
goto turn_off_interrupt;
|
goto turn_off_interrupt;
|
||||||
}
|
}
|
||||||
@@ -883,7 +888,7 @@ turn_off_interrupt:
|
|||||||
switch (operating_mode) {
|
switch (operating_mode) {
|
||||||
case OM_INITIAL:
|
case OM_INITIAL:
|
||||||
if (error) {
|
if (error) {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not complete initial step due to errors");
|
DEBUG_LOG(LOGF_RtcLinux, "Could not complete initial step due to errors");
|
||||||
operating_mode = OM_NORMAL;
|
operating_mode = OM_NORMAL;
|
||||||
(after_init_hook)(after_init_hook_arg);
|
(after_init_hook)(after_init_hook_arg);
|
||||||
|
|
||||||
@@ -897,7 +902,7 @@ turn_off_interrupt:
|
|||||||
|
|
||||||
case OM_AFTERTRIM:
|
case OM_AFTERTRIM:
|
||||||
if (error) {
|
if (error) {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not complete after trim relock due to errors");
|
DEBUG_LOG(LOGF_RtcLinux, "Could not complete after trim relock due to errors");
|
||||||
operating_mode = OM_NORMAL;
|
operating_mode = OM_NORMAL;
|
||||||
|
|
||||||
switch_interrupts(0);
|
switch_interrupts(0);
|
||||||
@@ -974,7 +979,7 @@ RTC_Linux_WriteParameters(void)
|
|||||||
RTC behaviour than we do for the rest of the module. */
|
RTC behaviour than we do for the rest of the module. */
|
||||||
|
|
||||||
int
|
int
|
||||||
RTC_Linux_TimePreInit(void)
|
RTC_Linux_TimePreInit(time_t driftfile_time)
|
||||||
{
|
{
|
||||||
int fd, status;
|
int fd, status;
|
||||||
struct rtc_time rtc_raw, rtc_raw_retry;
|
struct rtc_time rtc_raw, rtc_raw_retry;
|
||||||
@@ -1039,18 +1044,23 @@ RTC_Linux_TimePreInit(void)
|
|||||||
|
|
||||||
UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time);
|
UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time);
|
||||||
|
|
||||||
|
if (new_sys_time.tv_sec < driftfile_time) {
|
||||||
|
LOG(LOGS_WARN, LOGF_RtcLinux, "RTC time before last driftfile modification (ignored)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time);
|
UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time);
|
||||||
|
|
||||||
/* Set system time only if the step is larger than 1 second */
|
/* Set system time only if the step is larger than 1 second */
|
||||||
if (fabs(sys_offset) >= 1.0) {
|
if (fabs(sys_offset) >= 1.0) {
|
||||||
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
|
if (LCL_ApplyStepOffset(sys_offset))
|
||||||
accumulated_error);
|
LOG(LOGS_INFO, LOGF_RtcLinux, "System time set from RTC");
|
||||||
LCL_ApplyStepOffset(sys_offset);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1090,7 +1100,8 @@ RTC_Linux_Trim(void)
|
|||||||
|
|
||||||
if (fabs(coef_seconds_fast) > 1.0) {
|
if (fabs(coef_seconds_fast) > 1.0) {
|
||||||
|
|
||||||
LOG(LOGS_INFO, LOGF_RtcLinux, "Trimming RTC, error = %.3f seconds", coef_seconds_fast);
|
LOG(LOGS_INFO, LOGF_RtcLinux, "RTC wrong by %.3f seconds (step)",
|
||||||
|
coef_seconds_fast);
|
||||||
|
|
||||||
/* Do processing to set clock. Let R be the value we set the
|
/* Do processing to set clock. Let R be the value we set the
|
||||||
RTC to, then in 500ms the RTC ticks (R+1) (see comments in
|
RTC to, then in 500ms the RTC ticks (R+1) (see comments in
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
extern int RTC_Linux_Initialise(void);
|
extern int RTC_Linux_Initialise(void);
|
||||||
extern void RTC_Linux_Finalise(void);
|
extern void RTC_Linux_Finalise(void);
|
||||||
extern int RTC_Linux_TimePreInit(void);
|
extern int RTC_Linux_TimePreInit(time_t driftile_time);
|
||||||
extern void RTC_Linux_TimeInit(void (*after_hook)(void *), void *anything);
|
extern void RTC_Linux_TimeInit(void (*after_hook)(void *), void *anything);
|
||||||
extern void RTC_Linux_StartMeasurements(void);
|
extern void RTC_Linux_StartMeasurements(void);
|
||||||
|
|
||||||
|
|||||||
4
sched.c
4
sched.c
@@ -330,6 +330,10 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
|
|||||||
|
|
||||||
LCL_ReadRawTime(&now);
|
LCL_ReadRawTime(&now);
|
||||||
UTI_AddDoubleToTimeval(&now, delay, &then);
|
UTI_AddDoubleToTimeval(&now, delay, &then);
|
||||||
|
if (UTI_CompareTimevals(&now, &then) > 0) {
|
||||||
|
LOG_FATAL(LOGF_Scheduler, "Timeout overflow");
|
||||||
|
}
|
||||||
|
|
||||||
return SCH_AddTimeout(&then, handler, arg);
|
return SCH_AddTimeout(&then, handler, arg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
342
smooth.c
Normal file
342
smooth.c
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Routines implementing time smoothing.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "sysincl.h"
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "local.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "reference.h"
|
||||||
|
#include "smooth.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Time smoothing determines an offset that needs to be applied to the cooked
|
||||||
|
time to make it smooth for external observers. Observed offset and frequency
|
||||||
|
change slowly and there are no discontinuities. This can be used on an NTP
|
||||||
|
server to make it easier for the clients to track the time and keep their
|
||||||
|
clocks close together even when large offset or frequency corrections are
|
||||||
|
applied to the server's clock (e.g. after being offline for longer time).
|
||||||
|
|
||||||
|
Accumulated offset and frequency are smoothed out in three stages. In the
|
||||||
|
first stage, the frequency is changed at a constant rate (wander) up to a
|
||||||
|
maximum, in the second stage the frequency stays at the maximum for as long
|
||||||
|
as needed and in the third stage the frequency is brought back to zero.
|
||||||
|
|
||||||
|
|
|
||||||
|
max_freq +-------/--------\-------------
|
||||||
|
| /| |\
|
||||||
|
freq | / | | \
|
||||||
|
| / | | \
|
||||||
|
| / | | \
|
||||||
|
0 +--/----+--------+----\--------
|
||||||
|
| / | | | time
|
||||||
|
|/ | | |
|
||||||
|
|
||||||
|
stage 1 2 3
|
||||||
|
|
||||||
|
Integral of this function is the smoothed out offset. It's a continuous
|
||||||
|
piecewise polynomial with two quadratic parts and one linear.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct stage {
|
||||||
|
double wander;
|
||||||
|
double length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_STAGES 3
|
||||||
|
|
||||||
|
static struct stage stages[NUM_STAGES];
|
||||||
|
|
||||||
|
/* Enabled/disabled smoothing */
|
||||||
|
static int enabled;
|
||||||
|
|
||||||
|
/* Enabled/disabled mode where only leap seconds are smoothed out and normal
|
||||||
|
offset/frequency changes are ignored */
|
||||||
|
static int leap_only_mode;
|
||||||
|
|
||||||
|
/* Maximum skew/max_wander ratio to start updating offset and frequency */
|
||||||
|
#define UNLOCK_SKEW_WANDER_RATIO 10000
|
||||||
|
|
||||||
|
static int locked;
|
||||||
|
|
||||||
|
/* Maximum wander and frequency offset */
|
||||||
|
static double max_wander;
|
||||||
|
static double max_freq;
|
||||||
|
|
||||||
|
/* Frequency offset, time offset and the time of the last smoothing update */
|
||||||
|
static double smooth_freq;
|
||||||
|
static double smooth_offset;
|
||||||
|
static struct timeval last_update;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_smoothing(struct timeval *now, double *poffset, double *pfreq,
|
||||||
|
double *pwander)
|
||||||
|
{
|
||||||
|
double elapsed, length, offset, freq, wander;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
||||||
|
|
||||||
|
offset = smooth_offset;
|
||||||
|
freq = smooth_freq;
|
||||||
|
wander = 0.0;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_STAGES; i++) {
|
||||||
|
if (elapsed <= 0.0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
length = stages[i].length;
|
||||||
|
if (length >= elapsed)
|
||||||
|
length = elapsed;
|
||||||
|
|
||||||
|
wander = stages[i].wander;
|
||||||
|
offset -= length * (2.0 * freq + wander * length) / 2.0;
|
||||||
|
freq += wander * length;
|
||||||
|
elapsed -= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elapsed > 0.0) {
|
||||||
|
wander = 0.0;
|
||||||
|
offset -= elapsed * freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
*poffset = offset;
|
||||||
|
*pfreq = freq;
|
||||||
|
if (pwander)
|
||||||
|
*pwander = wander;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_stages(void)
|
||||||
|
{
|
||||||
|
double s1, s2, s, l1, l2, l3, lc, f, f2;
|
||||||
|
int i, dir;
|
||||||
|
|
||||||
|
/* Prepare the three stages so that the integral of the frequency offset
|
||||||
|
is equal to the offset that should be smoothed out */
|
||||||
|
|
||||||
|
s1 = smooth_offset / max_wander;
|
||||||
|
s2 = smooth_freq * smooth_freq / (2.0 * max_wander * max_wander);
|
||||||
|
|
||||||
|
l1 = l2 = l3 = 0.0;
|
||||||
|
|
||||||
|
/* Calculate the lengths of the 1st and 3rd stage assuming there is no
|
||||||
|
frequency limit. If length of the 1st stage comes out negative, switch
|
||||||
|
its direction. */
|
||||||
|
for (dir = -1; dir <= 1; dir += 2) {
|
||||||
|
s = dir * s1 + s2;
|
||||||
|
if (s >= 0.0) {
|
||||||
|
l3 = sqrt(s);
|
||||||
|
l1 = l3 - dir * smooth_freq / max_wander;
|
||||||
|
if (l1 >= 0.0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(dir <= 1 && l1 >= 0.0 && l3 >= 0.0);
|
||||||
|
|
||||||
|
/* If the limit was reached, shorten 1st+3rd stages and set a 2nd stage */
|
||||||
|
f = dir * smooth_freq + l1 * max_wander - max_freq;
|
||||||
|
if (f > 0.0) {
|
||||||
|
lc = f / max_wander;
|
||||||
|
|
||||||
|
/* No 1st stage if the frequency is already above the maximum */
|
||||||
|
if (lc > l1) {
|
||||||
|
lc = l1;
|
||||||
|
f2 = dir * smooth_freq;
|
||||||
|
} else {
|
||||||
|
f2 = max_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
l2 = lc * (2.0 + f / f2);
|
||||||
|
l1 -= lc;
|
||||||
|
l3 -= lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
stages[0].wander = dir * max_wander;
|
||||||
|
stages[0].length = l1;
|
||||||
|
stages[1].wander = 0.0;
|
||||||
|
stages[1].length = l2;
|
||||||
|
stages[2].wander = -dir * max_wander;
|
||||||
|
stages[2].length = l3;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_STAGES; i++) {
|
||||||
|
DEBUG_LOG(LOGF_Smooth, "Smooth stage %d wander %e length %f",
|
||||||
|
i + 1, stages[i].wander, stages[i].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_smoothing(struct timeval *now, double offset, double freq)
|
||||||
|
{
|
||||||
|
/* Don't accept offset/frequency until the clock has stabilized */
|
||||||
|
if (locked) {
|
||||||
|
if (REF_GetSkew() / max_wander < UNLOCK_SKEW_WANDER_RATIO || leap_only_mode)
|
||||||
|
SMT_Activate(now);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_smoothing(now, &smooth_offset, &smooth_freq, NULL);
|
||||||
|
smooth_offset += offset;
|
||||||
|
smooth_freq = (smooth_freq - freq) / (1.0 - freq);
|
||||||
|
last_update = *now;
|
||||||
|
|
||||||
|
update_stages();
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_Smooth, "Smooth offset %e freq %e", smooth_offset, smooth_freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_slew(struct timeval *raw, struct timeval *cooked, double dfreq,
|
||||||
|
double doffset, LCL_ChangeType change_type, void *anything)
|
||||||
|
{
|
||||||
|
double delta;
|
||||||
|
|
||||||
|
if (change_type == LCL_ChangeAdjust) {
|
||||||
|
if (leap_only_mode)
|
||||||
|
update_smoothing(cooked, 0.0, 0.0);
|
||||||
|
else
|
||||||
|
update_smoothing(cooked, doffset, dfreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTI_AdjustTimeval(&last_update, cooked, &last_update, &delta, dfreq, doffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMT_Initialise(void)
|
||||||
|
{
|
||||||
|
CNF_GetSmooth(&max_freq, &max_wander, &leap_only_mode);
|
||||||
|
if (max_freq <= 0.0 || max_wander <= 0.0) {
|
||||||
|
enabled = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = 1;
|
||||||
|
locked = 1;
|
||||||
|
|
||||||
|
/* Convert from ppm */
|
||||||
|
max_freq *= 1e-6;
|
||||||
|
max_wander *= 1e-6;
|
||||||
|
|
||||||
|
LCL_AddParameterChangeHandler(handle_slew, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMT_Finalise(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SMT_IsEnabled(void)
|
||||||
|
{
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
SMT_GetOffset(struct timeval *now)
|
||||||
|
{
|
||||||
|
double offset, freq;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
get_smoothing(now, &offset, &freq, NULL);
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMT_Activate(struct timeval *now)
|
||||||
|
{
|
||||||
|
if (!enabled || !locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated%s", leap_only_mode ?
|
||||||
|
" (leap seconds only)" : "");
|
||||||
|
locked = 0;
|
||||||
|
last_update = *now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMT_Reset(struct timeval *now)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
smooth_offset = 0.0;
|
||||||
|
smooth_freq = 0.0;
|
||||||
|
last_update = *now;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_STAGES; i++)
|
||||||
|
stages[i].wander = stages[i].length = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMT_Leap(struct timeval *now, int leap)
|
||||||
|
{
|
||||||
|
/* When the leap-only mode is disabled, the leap second will be accumulated
|
||||||
|
in handle_slew() as a normal offset */
|
||||||
|
if (!enabled || !leap_only_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
update_smoothing(now, leap, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now)
|
||||||
|
{
|
||||||
|
double length, elapsed;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
report->active = !locked;
|
||||||
|
report->leap_only = leap_only_mode;
|
||||||
|
|
||||||
|
get_smoothing(now, &report->offset, &report->freq_ppm, &report->wander_ppm);
|
||||||
|
|
||||||
|
/* Convert to ppm and negate (positive values mean faster/speeding up) */
|
||||||
|
report->freq_ppm *= -1.0e6;
|
||||||
|
report->wander_ppm *= -1.0e6;
|
||||||
|
|
||||||
|
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
||||||
|
if (!locked && elapsed >= 0.0) {
|
||||||
|
for (i = 0, length = 0.0; i < NUM_STAGES; i++)
|
||||||
|
length += stages[i].length;
|
||||||
|
report->last_update_ago = elapsed;
|
||||||
|
report->remaining_time = elapsed < length ? length - elapsed : 0.0;
|
||||||
|
} else {
|
||||||
|
report->last_update_ago = 0.0;
|
||||||
|
report->remaining_time = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -21,18 +21,28 @@
|
|||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Replacement strerror function for systems that don't have it
|
This module implements time smoothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#ifndef GOT_SMOOTH_H
|
||||||
|
#define GOT_SMOOTH_H
|
||||||
|
|
||||||
#ifdef SUNOS
|
#include "reports.h"
|
||||||
|
|
||||||
#include <errno.h>
|
extern void SMT_Initialise(void);
|
||||||
extern char *sys_errlist[];
|
|
||||||
|
|
||||||
char *strerror(int n) {
|
extern void SMT_Finalise(void);
|
||||||
return sys_errlist[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* SUNOS */
|
extern int SMT_IsEnabled(void);
|
||||||
|
|
||||||
|
extern double SMT_GetOffset(struct timeval *now);
|
||||||
|
|
||||||
|
extern void SMT_Activate(struct timeval *now);
|
||||||
|
|
||||||
|
extern void SMT_Reset(struct timeval *now);
|
||||||
|
|
||||||
|
extern void SMT_Leap(struct timeval *now, int leap);
|
||||||
|
|
||||||
|
extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
|
||||||
|
|
||||||
|
#endif
|
||||||
99
sources.c
99
sources.c
@@ -44,7 +44,6 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
#include "nameserv.h"
|
#include "nameserv.h"
|
||||||
#include "mkdirpp.h"
|
|
||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
#include "regress.h"
|
#include "regress.h"
|
||||||
|
|
||||||
@@ -71,6 +70,7 @@ typedef enum {
|
|||||||
SRC_OK, /* OK so far, not a final status! */
|
SRC_OK, /* OK so far, not a final status! */
|
||||||
SRC_UNSELECTABLE, /* Has noselect option set */
|
SRC_UNSELECTABLE, /* Has noselect option set */
|
||||||
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
||||||
|
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
|
||||||
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
||||||
SRC_STALE, /* Has older samples than others */
|
SRC_STALE, /* Has older samples than others */
|
||||||
SRC_FALSETICKER, /* Doesn't agree with others */
|
SRC_FALSETICKER, /* Doesn't agree with others */
|
||||||
@@ -156,6 +156,7 @@ static int selected_source_index; /* Which source index is currently
|
|||||||
/* Number of updates needed to reset the distant status */
|
/* Number of updates needed to reset the distant status */
|
||||||
#define DISTANT_PENALTY 32
|
#define DISTANT_PENALTY 32
|
||||||
|
|
||||||
|
static double max_distance;
|
||||||
static double reselect_distance;
|
static double reselect_distance;
|
||||||
static double stratum_weight;
|
static double stratum_weight;
|
||||||
static double combine_limit;
|
static double combine_limit;
|
||||||
@@ -180,6 +181,7 @@ void SRC_Initialise(void) {
|
|||||||
n_sources = 0;
|
n_sources = 0;
|
||||||
max_n_sources = 0;
|
max_n_sources = 0;
|
||||||
selected_source_index = INVALID_SOURCE;
|
selected_source_index = INVALID_SOURCE;
|
||||||
|
max_distance = CNF_GetMaxDistance();
|
||||||
reselect_distance = CNF_GetReselectDistance();
|
reselect_distance = CNF_GetReselectDistance();
|
||||||
stratum_weight = CNF_GetStratumWeight();
|
stratum_weight = CNF_GetStratumWeight();
|
||||||
combine_limit = CNF_GetCombineLimit();
|
combine_limit = CNF_GetCombineLimit();
|
||||||
@@ -513,7 +515,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
|||||||
{
|
{
|
||||||
struct timeval src_ref_time;
|
struct timeval src_ref_time;
|
||||||
double src_offset, src_offset_sd, src_frequency, src_skew;
|
double src_offset, src_offset_sd, src_frequency, src_skew;
|
||||||
double src_root_delay, src_root_dispersion, elapsed;
|
double src_root_delay, src_root_dispersion, sel_src_distance, elapsed;
|
||||||
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
|
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
|
||||||
double frequency_weight, sum_frequency_weight, sum_frequency, inv_sum2_skew;
|
double frequency_weight, sum_frequency_weight, sum_frequency, inv_sum2_skew;
|
||||||
int i, index, combined;
|
int i, index, combined;
|
||||||
@@ -524,6 +526,10 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
|||||||
sum_offset_weight = sum_offset = sum2_offset_sd = 0.0;
|
sum_offset_weight = sum_offset = sum2_offset_sd = 0.0;
|
||||||
sum_frequency_weight = sum_frequency = inv_sum2_skew = 0.0;
|
sum_frequency_weight = sum_frequency = inv_sum2_skew = 0.0;
|
||||||
|
|
||||||
|
sel_src_distance = sources[selected_source_index]->sel_info.root_distance;
|
||||||
|
if (sources[selected_source_index]->type == SRC_NTP)
|
||||||
|
sel_src_distance += reselect_distance;
|
||||||
|
|
||||||
for (i = combined = 0; i < n_sel_sources; i++) {
|
for (i = combined = 0; i < n_sel_sources; i++) {
|
||||||
index = sel_sources[i];
|
index = sel_sources[i];
|
||||||
SST_GetTrackingData(sources[index]->stats, &src_ref_time,
|
SST_GetTrackingData(sources[index]->stats, &src_ref_time,
|
||||||
@@ -536,8 +542,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
|||||||
are not close, or it was recently marked as distant */
|
are not close, or it was recently marked as distant */
|
||||||
|
|
||||||
if (index != selected_source_index &&
|
if (index != selected_source_index &&
|
||||||
(sources[index]->sel_info.root_distance > combine_limit *
|
(sources[index]->sel_info.root_distance > combine_limit * sel_src_distance ||
|
||||||
(reselect_distance + sources[selected_source_index]->sel_info.root_distance) ||
|
|
||||||
fabs(*frequency - src_frequency) >
|
fabs(*frequency - src_frequency) >
|
||||||
combine_limit * (*skew + src_skew + LCL_GetMaxClockError()))) {
|
combine_limit * (*skew + src_skew + LCL_GetMaxClockError()))) {
|
||||||
/* Use a smaller penalty in first few updates */
|
/* Use a smaller penalty in first few updates */
|
||||||
@@ -651,6 +656,12 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Require the root distance to be below the allowed maximum */
|
||||||
|
if (si->root_distance > max_distance) {
|
||||||
|
sources[i]->status = SRC_BAD_DISTANCE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sources[i]->status = SRC_OK; /* For now */
|
sources[i]->status = SRC_OK; /* For now */
|
||||||
|
|
||||||
if (sources[i]->reachability && max_reach_sample_ago < first_sample_ago)
|
if (sources[i]->reachability && max_reach_sample_ago < first_sample_ago)
|
||||||
@@ -804,43 +815,6 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* We now have a list of indices for the sources which pass the
|
|
||||||
false-ticker test. Now go on to reject those whose variance is
|
|
||||||
greater than the minimum distance of any other */
|
|
||||||
|
|
||||||
/* Find minimum distance */
|
|
||||||
index = sel_sources[0];
|
|
||||||
min_distance = sources[index]->sel_info.root_distance;
|
|
||||||
for (i = 1; i < n_sel_sources; i++) {
|
|
||||||
index = sel_sources[i];
|
|
||||||
distance = sources[index]->sel_info.root_distance;
|
|
||||||
if (distance < min_distance) {
|
|
||||||
min_distance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now go through and prune any NTP sources that have excessive
|
|
||||||
variance */
|
|
||||||
for (i = 0; i < n_sel_sources; i++) {
|
|
||||||
index = sel_sources[i];
|
|
||||||
if (sources[index]->type == SRC_NTP &&
|
|
||||||
sqrt(sources[index]->sel_info.variance) > min_distance) {
|
|
||||||
sel_sources[i] = INVALID_SOURCE;
|
|
||||||
sources[index]->status = SRC_JITTERY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now crunch the list and mark all sources as selectable */
|
|
||||||
for (i = j = 0; i < n_sel_sources; i++) {
|
|
||||||
index = sel_sources[i];
|
|
||||||
if (index == INVALID_SOURCE)
|
|
||||||
continue;
|
|
||||||
sel_sources[j++] = index;
|
|
||||||
}
|
|
||||||
n_sel_sources = j;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) {
|
if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) {
|
||||||
if (selected_source_index != INVALID_SOURCE) {
|
if (selected_source_index != INVALID_SOURCE) {
|
||||||
log_selection_message("Can't synchronise: %s selectable sources",
|
log_selection_message("Can't synchronise: %s selectable sources",
|
||||||
@@ -869,16 +843,18 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||||||
|
|
||||||
/* If there are any sources with prefer option, reduce the list again
|
/* If there are any sources with prefer option, reduce the list again
|
||||||
only to the preferred sources */
|
only to the preferred sources */
|
||||||
for (i = j = 0; i < n_sel_sources; i++) {
|
for (i = 0; i < n_sel_sources; i++) {
|
||||||
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer)
|
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer)
|
||||||
sel_sources[j++] = sel_sources[i];
|
break;
|
||||||
}
|
}
|
||||||
|
if (i < n_sel_sources) {
|
||||||
if (j > 0) {
|
for (i = j = 0; i < n_sel_sources; i++) {
|
||||||
for (i = 0; i < n_sel_sources; i++) {
|
|
||||||
if (sources[sel_sources[i]]->sel_option != SRC_SelectPrefer)
|
if (sources[sel_sources[i]]->sel_option != SRC_SelectPrefer)
|
||||||
sources[sel_sources[i]]->status = SRC_NONPREFERRED;
|
sources[sel_sources[i]]->status = SRC_NONPREFERRED;
|
||||||
|
else
|
||||||
|
sel_sources[j++] = sel_sources[i];
|
||||||
}
|
}
|
||||||
|
assert(j > 0);
|
||||||
n_sel_sources = j;
|
n_sel_sources = j;
|
||||||
sel_prefer = 1;
|
sel_prefer = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -1125,25 +1101,23 @@ SRC_DumpSources(void)
|
|||||||
direc_len = strlen(direc);
|
direc_len = strlen(direc);
|
||||||
file_len = direc_len + 24;
|
file_len = direc_len + 24;
|
||||||
filename = MallocArray(char, file_len); /* a bit of slack */
|
filename = MallocArray(char, file_len); /* a bit of slack */
|
||||||
if (mkdir_and_parents(direc)) {
|
|
||||||
for (i=0; i<n_sources; i++) {
|
|
||||||
a = (sources[i]->ref_id) >> 24;
|
|
||||||
b = ((sources[i]->ref_id) >> 16) & 0xff;
|
|
||||||
c = ((sources[i]->ref_id) >> 8) & 0xff;
|
|
||||||
d = ((sources[i]->ref_id)) & 0xff;
|
|
||||||
|
|
||||||
snprintf(filename, file_len-1, "%s/%d.%d.%d.%d.dat", direc, a, b, c, d);
|
for (i = 0; i < n_sources; i++) {
|
||||||
out = fopen(filename, "w");
|
a = (sources[i]->ref_id) >> 24;
|
||||||
if (!out) {
|
b = ((sources[i]->ref_id) >> 16) & 0xff;
|
||||||
LOG(LOGS_WARN, LOGF_Sources, "Could not open dump file %s", filename);
|
c = ((sources[i]->ref_id) >> 8) & 0xff;
|
||||||
} else {
|
d = ((sources[i]->ref_id)) & 0xff;
|
||||||
SST_SaveToFile(sources[i]->stats, out);
|
|
||||||
fclose(out);
|
snprintf(filename, file_len - 1, "%s/%d.%d.%d.%d.dat", direc, a, b, c, d);
|
||||||
}
|
out = fopen(filename, "w");
|
||||||
|
if (!out) {
|
||||||
|
LOG(LOGS_WARN, LOGF_Sources, "Could not open dump file %s", filename);
|
||||||
|
} else {
|
||||||
|
SST_SaveToFile(sources[i]->stats, out);
|
||||||
|
fclose(out);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG(LOGS_ERR, LOGF_Sources, "Could not create directory %s", direc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Free(filename);
|
Free(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1251,6 +1225,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
|
|||||||
switch (src->status) {
|
switch (src->status) {
|
||||||
case SRC_UNSELECTABLE:
|
case SRC_UNSELECTABLE:
|
||||||
case SRC_BAD_STATS:
|
case SRC_BAD_STATS:
|
||||||
|
case SRC_BAD_DISTANCE:
|
||||||
case SRC_STALE:
|
case SRC_STALE:
|
||||||
case SRC_WAITS_STATS:
|
case SRC_WAITS_STATS:
|
||||||
report->state = RPT_UNREACH;
|
report->state = RPT_UNREACH;
|
||||||
|
|||||||
@@ -634,14 +634,14 @@ SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffs
|
|||||||
inst->offsets[i] += delta_time;
|
inst->offsets[i] += delta_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do a half-baked update to the regression estimates */
|
/* Update the regression estimates */
|
||||||
prev = inst->offset_time;
|
prev = inst->offset_time;
|
||||||
prev_offset = inst->estimated_offset;
|
prev_offset = inst->estimated_offset;
|
||||||
prev_freq = inst->estimated_frequency;
|
prev_freq = inst->estimated_frequency;
|
||||||
UTI_AdjustTimeval(&(inst->offset_time), when, &(inst->offset_time),
|
UTI_AdjustTimeval(&(inst->offset_time), when, &(inst->offset_time),
|
||||||
&delta_time, dfreq, doffset);
|
&delta_time, dfreq, doffset);
|
||||||
inst->estimated_offset += delta_time;
|
inst->estimated_offset += delta_time;
|
||||||
inst->estimated_frequency -= dfreq;
|
inst->estimated_frequency = (inst->estimated_frequency - dfreq) / (1.0 - dfreq);
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_SourceStats, "n=%d m=%d old_off_time=%s new=%s old_off=%f new_off=%f old_freq=%.3f new_freq=%.3f",
|
DEBUG_LOG(LOGF_SourceStats, "n=%d m=%d old_off_time=%s new=%s old_off=%f new_off=%f old_freq=%.3f new_freq=%.3f",
|
||||||
inst->n_samples, inst->runs_samples,
|
inst->n_samples, inst->runs_samples,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ typedef struct {
|
|||||||
#define SRC_DEFAULT_MINPOLL 6
|
#define SRC_DEFAULT_MINPOLL 6
|
||||||
#define SRC_DEFAULT_MAXPOLL 10
|
#define SRC_DEFAULT_MAXPOLL 10
|
||||||
#define SRC_DEFAULT_PRESEND_MINPOLL 0
|
#define SRC_DEFAULT_PRESEND_MINPOLL 0
|
||||||
#define SRC_DEFAULT_MAXDELAY 16.0
|
#define SRC_DEFAULT_MAXDELAY 3.0
|
||||||
#define SRC_DEFAULT_MAXDELAYRATIO 0.0
|
#define SRC_DEFAULT_MAXDELAYRATIO 0.0
|
||||||
#define SRC_DEFAULT_MAXDELAYDEVRATIO 10.0
|
#define SRC_DEFAULT_MAXDELAYDEVRATIO 10.0
|
||||||
#define SRC_DEFAULT_MINSTRATUM 0
|
#define SRC_DEFAULT_MINSTRATUM 0
|
||||||
|
|||||||
47
stubs.c
47
stubs.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 2014
|
* Copyright (C) Miroslav Lichvar 2014-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -32,12 +32,14 @@
|
|||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "manual.h"
|
#include "manual.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "nameserv.h"
|
#include "nameserv.h"
|
||||||
#include "nameserv_async.h"
|
#include "nameserv_async.h"
|
||||||
#include "ntp_core.h"
|
#include "ntp_core.h"
|
||||||
#include "ntp_io.h"
|
#include "ntp_io.h"
|
||||||
#include "ntp_sources.h"
|
#include "ntp_sources.h"
|
||||||
#include "refclock.h"
|
#include "refclock.h"
|
||||||
|
#include "sched.h"
|
||||||
|
|
||||||
#ifndef FEAT_ASYNCDNS
|
#ifndef FEAT_ASYNCDNS
|
||||||
|
|
||||||
@@ -45,20 +47,43 @@
|
|||||||
|
|
||||||
/* This is a blocking implementation used when asynchronous resolving is not available */
|
/* This is a blocking implementation used when asynchronous resolving is not available */
|
||||||
|
|
||||||
void
|
struct DNS_Async_Instance {
|
||||||
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
|
const char *name;
|
||||||
|
DNS_NameResolveHandler handler;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
resolve_name(void *anything)
|
||||||
{
|
{
|
||||||
|
struct DNS_Async_Instance *inst;
|
||||||
IPAddr addrs[MAX_ADDRESSES];
|
IPAddr addrs[MAX_ADDRESSES];
|
||||||
DNS_Status status;
|
DNS_Status status;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
status = DNS_Name2IPAddress(name, addrs, MAX_ADDRESSES);
|
inst = (struct DNS_Async_Instance *)anything;
|
||||||
|
status = DNS_Name2IPAddress(inst->name, addrs, MAX_ADDRESSES);
|
||||||
|
|
||||||
for (i = 0; status == DNS_Success && i < MAX_ADDRESSES &&
|
for (i = 0; status == DNS_Success && i < MAX_ADDRESSES &&
|
||||||
addrs[i].family != IPADDR_UNSPEC; i++)
|
addrs[i].family != IPADDR_UNSPEC; i++)
|
||||||
;
|
;
|
||||||
|
|
||||||
(handler)(status, i, addrs, anything);
|
(inst->handler)(status, i, addrs, inst->arg);
|
||||||
|
|
||||||
|
Free(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
|
||||||
|
{
|
||||||
|
struct DNS_Async_Instance *inst;
|
||||||
|
|
||||||
|
inst = MallocNew(struct DNS_Async_Instance);
|
||||||
|
inst->name = name;
|
||||||
|
inst->handler = handler;
|
||||||
|
inst->arg = anything;
|
||||||
|
|
||||||
|
SCH_AddTimeoutByDelay(0.0, resolve_name, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !FEAT_ASYNCDNS */
|
#endif /* !FEAT_ASYNCDNS */
|
||||||
@@ -75,6 +100,11 @@ CAM_Finalise(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CAM_OpenUnixSocket(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
|
CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
|
||||||
{
|
{
|
||||||
@@ -169,6 +199,11 @@ NSR_HandleBadSource(IPAddr *address)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSR_RefreshAddresses(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
|
NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
|
||||||
{
|
{
|
||||||
|
|||||||
72
sys.c
72
sys.c
@@ -27,23 +27,21 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "sysincl.h"
|
||||||
|
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
#if defined (LINUX)
|
#if defined(LINUX)
|
||||||
#include "sys_linux.h"
|
#include "sys_linux.h"
|
||||||
#endif
|
#elif defined(SOLARIS)
|
||||||
|
|
||||||
#if defined (SOLARIS)
|
|
||||||
#include "sys_solaris.h"
|
#include "sys_solaris.h"
|
||||||
#endif
|
#elif defined(SUNOS)
|
||||||
|
|
||||||
#if defined (SUNOS)
|
|
||||||
#include "sys_sunos.h"
|
#include "sys_sunos.h"
|
||||||
#endif
|
#elif defined(NETBSD) || defined(FREEBSD)
|
||||||
|
|
||||||
#if defined (__NetBSD__)
|
|
||||||
#include "sys_netbsd.h"
|
#include "sys_netbsd.h"
|
||||||
|
#elif defined(MACOSX)
|
||||||
|
#include "sys_macosx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -51,23 +49,19 @@
|
|||||||
void
|
void
|
||||||
SYS_Initialise(void)
|
SYS_Initialise(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
SYS_Linux_Initialise();
|
SYS_Linux_Initialise();
|
||||||
#endif
|
#elif defined(SOLARIS)
|
||||||
|
|
||||||
#if defined(SOLARIS)
|
|
||||||
SYS_Solaris_Initialise();
|
SYS_Solaris_Initialise();
|
||||||
#endif
|
#elif defined(SUNOS)
|
||||||
|
|
||||||
#if defined(SUNOS)
|
|
||||||
SYS_SunOS_Initialise();
|
SYS_SunOS_Initialise();
|
||||||
#endif
|
#elif defined(NETBSD) || defined(FREEBSD)
|
||||||
|
|
||||||
#if defined(__NetBSD__)
|
|
||||||
SYS_NetBSD_Initialise();
|
SYS_NetBSD_Initialise();
|
||||||
|
#elif defined(MACOSX)
|
||||||
|
SYS_MacOSX_Initialise();
|
||||||
|
#else
|
||||||
|
#error Unknown system
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -75,30 +69,29 @@ SYS_Initialise(void)
|
|||||||
void
|
void
|
||||||
SYS_Finalise(void)
|
SYS_Finalise(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
SYS_Linux_Finalise();
|
SYS_Linux_Finalise();
|
||||||
#endif
|
#elif defined(SOLARIS)
|
||||||
|
|
||||||
#if defined(SOLARIS)
|
|
||||||
SYS_Solaris_Finalise();
|
SYS_Solaris_Finalise();
|
||||||
#endif
|
#elif defined(SUNOS)
|
||||||
|
|
||||||
#if defined(SUNOS)
|
|
||||||
SYS_SunOS_Finalise();
|
SYS_SunOS_Finalise();
|
||||||
#endif
|
#elif defined(NETBSD) || defined(FREEBSD)
|
||||||
|
|
||||||
#if defined(__NetBSD__)
|
|
||||||
SYS_NetBSD_Finalise();
|
SYS_NetBSD_Finalise();
|
||||||
|
#elif defined(MACOSX)
|
||||||
|
SYS_MacOSX_Finalise();
|
||||||
|
#else
|
||||||
|
#error Unknown system
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void SYS_DropRoot(char *user)
|
void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
||||||
SYS_Linux_DropRoot(user);
|
SYS_Linux_DropRoot(uid, gid);
|
||||||
|
#elif defined(NETBSD) && defined(FEAT_PRIVDROP)
|
||||||
|
SYS_NetBSD_DropRoot(uid, gid);
|
||||||
#else
|
#else
|
||||||
LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
|
LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
|
||||||
#endif
|
#endif
|
||||||
@@ -106,10 +99,23 @@ void SYS_DropRoot(char *user)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void SYS_EnableSystemCallFilter(int level)
|
||||||
|
{
|
||||||
|
#if defined(LINUX) && defined(FEAT_SCFILTER)
|
||||||
|
SYS_Linux_EnableSystemCallFilter(level);
|
||||||
|
#else
|
||||||
|
LOG_FATAL(LOGF_Sys, "system call filter not supported");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void SYS_SetScheduler(int SchedPriority)
|
void SYS_SetScheduler(int SchedPriority)
|
||||||
{
|
{
|
||||||
#if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
|
#if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
|
||||||
SYS_Linux_SetScheduler(SchedPriority);
|
SYS_Linux_SetScheduler(SchedPriority);
|
||||||
|
#elif defined(MACOSX)
|
||||||
|
SYS_MacOSX_SetScheduler(SchedPriority);
|
||||||
#else
|
#else
|
||||||
LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported");
|
LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
8
sys.h
8
sys.h
@@ -35,8 +35,12 @@ extern void SYS_Initialise(void);
|
|||||||
/* Called at the end of the run to do final clean-up */
|
/* Called at the end of the run to do final clean-up */
|
||||||
extern void SYS_Finalise(void);
|
extern void SYS_Finalise(void);
|
||||||
|
|
||||||
/* Drop root privileges to the specified user */
|
/* Drop root privileges to the specified user and group */
|
||||||
extern void SYS_DropRoot(char *user);
|
extern void SYS_DropRoot(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
|
/* Enable a system call filter to allow only system calls
|
||||||
|
which chronyd normally needs after initialization */
|
||||||
|
extern void SYS_EnableSystemCallFilter(int level);
|
||||||
|
|
||||||
extern void SYS_SetScheduler(int SchedPriority);
|
extern void SYS_SetScheduler(int SchedPriority);
|
||||||
extern void SYS_LockMemory(void);
|
extern void SYS_LockMemory(void);
|
||||||
|
|||||||
121
sys_generic.c
121
sys_generic.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 2014
|
* Copyright (C) Miroslav Lichvar 2014-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -43,6 +43,8 @@
|
|||||||
static lcl_ReadFrequencyDriver drv_read_freq;
|
static lcl_ReadFrequencyDriver drv_read_freq;
|
||||||
static lcl_SetFrequencyDriver drv_set_freq;
|
static lcl_SetFrequencyDriver drv_set_freq;
|
||||||
static lcl_SetSyncStatusDriver drv_set_sync_status;
|
static lcl_SetSyncStatusDriver drv_set_sync_status;
|
||||||
|
static lcl_AccrueOffsetDriver drv_accrue_offset;
|
||||||
|
static lcl_OffsetCorrectionDriver drv_get_offset_correction;
|
||||||
|
|
||||||
/* Current frequency as requested by the local module (in ppm) */
|
/* Current frequency as requested by the local module (in ppm) */
|
||||||
static double base_freq;
|
static double base_freq;
|
||||||
@@ -85,6 +87,16 @@ static double correction_rate;
|
|||||||
real frequency of the clock */
|
real frequency of the clock */
|
||||||
static double slew_error;
|
static double slew_error;
|
||||||
|
|
||||||
|
/* Minimum offset that the system driver can slew faster than the maximum
|
||||||
|
frequency offset that it allows to be set directly */
|
||||||
|
static double fastslew_min_offset;
|
||||||
|
|
||||||
|
/* Maximum slew rate of the system driver */
|
||||||
|
static double fastslew_max_rate;
|
||||||
|
|
||||||
|
/* Flag indicating that the system driver is currently slewing */
|
||||||
|
static int fastslew_active;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void handle_end_of_slew(void *anything);
|
static void handle_end_of_slew(void *anything);
|
||||||
@@ -107,6 +119,50 @@ handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_fastslew(void)
|
||||||
|
{
|
||||||
|
if (!drv_accrue_offset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
drv_accrue_offset(offset_register, 0.0);
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_SysGeneric, "fastslew offset=%e", offset_register);
|
||||||
|
|
||||||
|
offset_register = 0.0;
|
||||||
|
fastslew_active = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
stop_fastslew(struct timeval *now)
|
||||||
|
{
|
||||||
|
double corr;
|
||||||
|
|
||||||
|
if (!drv_get_offset_correction || !fastslew_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Cancel the remaining offset */
|
||||||
|
drv_get_offset_correction(now, &corr, NULL);
|
||||||
|
drv_accrue_offset(corr, 0.0);
|
||||||
|
offset_register -= corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static double
|
||||||
|
clamp_freq(double freq)
|
||||||
|
{
|
||||||
|
if (freq > max_freq)
|
||||||
|
return max_freq;
|
||||||
|
if (freq < -max_freq)
|
||||||
|
return -max_freq;
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* End currently running slew and start a new one */
|
/* End currently running slew and start a new one */
|
||||||
|
|
||||||
@@ -126,6 +182,8 @@ update_slew(void)
|
|||||||
UTI_DiffTimevalsToDouble(&duration, &now, &slew_start);
|
UTI_DiffTimevalsToDouble(&duration, &now, &slew_start);
|
||||||
offset_register -= slew_freq * duration;
|
offset_register -= slew_freq * duration;
|
||||||
|
|
||||||
|
stop_fastslew(&now);
|
||||||
|
|
||||||
/* Estimate how long should the next slew take */
|
/* Estimate how long should the next slew take */
|
||||||
if (fabs(offset_register) < MIN_OFFSET_CORRECTION) {
|
if (fabs(offset_register) < MIN_OFFSET_CORRECTION) {
|
||||||
duration = MAX_SLEW_TIMEOUT;
|
duration = MAX_SLEW_TIMEOUT;
|
||||||
@@ -143,12 +201,16 @@ update_slew(void)
|
|||||||
else if (corr_freq > max_corr_freq)
|
else if (corr_freq > max_corr_freq)
|
||||||
corr_freq = max_corr_freq;
|
corr_freq = max_corr_freq;
|
||||||
|
|
||||||
|
/* Let the system driver perform the slew if the requested frequency
|
||||||
|
offset is too large for the frequency driver */
|
||||||
|
if (drv_accrue_offset && fabs(corr_freq) >= fastslew_max_rate &&
|
||||||
|
fabs(offset_register) > fastslew_min_offset) {
|
||||||
|
start_fastslew();
|
||||||
|
corr_freq = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the new real frequency and clamp it */
|
/* Get the new real frequency and clamp it */
|
||||||
total_freq = base_freq + corr_freq * (1.0e6 - base_freq);
|
total_freq = clamp_freq(base_freq + corr_freq * (1.0e6 - base_freq));
|
||||||
if (total_freq > max_freq)
|
|
||||||
total_freq = max_freq;
|
|
||||||
else if (total_freq < -max_freq)
|
|
||||||
total_freq = -max_freq;
|
|
||||||
|
|
||||||
/* Set the new frequency (the actual frequency returned by the call may be
|
/* Set the new frequency (the actual frequency returned by the call may be
|
||||||
slightly different from the requested frequency due to rounding) */
|
slightly different from the requested frequency due to rounding) */
|
||||||
@@ -167,8 +229,8 @@ update_slew(void)
|
|||||||
|
|
||||||
/* Compute the duration of the slew and clamp it. If the slewing frequency
|
/* Compute the duration of the slew and clamp it. If the slewing frequency
|
||||||
is zero or has wrong sign (e.g. due to rounding in the frequency driver or
|
is zero or has wrong sign (e.g. due to rounding in the frequency driver or
|
||||||
when base_freq is larger than max_freq), use maximum timeout and try again
|
when base_freq is larger than max_freq, or fast slew is active), use the
|
||||||
on the next update. */
|
maximum timeout and try again on the next update. */
|
||||||
if (fabs(offset_register) < MIN_OFFSET_CORRECTION ||
|
if (fabs(offset_register) < MIN_OFFSET_CORRECTION ||
|
||||||
offset_register * slew_freq <= 0.0) {
|
offset_register * slew_freq <= 0.0) {
|
||||||
duration = MAX_SLEW_TIMEOUT;
|
duration = MAX_SLEW_TIMEOUT;
|
||||||
@@ -238,19 +300,31 @@ static void
|
|||||||
offset_convert(struct timeval *raw,
|
offset_convert(struct timeval *raw,
|
||||||
double *corr, double *err)
|
double *corr, double *err)
|
||||||
{
|
{
|
||||||
double duration;
|
double duration, fastslew_corr, fastslew_err;
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&duration, raw, &slew_start);
|
UTI_DiffTimevalsToDouble(&duration, raw, &slew_start);
|
||||||
|
|
||||||
*corr = slew_freq * duration - offset_register;
|
if (drv_get_offset_correction && fastslew_active) {
|
||||||
if (err)
|
drv_get_offset_correction(raw, &fastslew_corr, &fastslew_err);
|
||||||
*err = fabs(duration) <= max_freq_change_delay ? slew_error : 0.0;
|
if (fastslew_corr == 0.0 && fastslew_err == 0.0)
|
||||||
|
fastslew_active = 0;
|
||||||
|
} else {
|
||||||
|
fastslew_corr = fastslew_err = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*corr = slew_freq * duration + fastslew_corr - offset_register;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
*err = fastslew_err;
|
||||||
|
if (fabs(duration) <= max_freq_change_delay)
|
||||||
|
*err += slew_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Positive means currently fast of true time, i.e. jump backwards */
|
/* Positive means currently fast of true time, i.e. jump backwards */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
apply_step_offset(double offset)
|
apply_step_offset(double offset)
|
||||||
{
|
{
|
||||||
struct timeval old_time, new_time;
|
struct timeval old_time, new_time;
|
||||||
@@ -260,13 +334,16 @@ apply_step_offset(double offset)
|
|||||||
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
||||||
|
|
||||||
if (settimeofday(&new_time, NULL) < 0) {
|
if (settimeofday(&new_time, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysGeneric, "settimeofday() failed");
|
DEBUG_LOG(LOGF_SysGeneric, "settimeofday() failed");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LCL_ReadRawTime(&old_time);
|
LCL_ReadRawTime(&old_time);
|
||||||
UTI_DiffTimevalsToDouble(&err, &old_time, &new_time);
|
UTI_DiffTimevalsToDouble(&err, &old_time, &new_time);
|
||||||
|
|
||||||
lcl_InvokeDispersionNotifyHandlers(fabs(err));
|
lcl_InvokeDispersionNotifyHandlers(fabs(err));
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -292,6 +369,9 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
|||||||
lcl_ReadFrequencyDriver sys_read_freq,
|
lcl_ReadFrequencyDriver sys_read_freq,
|
||||||
lcl_SetFrequencyDriver sys_set_freq,
|
lcl_SetFrequencyDriver sys_set_freq,
|
||||||
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
||||||
|
double min_fastslew_offset, double max_fastslew_rate,
|
||||||
|
lcl_AccrueOffsetDriver sys_accrue_offset,
|
||||||
|
lcl_OffsetCorrectionDriver sys_get_offset_correction,
|
||||||
lcl_SetLeapDriver sys_set_leap,
|
lcl_SetLeapDriver sys_set_leap,
|
||||||
lcl_SetSyncStatusDriver sys_set_sync_status)
|
lcl_SetSyncStatusDriver sys_set_sync_status)
|
||||||
{
|
{
|
||||||
@@ -299,6 +379,8 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
|||||||
max_freq_change_delay = max_set_freq_delay * (1.0 + max_freq / 1.0e6);
|
max_freq_change_delay = max_set_freq_delay * (1.0 + max_freq / 1.0e6);
|
||||||
drv_read_freq = sys_read_freq;
|
drv_read_freq = sys_read_freq;
|
||||||
drv_set_freq = sys_set_freq;
|
drv_set_freq = sys_set_freq;
|
||||||
|
drv_accrue_offset = sys_accrue_offset;
|
||||||
|
drv_get_offset_correction = sys_get_offset_correction;
|
||||||
drv_set_sync_status = sys_set_sync_status;
|
drv_set_sync_status = sys_set_sync_status;
|
||||||
|
|
||||||
base_freq = (*drv_read_freq)();
|
base_freq = (*drv_read_freq)();
|
||||||
@@ -307,6 +389,10 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
|||||||
|
|
||||||
max_corr_freq = CNF_GetMaxSlewRate() / 1.0e6;
|
max_corr_freq = CNF_GetMaxSlewRate() / 1.0e6;
|
||||||
|
|
||||||
|
fastslew_min_offset = min_fastslew_offset;
|
||||||
|
fastslew_max_rate = max_fastslew_rate / 1.0e6;
|
||||||
|
fastslew_active = 0;
|
||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, sys_apply_step_offset ?
|
accrue_offset, sys_apply_step_offset ?
|
||||||
sys_apply_step_offset : apply_step_offset,
|
sys_apply_step_offset : apply_step_offset,
|
||||||
@@ -320,6 +406,8 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
|||||||
void
|
void
|
||||||
SYS_Generic_Finalise(void)
|
SYS_Generic_Finalise(void)
|
||||||
{
|
{
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
/* Must *NOT* leave a slew running - clock could drift way off
|
/* Must *NOT* leave a slew running - clock could drift way off
|
||||||
if the daemon is not restarted */
|
if the daemon is not restarted */
|
||||||
if (slew_timer_running) {
|
if (slew_timer_running) {
|
||||||
@@ -327,7 +415,10 @@ SYS_Generic_Finalise(void)
|
|||||||
slew_timer_running = 0;
|
slew_timer_running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*drv_set_freq)(base_freq);
|
(*drv_set_freq)(clamp_freq(base_freq));
|
||||||
|
|
||||||
|
LCL_ReadRawTime(&now);
|
||||||
|
stop_fastslew(&now);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ extern void SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_s
|
|||||||
lcl_ReadFrequencyDriver sys_read_freq,
|
lcl_ReadFrequencyDriver sys_read_freq,
|
||||||
lcl_SetFrequencyDriver sys_set_freq,
|
lcl_SetFrequencyDriver sys_set_freq,
|
||||||
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
||||||
|
double min_fastslew_offset, double max_fastslew_rate,
|
||||||
|
lcl_AccrueOffsetDriver sys_accrue_offset,
|
||||||
|
lcl_OffsetCorrectionDriver sys_get_offset_correction,
|
||||||
lcl_SetLeapDriver sys_set_leap,
|
lcl_SetLeapDriver sys_set_leap,
|
||||||
lcl_SetSyncStatusDriver sys_set_sync_status);
|
lcl_SetSyncStatusDriver sys_set_sync_status);
|
||||||
|
|
||||||
|
|||||||
355
sys_linux.c
355
sys_linux.c
@@ -4,7 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) John G. Hasler 2009
|
* Copyright (C) John G. Hasler 2009
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2012, 2014
|
* Copyright (C) Miroslav Lichvar 2009-2012, 2014-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -35,31 +35,48 @@
|
|||||||
|
|
||||||
#if defined(HAVE_SCHED_SETSCHEDULER)
|
#if defined(HAVE_SCHED_SETSCHEDULER)
|
||||||
# include <sched.h>
|
# include <sched.h>
|
||||||
int SchedPriority = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_MLOCKALL)
|
#if defined(HAVE_MLOCKALL)
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
int LockAll = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
#include <sys/types.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/capability.h>
|
#include <sys/capability.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sys_generic.h"
|
#ifdef FEAT_SCFILTER
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <seccomp.h>
|
||||||
|
#ifdef FEAT_PHC
|
||||||
|
#include <linux/ptp_clock.h>
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_PPS
|
||||||
|
#include <linux/pps.h>
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_RTC
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "sys_linux.h"
|
#include "sys_linux.h"
|
||||||
|
#include "sys_timex.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "wrap_adjtimex.h"
|
|
||||||
|
|
||||||
/* The threshold for adjtimex maxerror when the kernel sets the UNSYNC flag */
|
/* Frequency scale to convert from ppm to the timex freq */
|
||||||
#define UNSYNC_MAXERROR 16.0
|
#define FREQ_SCALE (double)(1 << 16)
|
||||||
|
|
||||||
|
/* Definitions used if missed in the system headers */
|
||||||
|
#ifndef ADJ_SETOFFSET
|
||||||
|
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
|
||||||
|
#endif
|
||||||
|
#ifndef ADJ_NANO
|
||||||
|
#define ADJ_NANO 0x2000 /* select nanosecond resolution */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This is the uncompensated system tick value */
|
/* This is the uncompensated system tick value */
|
||||||
static int nominal_tick;
|
static int nominal_tick;
|
||||||
@@ -100,12 +117,23 @@ our_round(double x)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Positive means currently fast of true time, i.e. jump backwards */
|
/* Positive means currently fast of true time, i.e. jump backwards */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
apply_step_offset(double offset)
|
apply_step_offset(double offset)
|
||||||
{
|
{
|
||||||
if (TMX_ApplyStepOffset(-offset) < 0) {
|
struct timex txc;
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
|
|
||||||
|
txc.modes = ADJ_SETOFFSET | ADJ_NANO;
|
||||||
|
txc.time.tv_sec = -offset;
|
||||||
|
txc.time.tv_usec = 1.0e9 * (-offset - txc.time.tv_sec);
|
||||||
|
if (txc.time.tv_usec < 0) {
|
||||||
|
txc.time.tv_sec--;
|
||||||
|
txc.time.tv_usec += 1000000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SYS_Timex_Adjust(&txc, 1) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -118,6 +146,7 @@ apply_step_offset(double offset)
|
|||||||
static double
|
static double
|
||||||
set_frequency(double freq_ppm)
|
set_frequency(double freq_ppm)
|
||||||
{
|
{
|
||||||
|
struct timex txc;
|
||||||
long required_tick;
|
long required_tick;
|
||||||
double required_freq;
|
double required_freq;
|
||||||
int required_delta_tick;
|
int required_delta_tick;
|
||||||
@@ -141,14 +170,15 @@ set_frequency(double freq_ppm)
|
|||||||
required_freq = -(freq_ppm - dhz * required_delta_tick);
|
required_freq = -(freq_ppm - dhz * required_delta_tick);
|
||||||
required_tick = nominal_tick - required_delta_tick;
|
required_tick = nominal_tick - required_delta_tick;
|
||||||
|
|
||||||
if (TMX_SetFrequency(&required_freq, required_tick) < 0) {
|
txc.modes = ADJ_TICK | ADJ_FREQUENCY;
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex failed for set_frequency, freq_ppm=%10.4e required_freq=%10.4e required_tick=%ld",
|
txc.freq = required_freq * FREQ_SCALE;
|
||||||
freq_ppm, required_freq, required_tick);
|
txc.tick = required_tick;
|
||||||
}
|
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
current_delta_tick = required_delta_tick;
|
current_delta_tick = required_delta_tick;
|
||||||
|
|
||||||
return dhz * current_delta_tick - required_freq;
|
return dhz * current_delta_tick - txc.freq / FREQ_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -157,52 +187,15 @@ set_frequency(double freq_ppm)
|
|||||||
static double
|
static double
|
||||||
read_frequency(void)
|
read_frequency(void)
|
||||||
{
|
{
|
||||||
long tick;
|
struct timex txc;
|
||||||
double freq;
|
|
||||||
|
|
||||||
if (TMX_GetFrequency(&freq, &tick) < 0) {
|
txc.modes = 0;
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
current_delta_tick = nominal_tick - tick;
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
return dhz * current_delta_tick - freq;
|
current_delta_tick = nominal_tick - txc.tick;
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
return dhz * current_delta_tick - txc.freq / FREQ_SCALE;
|
||||||
|
|
||||||
static void
|
|
||||||
set_leap(int leap)
|
|
||||||
{
|
|
||||||
if (TMX_SetLeap(leap) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed in set_leap");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LOGS_INFO, LOGF_SysLinux, "System clock status set to %s leap second",
|
|
||||||
leap ? (leap > 0 ? "insert" : "delete") : "not insert/delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_sync_status(int synchronised, double est_error, double max_error)
|
|
||||||
{
|
|
||||||
if (synchronised) {
|
|
||||||
if (est_error > UNSYNC_MAXERROR)
|
|
||||||
est_error = UNSYNC_MAXERROR;
|
|
||||||
if (max_error >= UNSYNC_MAXERROR) {
|
|
||||||
max_error = UNSYNC_MAXERROR;
|
|
||||||
synchronised = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
est_error = max_error = UNSYNC_MAXERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the UNSYNC flag only if rtcsync is enabled */
|
|
||||||
if (!CNF_GetRtcSync())
|
|
||||||
synchronised = 0;
|
|
||||||
|
|
||||||
TMX_SetSync(synchronised, est_error, max_error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -213,10 +206,16 @@ set_sync_status(int synchronised, double est_error, double max_error)
|
|||||||
* a +/- 10% movement of tick away from the nominal value 1e6/USER_HZ. */
|
* a +/- 10% movement of tick away from the nominal value 1e6/USER_HZ. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
guess_hz(int tick)
|
guess_hz(void)
|
||||||
{
|
{
|
||||||
int i, tick_lo, tick_hi, ihz;
|
struct timex txc;
|
||||||
|
int i, tick, tick_lo, tick_hi, ihz;
|
||||||
double tick_nominal;
|
double tick_nominal;
|
||||||
|
|
||||||
|
txc.modes = 0;
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
tick = txc.tick;
|
||||||
|
|
||||||
/* Pick off the hz=100 case first */
|
/* Pick off the hz=100 case first */
|
||||||
if (tick >= 9000 && tick <= 11000) {
|
if (tick >= 9000 && tick <= 11000) {
|
||||||
return 100;
|
return 100;
|
||||||
@@ -234,6 +233,8 @@ guess_hz(int tick)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* oh dear. doomed. */
|
/* oh dear. doomed. */
|
||||||
|
LOG_FATAL(LOGF_SysLinux, "Can't determine hz from tick %d", tick);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,21 +276,12 @@ static void
|
|||||||
get_version_specific_details(void)
|
get_version_specific_details(void)
|
||||||
{
|
{
|
||||||
int major, minor, patch;
|
int major, minor, patch;
|
||||||
long tick;
|
|
||||||
double freq;
|
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
|
|
||||||
hz = get_hz();
|
hz = get_hz();
|
||||||
|
|
||||||
if (!hz) {
|
if (!hz)
|
||||||
if (TMX_GetFrequency(&freq, &tick) < 0)
|
hz = guess_hz();
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
|
|
||||||
|
|
||||||
hz = guess_hz(tick);
|
|
||||||
|
|
||||||
if (!hz)
|
|
||||||
LOG_FATAL(LOGF_SysLinux, "Can't determine hz from tick %ld", tick);
|
|
||||||
}
|
|
||||||
|
|
||||||
dhz = (double) hz;
|
dhz = (double) hz;
|
||||||
nominal_tick = (1000000L + (hz/2))/hz; /* Mirror declaration in kernel */
|
nominal_tick = (1000000L + (hz/2))/hz; /* Mirror declaration in kernel */
|
||||||
@@ -332,6 +324,48 @@ get_version_specific_details(void)
|
|||||||
hz, nominal_tick, max_tick_bias);
|
hz, nominal_tick, max_tick_bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_adjtime_offset(void)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
/* Reset adjtime() offset */
|
||||||
|
txc.modes = ADJ_OFFSET_SINGLESHOT;
|
||||||
|
txc.offset = 0;
|
||||||
|
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_step_offset(void)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
/* Zero maxerror and check it's reset to a maximum after ADJ_SETOFFSET.
|
||||||
|
This seems to be the only way how to verify that the kernel really
|
||||||
|
supports the ADJ_SETOFFSET mode as it doesn't return an error on unknown
|
||||||
|
mode. */
|
||||||
|
|
||||||
|
txc.modes = MOD_MAXERROR;
|
||||||
|
txc.maxerror = 0;
|
||||||
|
|
||||||
|
if (SYS_Timex_Adjust(&txc, 1) < 0 || txc.maxerror != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
txc.modes = ADJ_SETOFFSET | ADJ_NANO;
|
||||||
|
txc.time.tv_sec = 0;
|
||||||
|
txc.time.tv_usec = 0;
|
||||||
|
|
||||||
|
if (SYS_Timex_Adjust(&txc, 1) < 0 || txc.maxerror < 100000)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Initialisation code for this module */
|
/* Initialisation code for this module */
|
||||||
|
|
||||||
@@ -340,20 +374,18 @@ SYS_Linux_Initialise(void)
|
|||||||
{
|
{
|
||||||
get_version_specific_details();
|
get_version_specific_details();
|
||||||
|
|
||||||
if (TMX_ResetOffset() < 0) {
|
reset_adjtime_offset();
|
||||||
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_setoffset && TMX_TestStepOffset() < 0) {
|
if (have_setoffset && !test_step_offset()) {
|
||||||
LOG(LOGS_INFO, LOGF_SysLinux, "adjtimex() doesn't support ADJ_SETOFFSET");
|
LOG(LOGS_INFO, LOGF_SysLinux, "adjtimex() doesn't support ADJ_SETOFFSET");
|
||||||
have_setoffset = 0;
|
have_setoffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_Generic_CompleteFreqDriver(1.0e6 * max_tick_bias / nominal_tick,
|
SYS_Timex_InitialiseWithFunctions(1.0e6 * max_tick_bias / nominal_tick,
|
||||||
1.0 / tick_update_hz,
|
1.0 / tick_update_hz,
|
||||||
read_frequency, set_frequency,
|
read_frequency, set_frequency,
|
||||||
have_setoffset ? apply_step_offset : NULL,
|
have_setoffset ? apply_step_offset : NULL,
|
||||||
set_leap, set_sync_status);
|
0.0, 0.0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -362,25 +394,17 @@ SYS_Linux_Initialise(void)
|
|||||||
void
|
void
|
||||||
SYS_Linux_Finalise(void)
|
SYS_Linux_Finalise(void)
|
||||||
{
|
{
|
||||||
SYS_Generic_Finalise();
|
SYS_Timex_Finalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
void
|
void
|
||||||
SYS_Linux_DropRoot(char *user)
|
SYS_Linux_DropRoot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
|
||||||
cap_t cap;
|
cap_t cap;
|
||||||
|
|
||||||
if (user == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((pw = getpwnam(user)) == NULL) {
|
|
||||||
LOG_FATAL(LOGF_SysLinux, "getpwnam(%s) failed", user);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prctl(PR_SET_KEEPCAPS, 1)) {
|
if (prctl(PR_SET_KEEPCAPS, 1)) {
|
||||||
LOG_FATAL(LOGF_SysLinux, "prctl() failed");
|
LOG_FATAL(LOGF_SysLinux, "prctl() failed");
|
||||||
}
|
}
|
||||||
@@ -389,12 +413,12 @@ SYS_Linux_DropRoot(char *user)
|
|||||||
LOG_FATAL(LOGF_SysLinux, "setgroups() failed");
|
LOG_FATAL(LOGF_SysLinux, "setgroups() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setgid(pw->pw_gid)) {
|
if (setgid(gid)) {
|
||||||
LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", pw->pw_gid);
|
LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setuid(pw->pw_uid)) {
|
if (setuid(uid)) {
|
||||||
LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", pw->pw_uid);
|
LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cap = cap_from_text("cap_net_bind_service,cap_sys_time=ep")) == NULL) {
|
if ((cap = cap_from_text("cap_net_bind_service,cap_sys_time=ep")) == NULL) {
|
||||||
@@ -407,7 +431,146 @@ SYS_Linux_DropRoot(char *user)
|
|||||||
|
|
||||||
cap_free(cap);
|
cap_free(cap);
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_SysLinux, "Privileges dropped to user %s", user);
|
DEBUG_LOG(LOGF_SysLinux, "Root dropped to uid %d gid %d", uid, gid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
#ifdef FEAT_SCFILTER
|
||||||
|
static
|
||||||
|
void check_seccomp_applicability(void)
|
||||||
|
{
|
||||||
|
int mail_enabled;
|
||||||
|
double mail_threshold;
|
||||||
|
char *mail_user;
|
||||||
|
|
||||||
|
CNF_GetMailOnChange(&mail_enabled, &mail_threshold, &mail_user);
|
||||||
|
if (mail_enabled)
|
||||||
|
LOG_FATAL(LOGF_SysLinux, "mailonchange directive cannot be used with -F enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
SYS_Linux_EnableSystemCallFilter(int level)
|
||||||
|
{
|
||||||
|
const int syscalls[] = {
|
||||||
|
/* Clock */
|
||||||
|
SCMP_SYS(adjtimex), SCMP_SYS(gettimeofday), SCMP_SYS(settimeofday),
|
||||||
|
SCMP_SYS(time),
|
||||||
|
/* Process */
|
||||||
|
SCMP_SYS(clone), SCMP_SYS(exit), SCMP_SYS(exit_group),
|
||||||
|
SCMP_SYS(rt_sigreturn), SCMP_SYS(sigreturn),
|
||||||
|
/* Memory */
|
||||||
|
SCMP_SYS(brk), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2),
|
||||||
|
SCMP_SYS(mprotect), SCMP_SYS(munmap), SCMP_SYS(shmdt),
|
||||||
|
/* Filesystem */
|
||||||
|
SCMP_SYS(chmod), SCMP_SYS(chown), SCMP_SYS(chown32), SCMP_SYS(fstat),
|
||||||
|
SCMP_SYS(fstat64), SCMP_SYS(lseek), SCMP_SYS(rename), SCMP_SYS(stat),
|
||||||
|
SCMP_SYS(stat64), SCMP_SYS(unlink),
|
||||||
|
/* Socket */
|
||||||
|
SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname),
|
||||||
|
SCMP_SYS(recvfrom), SCMP_SYS(recvmsg), SCMP_SYS(sendmmsg),
|
||||||
|
SCMP_SYS(sendmsg), SCMP_SYS(sendto),
|
||||||
|
/* TODO: check socketcall arguments */
|
||||||
|
SCMP_SYS(socketcall),
|
||||||
|
/* General I/O */
|
||||||
|
SCMP_SYS(_newselect), SCMP_SYS(close), SCMP_SYS(open), SCMP_SYS(pipe),
|
||||||
|
SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(futex), SCMP_SYS(select),
|
||||||
|
SCMP_SYS(set_robust_list), SCMP_SYS(write),
|
||||||
|
/* Miscellaneous */
|
||||||
|
SCMP_SYS(uname),
|
||||||
|
};
|
||||||
|
|
||||||
|
const int socket_domains[] = {
|
||||||
|
AF_NETLINK, AF_UNIX, AF_INET,
|
||||||
|
#ifdef FEAT_IPV6
|
||||||
|
AF_INET6,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const static int socket_options[][2] = {
|
||||||
|
{ SOL_IP, IP_PKTINFO }, { SOL_IP, IP_FREEBIND },
|
||||||
|
#ifdef FEAT_IPV6
|
||||||
|
{ SOL_IPV6, IPV6_V6ONLY }, { SOL_IPV6, IPV6_RECVPKTINFO },
|
||||||
|
#endif
|
||||||
|
{ SOL_SOCKET, SO_BROADCAST }, { SOL_SOCKET, SO_REUSEADDR },
|
||||||
|
{ SOL_SOCKET, SO_TIMESTAMP },
|
||||||
|
};
|
||||||
|
|
||||||
|
const static int fcntls[] = { F_GETFD, F_SETFD };
|
||||||
|
|
||||||
|
const static unsigned long ioctls[] = {
|
||||||
|
FIONREAD,
|
||||||
|
#ifdef FEAT_PPS
|
||||||
|
PTP_SYS_OFFSET,
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_PPS
|
||||||
|
PPS_FETCH,
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_RTC
|
||||||
|
RTC_RD_TIME, RTC_SET_TIME, RTC_UIE_ON, RTC_UIE_OFF,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
scmp_filter_ctx *ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Check if the chronyd configuration is supported */
|
||||||
|
check_seccomp_applicability();
|
||||||
|
|
||||||
|
ctx = seccomp_init(level > 0 ? SCMP_ACT_KILL : SCMP_ACT_TRAP);
|
||||||
|
if (ctx == NULL)
|
||||||
|
LOG_FATAL(LOGF_SysLinux, "Failed to initialize seccomp");
|
||||||
|
|
||||||
|
/* Add system calls that are always allowed */
|
||||||
|
for (i = 0; i < (sizeof (syscalls) / sizeof (*syscalls)); i++) {
|
||||||
|
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) < 0)
|
||||||
|
goto add_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow sockets to be created only in selected domains */
|
||||||
|
for (i = 0; i < sizeof (socket_domains) / sizeof (*socket_domains); i++) {
|
||||||
|
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
|
||||||
|
SCMP_A0(SCMP_CMP_EQ, socket_domains[i])) < 0)
|
||||||
|
goto add_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow setting only selected sockets options */
|
||||||
|
for (i = 0; i < sizeof (socket_options) / sizeof (*socket_options); i++) {
|
||||||
|
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 3,
|
||||||
|
SCMP_A1(SCMP_CMP_EQ, socket_options[i][0]),
|
||||||
|
SCMP_A2(SCMP_CMP_EQ, socket_options[i][1]),
|
||||||
|
SCMP_A4(SCMP_CMP_LE, sizeof (int))) < 0)
|
||||||
|
goto add_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow only selected fcntl calls */
|
||||||
|
for (i = 0; i < sizeof (fcntls) / sizeof (*fcntls); i++) {
|
||||||
|
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1,
|
||||||
|
SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0 ||
|
||||||
|
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1,
|
||||||
|
SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0)
|
||||||
|
goto add_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow only selected ioctls */
|
||||||
|
for (i = 0; i < sizeof (ioctls) / sizeof (*ioctls); i++) {
|
||||||
|
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1,
|
||||||
|
SCMP_A1(SCMP_CMP_EQ, ioctls[i])) < 0)
|
||||||
|
goto add_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seccomp_load(ctx) < 0)
|
||||||
|
LOG_FATAL(LOGF_SysLinux, "Failed to load seccomp rules");
|
||||||
|
|
||||||
|
LOG(LOGS_INFO, LOGF_SysLinux, "Loaded seccomp filter");
|
||||||
|
seccomp_release(ctx);
|
||||||
|
return;
|
||||||
|
|
||||||
|
add_failed:
|
||||||
|
LOG_FATAL(LOGF_SysLinux, "Failed to add seccomp rules");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ extern void SYS_Linux_Initialise(void);
|
|||||||
|
|
||||||
extern void SYS_Linux_Finalise(void);
|
extern void SYS_Linux_Finalise(void);
|
||||||
|
|
||||||
extern void SYS_Linux_DropRoot(char *user);
|
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
|
extern void SYS_Linux_EnableSystemCallFilter(int level);
|
||||||
|
|
||||||
extern void SYS_Linux_MemLockAll(int LockAll);
|
extern void SYS_Linux_MemLockAll(int LockAll);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2001
|
||||||
|
* Copyright (C) J. Hannken-Illjes 2001
|
||||||
|
* Copyright (C) Bryan Christianson 2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -21,27 +23,34 @@
|
|||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Driver file for the SunOS 4.1.x operating system.
|
Driver file for the MacOS X operating system.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef SUNOS
|
#ifdef MACOSX
|
||||||
|
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "sys_sunos.h"
|
#include <mach/mach.h>
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "sys_macosx.h"
|
||||||
#include "localp.h"
|
#include "localp.h"
|
||||||
|
#include "sched.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "sched.h"
|
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -65,16 +74,27 @@ static double current_freq;
|
|||||||
|
|
||||||
static double adjustment_requested;
|
static double adjustment_requested;
|
||||||
|
|
||||||
/* Eventually, this needs to be a user-defined parameter - e.g. user
|
/* Interval in seconds between adjustments to cancel systematic drift */
|
||||||
might want 5 to get much finer resolution like xntpd. We stick
|
|
||||||
with a reasonable number so that slewing can work.
|
|
||||||
|
|
||||||
This value has to be a factor of 1 million, otherwise the noddy
|
#define DRIFT_REMOVAL_INTERVAL (4.0)
|
||||||
method we use for rounding an adjustment to the nearest multiple of
|
#define DRIFT_REMOVAL_INTERVAL_MIN (0.5)
|
||||||
this value won't work!!
|
|
||||||
|
|
||||||
*/
|
/* If current_drift_removal_interval / drift_removal_interval exceeds this
|
||||||
static unsigned long our_tickadj = 100;
|
ratio, then restart the drift removal timer */
|
||||||
|
|
||||||
|
#define DRIFT_REMOVAL_RESTART_RATIO (8.0)
|
||||||
|
|
||||||
|
static double drift_removal_interval;
|
||||||
|
static double current_drift_removal_interval;
|
||||||
|
static struct timeval Tdrift;
|
||||||
|
|
||||||
|
/* weighting applied to error in calculating drift_removal_interval */
|
||||||
|
#define ERROR_WEIGHT (0.5)
|
||||||
|
|
||||||
|
/* minimum resolution of current_frequency */
|
||||||
|
#define FREQUENCY_RES (1.0e-9)
|
||||||
|
|
||||||
|
#define NANOS_PER_MSEC (1000000ULL)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -86,20 +106,19 @@ clock_initialise(void)
|
|||||||
offset_register = 0.0;
|
offset_register = 0.0;
|
||||||
adjustment_requested = 0.0;
|
adjustment_requested = 0.0;
|
||||||
current_freq = 0.0;
|
current_freq = 0.0;
|
||||||
|
drift_removal_interval = DRIFT_REMOVAL_INTERVAL;
|
||||||
|
current_drift_removal_interval = DRIFT_REMOVAL_INTERVAL;
|
||||||
|
|
||||||
if (gettimeofday(&T0, NULL) < 0) {
|
if (gettimeofday(&T0, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
|
||||||
}
|
}
|
||||||
|
Tdrift = T0;
|
||||||
|
|
||||||
newadj.tv_sec = 0;
|
newadj.tv_sec = 0;
|
||||||
newadj.tv_usec = 0;
|
newadj.tv_usec = 0;
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
if (adjtime(&newadj, &oldadj) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
|
||||||
}
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,56 +137,47 @@ start_adjust(void)
|
|||||||
{
|
{
|
||||||
struct timeval newadj, oldadj;
|
struct timeval newadj, oldadj;
|
||||||
struct timeval T1;
|
struct timeval T1;
|
||||||
double elapsed, accrued_error;
|
double elapsed, accrued_error, predicted_error, drift_removal_elapsed;
|
||||||
double adjust_required;
|
double adjust_required;
|
||||||
struct timeval exact_newadj;
|
|
||||||
double rounding_error;
|
double rounding_error;
|
||||||
double old_adjust_remaining;
|
double old_adjust_remaining;
|
||||||
long remainder, multiplier;
|
|
||||||
|
|
||||||
/* Determine the amount of error built up since the last adjustment */
|
/* Determine the amount of error built up since the last adjustment */
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
if (gettimeofday(&T1, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
||||||
accrued_error = elapsed * current_freq;
|
accrued_error = elapsed * current_freq;
|
||||||
|
|
||||||
adjust_required = - (accrued_error + offset_register);
|
UTI_DiffTimevalsToDouble(&drift_removal_elapsed, &T1, &Tdrift);
|
||||||
|
|
||||||
UTI_DoubleToTimeval(adjust_required, &exact_newadj);
|
/* To allow for the clock being stepped either forward or backwards, clamp
|
||||||
|
the elapsed time to bounds [ 0.0, current_drift_removal_interval ] */
|
||||||
|
drift_removal_elapsed = MIN(MAX(0.0, drift_removal_elapsed), current_drift_removal_interval);
|
||||||
|
|
||||||
/* At this point, we need to round the required adjustment to the
|
predicted_error = (current_drift_removal_interval - drift_removal_elapsed) / 2.0 * current_freq;
|
||||||
closest multiple of _tickadj --- because SunOS can't process
|
|
||||||
other adjustments exactly and will silently discard the residual.
|
|
||||||
Obviously such behaviour can't be tolerated for us. */
|
|
||||||
|
|
||||||
newadj = exact_newadj;
|
DEBUG_LOG(LOGF_SysMacOSX, "drift_removal_elapsed: %.3f current_drift_removal_interval: %.3f predicted_error: %.3f",
|
||||||
remainder = newadj.tv_usec % our_tickadj;
|
1.0e6 * drift_removal_elapsed,
|
||||||
multiplier = newadj.tv_usec / our_tickadj;
|
1.0e6 * current_drift_removal_interval,
|
||||||
if (remainder >= (our_tickadj >> 1)) {
|
1.0e6 * predicted_error);
|
||||||
newadj.tv_usec = (multiplier + 1) * our_tickadj;
|
|
||||||
} else {
|
|
||||||
newadj.tv_usec = multiplier * our_tickadj;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_NormaliseTimeval(&newadj);
|
adjust_required = - (accrued_error + offset_register + predicted_error);
|
||||||
|
|
||||||
/* Want to *add* rounding error back onto offset register. Note
|
UTI_DoubleToTimeval(adjust_required, &newadj);
|
||||||
that the exact adjustment was the offset register *negated* */
|
UTI_TimevalToDouble(&newadj, &adjustment_requested);
|
||||||
UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj);
|
rounding_error = adjust_required - adjustment_requested;
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
if (adjtime(&newadj, &oldadj) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
|
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
|
||||||
|
|
||||||
offset_register = rounding_error - old_adjust_remaining;
|
offset_register = rounding_error - old_adjust_remaining - predicted_error;
|
||||||
|
|
||||||
T0 = T1;
|
T0 = T1;
|
||||||
UTI_TimevalToDouble(&newadj, &adjustment_requested);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -178,18 +188,17 @@ stop_adjust(void)
|
|||||||
struct timeval T1;
|
struct timeval T1;
|
||||||
struct timeval zeroadj, remadj;
|
struct timeval zeroadj, remadj;
|
||||||
double adjustment_remaining, adjustment_achieved;
|
double adjustment_remaining, adjustment_achieved;
|
||||||
double gap;
|
|
||||||
double elapsed, elapsed_plus_adjust;
|
double elapsed, elapsed_plus_adjust;
|
||||||
|
|
||||||
zeroadj.tv_sec = 0;
|
zeroadj.tv_sec = 0;
|
||||||
zeroadj.tv_usec = 0;
|
zeroadj.tv_usec = 0;
|
||||||
|
|
||||||
if (adjtime(&zeroadj, &remadj) < 0) {
|
if (adjtime(&zeroadj, &remadj) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "adjtime() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
if (gettimeofday(&T1, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
||||||
@@ -202,7 +211,6 @@ stop_adjust(void)
|
|||||||
|
|
||||||
adjustment_requested = 0.0;
|
adjustment_requested = 0.0;
|
||||||
T0 = T1;
|
T0 = T1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -223,20 +231,22 @@ accrue_offset(double offset, double corr_rate)
|
|||||||
/* Positive offset means system clock is fast of true time, therefore
|
/* Positive offset means system clock is fast of true time, therefore
|
||||||
step backwards */
|
step backwards */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
apply_step_offset(double offset)
|
apply_step_offset(double offset)
|
||||||
{
|
{
|
||||||
struct timeval old_time, new_time, T1;
|
struct timeval old_time, new_time, T1;
|
||||||
|
|
||||||
stop_adjust();
|
stop_adjust();
|
||||||
|
|
||||||
if (gettimeofday(&old_time, NULL) < 0) {
|
if (gettimeofday(&old_time, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
|
LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
||||||
|
|
||||||
if (settimeofday(&new_time, NULL) < 0) {
|
if (settimeofday(&new_time, NULL) < 0) {
|
||||||
LOG_FATAL(LOGF_SysSunOS, "settimeofday() failed");
|
DEBUG_LOG(LOGF_SysMacOSX, "settimeofday() failed");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&T0, offset, &T1);
|
UTI_AddDoubleToTimeval(&T0, offset, &T1);
|
||||||
@@ -244,6 +254,7 @@ apply_step_offset(double offset)
|
|||||||
|
|
||||||
start_adjust();
|
start_adjust();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -281,136 +292,143 @@ get_offset_correction(struct timeval *raw,
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
/* Cancel systematic drift */
|
||||||
immediate_step(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* Interval in seconds between adjustments to cancel systematic drift */
|
|
||||||
#define DRIFT_REMOVAL_INTERVAL (4.0)
|
|
||||||
|
|
||||||
static int drift_removal_running = 0;
|
static int drift_removal_running = 0;
|
||||||
static SCH_TimeoutID drift_removal_id;
|
static SCH_TimeoutID drift_removal_id;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* This is the timer callback routine which is called periodically to
|
/* This is the timer callback routine which is called periodically to
|
||||||
invoke a time adjustment to take out the machine's drift.
|
invoke a time adjustment to take out the machine's drift.
|
||||||
Otherwise, times reported through this software (e.g. by running
|
Otherwise, times reported through this software (e.g. by running
|
||||||
ntpdate from another machine) show the machine being correct (since
|
ntpdate from another machine) show the machine being correct (since
|
||||||
they correct for drift build-up), but any program on this machine
|
they correct for drift build-up), but any program on this machine
|
||||||
that reads the system time will be given an erroneous value, the
|
that reads the system time will be given an erroneous value, the
|
||||||
degree of error depending on how long it is since
|
degree of error depending on how long it is since
|
||||||
get_offset_correction was last called. */
|
get_offset_correction was last called. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drift_removal_timeout(SCH_ArbitraryArgument not_used)
|
drift_removal_timeout(SCH_ArbitraryArgument not_used)
|
||||||
{
|
{
|
||||||
|
|
||||||
stop_adjust();
|
stop_adjust();
|
||||||
|
|
||||||
|
if (gettimeofday(&Tdrift, NULL) < 0) {
|
||||||
|
LOG_FATAL(LOGF_SysMacOSX, "gettimeofday() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
current_drift_removal_interval = drift_removal_interval;
|
||||||
|
|
||||||
start_adjust();
|
start_adjust();
|
||||||
drift_removal_id = SCH_AddTimeoutByDelay(DRIFT_REMOVAL_INTERVAL, drift_removal_timeout, NULL);
|
|
||||||
|
drift_removal_id = SCH_AddTimeoutByDelay(drift_removal_interval, drift_removal_timeout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
/* use est_error to calculate the drift_removal_interval */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setup_kernel(unsigned long on_off)
|
set_sync_status(int synchronised, double est_error, double max_error)
|
||||||
{
|
{
|
||||||
static struct nlist nl[] = {
|
double interval;
|
||||||
{"_dosynctodr"},
|
|
||||||
{"_tick"},
|
|
||||||
{"_tickadj"},
|
|
||||||
{NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
kvm_t *kt;
|
if (!synchronised) {
|
||||||
unsigned long read_back;
|
drift_removal_interval = MAX(drift_removal_interval, DRIFT_REMOVAL_INTERVAL);
|
||||||
unsigned long our_tick = 10000;
|
} else {
|
||||||
unsigned long default_tickadj = 625;
|
interval = ERROR_WEIGHT * est_error / (fabs(current_freq) + FREQUENCY_RES);
|
||||||
|
drift_removal_interval = MAX(interval, DRIFT_REMOVAL_INTERVAL_MIN);
|
||||||
|
|
||||||
assert(on_off == 1 || on_off == 0);
|
DEBUG_LOG(LOGF_SysMacOSX, "est_error: %.3f current_freq: %.3f est drift_removal_interval: %.3f act drift_removal_interval: %.3f",
|
||||||
|
est_error * 1.0e6, current_freq * 1.0e6, interval, drift_removal_interval);
|
||||||
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
|
|
||||||
if (!kt) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot open kvm");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_nlist(kt, nl) < 0) {
|
if (current_drift_removal_interval / drift_removal_interval > DRIFT_REMOVAL_RESTART_RATIO) {
|
||||||
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot read kernel symbols");
|
/* recover from a large est_error by resetting the timer */
|
||||||
kvm_close(kt);
|
SCH_ArbitraryArgument unused;
|
||||||
return;
|
SCH_RemoveTimeout(drift_removal_id);
|
||||||
|
unused = NULL;
|
||||||
|
drift_removal_timeout(unused);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (kvm_write(kt, nl[0].n_value, (char *)(&on_off), sizeof(unsigned long)) < 0) {
|
/* ================================================== */
|
||||||
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _dosynctodr");
|
/*
|
||||||
kvm_close(kt);
|
Give chronyd real time priority so that time critical calculations
|
||||||
return;
|
are not pre-empted by the kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_realtime(void)
|
||||||
|
{
|
||||||
|
/* https://developer.apple.com/library/ios/technotes/tn2169/_index.html */
|
||||||
|
|
||||||
|
mach_timebase_info_data_t timebase_info;
|
||||||
|
double clock2abs;
|
||||||
|
thread_time_constraint_policy_data_t policy;
|
||||||
|
int kr;
|
||||||
|
|
||||||
|
mach_timebase_info(&timebase_info);
|
||||||
|
clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
|
||||||
|
|
||||||
|
policy.period = 0;
|
||||||
|
policy.computation = (uint32_t)(5 * clock2abs); /* 5 ms of work */
|
||||||
|
policy.constraint = (uint32_t)(10 * clock2abs);
|
||||||
|
policy.preemptible = 0;
|
||||||
|
|
||||||
|
kr = thread_policy_set(
|
||||||
|
pthread_mach_thread_np(pthread_self()),
|
||||||
|
THREAD_TIME_CONSTRAINT_POLICY,
|
||||||
|
(thread_policy_t)&policy,
|
||||||
|
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
|
||||||
|
|
||||||
|
if (kr != KERN_SUCCESS) {
|
||||||
|
LOG(LOGS_WARN, LOGF_SysMacOSX, "Cannot set real-time priority: %d", kr);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
if (kvm_write(kt, nl[1].n_value, (char *)(&our_tick), sizeof(unsigned long)) < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _tick");
|
|
||||||
kvm_close(kt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_write(kt, nl[2].n_value,
|
|
||||||
(char *)(on_off ? &default_tickadj : &our_tickadj),
|
|
||||||
sizeof(unsigned long)) < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _tickadj");
|
|
||||||
kvm_close(kt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
kvm_close(kt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SYS_SunOS_Initialise(void)
|
SYS_MacOSX_SetScheduler(int SchedPriority)
|
||||||
{
|
{
|
||||||
|
if (SchedPriority) {
|
||||||
|
set_realtime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Need to do KVM stuff to turn off dosynctodr. */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
SYS_MacOSX_Initialise(void)
|
||||||
|
{
|
||||||
clock_initialise();
|
clock_initialise();
|
||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, apply_step_offset,
|
accrue_offset, apply_step_offset,
|
||||||
get_offset_correction,
|
get_offset_correction,
|
||||||
NULL /* set_leap */,
|
NULL /* set_leap */,
|
||||||
NULL /* set_sync_status */);
|
set_sync_status);
|
||||||
|
|
||||||
/* Turn off the kernel switch that keeps the system clock in step
|
|
||||||
with the non-volatile clock */
|
|
||||||
setup_kernel(0);
|
|
||||||
|
|
||||||
drift_removal_id = SCH_AddTimeoutByDelay(DRIFT_REMOVAL_INTERVAL, drift_removal_timeout, NULL);
|
drift_removal_id = SCH_AddTimeoutByDelay(drift_removal_interval, drift_removal_timeout, NULL);
|
||||||
drift_removal_running = 1;
|
drift_removal_running = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SYS_SunOS_Finalise(void)
|
SYS_MacOSX_Finalise(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (drift_removal_running) {
|
if (drift_removal_running) {
|
||||||
SCH_RemoveTimeout(drift_removal_id);
|
SCH_RemoveTimeout(drift_removal_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn dosynctodr back on?? */
|
|
||||||
|
|
||||||
clock_finalise();
|
clock_finalise();
|
||||||
|
|
||||||
/* When exiting, we want to return the machine to its 'autonomous'
|
|
||||||
tracking mode */
|
|
||||||
setup_kernel(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif /* SUNOS */
|
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
* Copyright (C) Richard P. Curnow 1997-2001
|
||||||
|
* Copyright (C) J. Hannken-Illjes 2001
|
||||||
|
* Copyright (C) Bryan Christianson 2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -21,14 +23,15 @@
|
|||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Header file for Solaris driver
|
Header file for MacOS X driver
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GOT_SYS_SUNOS_H
|
#ifndef GOT_SYS_MACOSX_H
|
||||||
#define GOT_SYS_SUNOS_H
|
#define GOT_SYS_MACOSX_H
|
||||||
|
|
||||||
void SYS_SunOS_Initialise(void);
|
void SYS_MacOSX_SetScheduler(int SchedPriority);
|
||||||
|
void SYS_MacOSX_Initialise(void);
|
||||||
void SYS_SunOS_Finalise(void);
|
void SYS_MacOSX_Finalise(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
314
sys_netbsd.c
314
sys_netbsd.c
@@ -4,6 +4,7 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2001
|
* Copyright (C) Richard P. Curnow 1997-2001
|
||||||
* Copyright (C) J. Hannken-Illjes 2001
|
* Copyright (C) J. Hannken-Illjes 2001
|
||||||
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -27,171 +28,27 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef __NetBSD__
|
#include "sysincl.h"
|
||||||
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <nlist.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "sys_netbsd.h"
|
#include "sys_netbsd.h"
|
||||||
#include "localp.h"
|
#include "sys_timex.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* Maximum frequency offset accepted by the kernel (in ppm) */
|
||||||
|
#define MAX_FREQ 500.0
|
||||||
|
|
||||||
/* This register contains the number of seconds by which the local
|
/* Minimum assumed rate at which the kernel updates the clock frequency */
|
||||||
clock was estimated to be fast of reference time at the epoch when
|
#define MIN_TICK_RATE 100
|
||||||
gettimeofday() returned T0 */
|
|
||||||
|
|
||||||
static double offset_register;
|
/* Interval between kernel updates of the adjtime() offset */
|
||||||
|
#define ADJTIME_UPDATE_INTERVAL 1.0
|
||||||
|
|
||||||
/* This register contains the epoch to which the offset is referenced */
|
/* Maximum adjtime() slew rate (in ppm) */
|
||||||
|
#define MAX_ADJTIME_SLEWRATE 5000.0
|
||||||
|
|
||||||
static struct timeval T0;
|
/* Minimum offset adjtime() slews faster than MAX_FREQ */
|
||||||
|
#define MIN_FASTSLEW_OFFSET 1.0
|
||||||
/* This register contains the current estimate of the system
|
|
||||||
frequency, in absolute (NOT ppm) */
|
|
||||||
|
|
||||||
static double current_freq;
|
|
||||||
|
|
||||||
/* This register contains the number of seconds of adjustment that
|
|
||||||
were passed to adjtime last time it was called. */
|
|
||||||
|
|
||||||
static double adjustment_requested;
|
|
||||||
|
|
||||||
/* Kernel parameters to calculate adjtime error. */
|
|
||||||
|
|
||||||
static int kern_tickadj;
|
|
||||||
static long kern_bigadj;
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
clock_initialise(void)
|
|
||||||
{
|
|
||||||
struct timeval newadj, oldadj;
|
|
||||||
|
|
||||||
offset_register = 0.0;
|
|
||||||
adjustment_requested = 0.0;
|
|
||||||
current_freq = 0.0;
|
|
||||||
|
|
||||||
if (gettimeofday(&T0, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
newadj.tv_sec = 0;
|
|
||||||
newadj.tv_usec = 0;
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
clock_finalise(void)
|
|
||||||
{
|
|
||||||
/* Nothing to do yet */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_adjust(void)
|
|
||||||
{
|
|
||||||
struct timeval newadj, oldadj;
|
|
||||||
struct timeval T1;
|
|
||||||
double elapsed, accrued_error;
|
|
||||||
double adjust_required;
|
|
||||||
struct timeval exact_newadj;
|
|
||||||
long delta, tickdelta;
|
|
||||||
double rounding_error;
|
|
||||||
double old_adjust_remaining;
|
|
||||||
|
|
||||||
/* Determine the amount of error built up since the last adjustment */
|
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
|
||||||
accrued_error = elapsed * current_freq;
|
|
||||||
|
|
||||||
adjust_required = - (accrued_error + offset_register);
|
|
||||||
|
|
||||||
UTI_DoubleToTimeval(adjust_required, &exact_newadj);
|
|
||||||
|
|
||||||
/* At this point, we need to round the required adjustment the
|
|
||||||
same way the kernel does. */
|
|
||||||
|
|
||||||
delta = exact_newadj.tv_sec * 1000000 + exact_newadj.tv_usec;
|
|
||||||
if (delta > kern_bigadj || delta < -kern_bigadj)
|
|
||||||
tickdelta = 10 * kern_tickadj;
|
|
||||||
else
|
|
||||||
tickdelta = kern_tickadj;
|
|
||||||
if (delta % tickdelta)
|
|
||||||
delta = delta / tickdelta * tickdelta;
|
|
||||||
newadj.tv_sec = 0;
|
|
||||||
newadj.tv_usec = delta;
|
|
||||||
UTI_NormaliseTimeval(&newadj);
|
|
||||||
|
|
||||||
/* Add rounding error back onto offset register. */
|
|
||||||
UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj);
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
|
|
||||||
|
|
||||||
offset_register = rounding_error - old_adjust_remaining;
|
|
||||||
|
|
||||||
T0 = T1;
|
|
||||||
UTI_TimevalToDouble(&newadj, &adjustment_requested);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
stop_adjust(void)
|
|
||||||
{
|
|
||||||
struct timeval T1;
|
|
||||||
struct timeval zeroadj, remadj;
|
|
||||||
double adjustment_remaining, adjustment_achieved;
|
|
||||||
double elapsed, elapsed_plus_adjust;
|
|
||||||
|
|
||||||
zeroadj.tv_sec = 0;
|
|
||||||
zeroadj.tv_usec = 0;
|
|
||||||
|
|
||||||
if (adjtime(&zeroadj, &remadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
|
||||||
UTI_TimevalToDouble(&remadj, &adjustment_remaining);
|
|
||||||
|
|
||||||
adjustment_achieved = adjustment_requested - adjustment_remaining;
|
|
||||||
elapsed_plus_adjust = elapsed - adjustment_achieved;
|
|
||||||
|
|
||||||
offset_register += current_freq * elapsed_plus_adjust - adjustment_remaining;
|
|
||||||
|
|
||||||
adjustment_requested = 0.0;
|
|
||||||
T0 = T1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
@@ -201,59 +58,20 @@ stop_adjust(void)
|
|||||||
static void
|
static void
|
||||||
accrue_offset(double offset, double corr_rate)
|
accrue_offset(double offset, double corr_rate)
|
||||||
{
|
{
|
||||||
stop_adjust();
|
struct timeval newadj, oldadj;
|
||||||
offset_register += offset;
|
|
||||||
start_adjust();
|
|
||||||
|
|
||||||
}
|
UTI_DoubleToTimeval(-offset, &newadj);
|
||||||
|
|
||||||
/* ================================================== */
|
if (adjtime(&newadj, &oldadj) < 0)
|
||||||
|
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
||||||
|
|
||||||
/* Positive offset means system clock is fast of true time, therefore
|
/* Add the old remaining adjustment if not zero */
|
||||||
step backwards */
|
UTI_TimevalToDouble(&oldadj, &offset);
|
||||||
|
if (offset != 0.0) {
|
||||||
static void
|
UTI_AddDoubleToTimeval(&newadj, offset, &newadj);
|
||||||
apply_step_offset(double offset)
|
if (adjtime(&newadj, NULL) < 0)
|
||||||
{
|
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
||||||
struct timeval old_time, new_time, T1;
|
|
||||||
|
|
||||||
stop_adjust();
|
|
||||||
|
|
||||||
if (gettimeofday(&old_time, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
|
||||||
|
|
||||||
if (settimeofday(&new_time, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "settimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&T0, offset, &T1);
|
|
||||||
T0 = T1;
|
|
||||||
|
|
||||||
start_adjust();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static double
|
|
||||||
set_frequency(double new_freq_ppm)
|
|
||||||
{
|
|
||||||
stop_adjust();
|
|
||||||
current_freq = new_freq_ppm * 1.0e-6;
|
|
||||||
start_adjust();
|
|
||||||
|
|
||||||
return current_freq * 1.0e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static double
|
|
||||||
read_frequency(void)
|
|
||||||
{
|
|
||||||
return current_freq * 1.0e6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -262,11 +80,21 @@ static void
|
|||||||
get_offset_correction(struct timeval *raw,
|
get_offset_correction(struct timeval *raw,
|
||||||
double *corr, double *err)
|
double *corr, double *err)
|
||||||
{
|
{
|
||||||
stop_adjust();
|
struct timeval remadj;
|
||||||
*corr = -offset_register;
|
double adjustment_remaining;
|
||||||
start_adjust();
|
|
||||||
if (err)
|
if (adjtime(NULL, &remadj) < 0)
|
||||||
*err = 0.0;
|
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
|
||||||
|
|
||||||
|
UTI_TimevalToDouble(&remadj, &adjustment_remaining);
|
||||||
|
|
||||||
|
*corr = adjustment_remaining;
|
||||||
|
if (err) {
|
||||||
|
if (*corr != 0.0)
|
||||||
|
*err = 1.0e-6 * MAX_ADJTIME_SLEWRATE / ADJTIME_UPDATE_INTERVAL;
|
||||||
|
else
|
||||||
|
*err = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -274,42 +102,10 @@ get_offset_correction(struct timeval *raw,
|
|||||||
void
|
void
|
||||||
SYS_NetBSD_Initialise(void)
|
SYS_NetBSD_Initialise(void)
|
||||||
{
|
{
|
||||||
static struct nlist nl[] = {
|
SYS_Timex_InitialiseWithFunctions(MAX_FREQ, 1.0 / MIN_TICK_RATE,
|
||||||
{"_tickadj"},
|
NULL, NULL, NULL,
|
||||||
{"_bigadj"},
|
MIN_FASTSLEW_OFFSET, MAX_ADJTIME_SLEWRATE,
|
||||||
{NULL}
|
accrue_offset, get_offset_correction);
|
||||||
};
|
|
||||||
|
|
||||||
kvm_t *kt;
|
|
||||||
|
|
||||||
kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
|
||||||
if (!kt) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "Cannot open kvm");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_nlist(kt, nl) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "Cannot read kernel symbols");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_read(kt, nl[0].n_value, (char *)(&kern_tickadj), sizeof(int)) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysNetBSD, "Cannot read from _tickadj");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {
|
|
||||||
/* kernel doesn't have the symbol, use one second instead */
|
|
||||||
kern_bigadj = 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
kvm_close(kt);
|
|
||||||
|
|
||||||
clock_initialise();
|
|
||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
|
||||||
accrue_offset, apply_step_offset,
|
|
||||||
get_offset_correction,
|
|
||||||
NULL /* set_leap */,
|
|
||||||
NULL /* set_sync_status */);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -317,10 +113,32 @@ SYS_NetBSD_Initialise(void)
|
|||||||
void
|
void
|
||||||
SYS_NetBSD_Finalise(void)
|
SYS_NetBSD_Finalise(void)
|
||||||
{
|
{
|
||||||
clock_finalise();
|
SYS_Timex_Finalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
#ifdef FEAT_PRIVDROP
|
||||||
|
void
|
||||||
|
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
#endif /* __NetBSD__ */
|
if (setgroups(0, NULL))
|
||||||
|
LOG_FATAL(LOGF_SysNetBSD, "setgroups() failed : %s", strerror(errno));
|
||||||
|
|
||||||
|
if (setgid(gid))
|
||||||
|
LOG_FATAL(LOGF_SysNetBSD, "setgid(%d) failed : %s", gid, strerror(errno));
|
||||||
|
|
||||||
|
if (setuid(uid))
|
||||||
|
LOG_FATAL(LOGF_SysNetBSD, "setuid(%d) failed : %s", uid, strerror(errno));
|
||||||
|
|
||||||
|
DEBUG_LOG(LOGF_SysNetBSD, "Root dropped to uid %d gid %d", uid, gid);
|
||||||
|
|
||||||
|
/* Check if we have write access to /dev/clockctl */
|
||||||
|
fd = open("/dev/clockctl", O_WRONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
LOG_FATAL(LOGF_SysNetBSD, "Can't write to /dev/clockctl");
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -32,4 +32,6 @@ void SYS_NetBSD_Initialise(void);
|
|||||||
|
|
||||||
void SYS_NetBSD_Finalise(void);
|
void SYS_NetBSD_Finalise(void);
|
||||||
|
|
||||||
|
void SYS_NetBSD_DropRoot(uid_t uid, gid_t gid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
425
sys_solaris.c
425
sys_solaris.c
@@ -26,417 +26,18 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef SOLARIS
|
#include "sysincl.h"
|
||||||
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <nlist.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "sys_solaris.h"
|
#include "sys_solaris.h"
|
||||||
#include "localp.h"
|
#include "sys_timex.h"
|
||||||
#include "sched.h"
|
|
||||||
#include "logging.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* This register contains the number of seconds by which the local
|
|
||||||
clock was estimated to be fast of reference time at the epoch when
|
|
||||||
gettimeofday() returned T0 */
|
|
||||||
|
|
||||||
static double offset_register;
|
|
||||||
|
|
||||||
/* This register contains the epoch to which the offset is referenced */
|
|
||||||
|
|
||||||
static struct timeval T0;
|
|
||||||
|
|
||||||
/* This register contains the current estimate of the system
|
|
||||||
frequency, in absolute (NOT ppm) */
|
|
||||||
|
|
||||||
static double current_freq;
|
|
||||||
|
|
||||||
/* This register contains the number of seconds of adjustment that
|
|
||||||
were passed to adjtime last time it was called. */
|
|
||||||
|
|
||||||
static double adjustment_requested;
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
/* On Solaris 2.5 & 2.5.1, passing an argument of zero as the new
|
|
||||||
delta to adjtime does not zero out the adjustment - the remaining
|
|
||||||
adjustment is returned as the old delta arg, but the adjustment keeps
|
|
||||||
running. To get round this, we set adjustments of +/-1us when we
|
|
||||||
really want zero. Alternate adjustments are used to avoid a drift
|
|
||||||
from building up. */
|
|
||||||
|
|
||||||
static struct timeval zeroes[2] = {
|
|
||||||
{0, 1},
|
|
||||||
{-1, 999999}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int index=0;
|
|
||||||
|
|
||||||
/* If 1, need to run dosynctodr(). If 0, don't */
|
|
||||||
static int need_dosynctodr = -1;
|
|
||||||
|
|
||||||
|
|
||||||
#define GET_ZERO (zeroes[index^=1])
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
clock_initialise(void)
|
|
||||||
{
|
|
||||||
struct timeval newadj, oldadj;
|
|
||||||
|
|
||||||
offset_register = 0.0;
|
|
||||||
adjustment_requested = 0.0;
|
|
||||||
current_freq = 0.0;
|
|
||||||
|
|
||||||
if (gettimeofday(&T0, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
newadj = GET_ZERO;
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
clock_finalise(void)
|
|
||||||
{
|
|
||||||
/* Nothing to do yet */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_adjust(void)
|
|
||||||
{
|
|
||||||
struct timeval newadj, oldadj;
|
|
||||||
struct timeval T1;
|
|
||||||
double elapsed, accrued_error;
|
|
||||||
double adjust_required;
|
|
||||||
struct timeval exact_newadj;
|
|
||||||
double rounding_error;
|
|
||||||
double old_adjust_remaining;
|
|
||||||
|
|
||||||
/* Determine the amount of error built up since the last adjustment */
|
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
|
||||||
accrued_error = elapsed * current_freq;
|
|
||||||
|
|
||||||
adjust_required = - (accrued_error + offset_register);
|
|
||||||
|
|
||||||
UTI_DoubleToTimeval(adjust_required, &exact_newadj);
|
|
||||||
|
|
||||||
/* At this point, we will need to call the adjustment rounding
|
|
||||||
algorithm in the system-specific layer. For now, just assume the
|
|
||||||
adjustment can be applied exactly. */
|
|
||||||
|
|
||||||
newadj = exact_newadj;
|
|
||||||
|
|
||||||
/* Want to *add* rounding error back onto offset register */
|
|
||||||
UTI_DiffTimevalsToDouble(&rounding_error, &exact_newadj, &newadj);
|
|
||||||
|
|
||||||
if (adjtime(&newadj, &oldadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
|
|
||||||
|
|
||||||
offset_register = rounding_error - old_adjust_remaining;
|
|
||||||
|
|
||||||
T0 = T1;
|
|
||||||
UTI_TimevalToDouble(&newadj, &adjustment_requested);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
stop_adjust(void)
|
|
||||||
{
|
|
||||||
struct timeval T1;
|
|
||||||
struct timeval zeroadj, remadj;
|
|
||||||
double adjustment_remaining, adjustment_achieved;
|
|
||||||
double elapsed, elapsed_plus_adjust;
|
|
||||||
|
|
||||||
|
|
||||||
zeroadj = GET_ZERO;
|
|
||||||
|
|
||||||
if (adjtime(&zeroadj, &remadj) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gettimeofday(&T1, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
|
|
||||||
UTI_TimevalToDouble(&remadj, &adjustment_remaining);
|
|
||||||
|
|
||||||
adjustment_achieved = adjustment_requested - adjustment_remaining;
|
|
||||||
elapsed_plus_adjust = elapsed - adjustment_achieved;
|
|
||||||
|
|
||||||
offset_register += current_freq * elapsed_plus_adjust - adjustment_remaining;
|
|
||||||
|
|
||||||
adjustment_requested = 0.0;
|
|
||||||
T0 = T1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* Positive offset means system clock is fast of true time, therefore
|
|
||||||
slew backwards */
|
|
||||||
|
|
||||||
static void
|
|
||||||
accrue_offset(double offset, double corr_rate)
|
|
||||||
{
|
|
||||||
stop_adjust();
|
|
||||||
offset_register += offset;
|
|
||||||
start_adjust();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* Positive offset means system clock is fast of true time, therefore
|
|
||||||
step backwards */
|
|
||||||
|
|
||||||
static void
|
|
||||||
apply_step_offset(double offset)
|
|
||||||
{
|
|
||||||
struct timeval old_time, new_time, rounded_new_time, T1;
|
|
||||||
double rounding_error;
|
|
||||||
|
|
||||||
stop_adjust();
|
|
||||||
if (gettimeofday(&old_time, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
|
|
||||||
|
|
||||||
/* The settimeofday function (on Solaris 2.5/Sparc20 at least) does
|
|
||||||
not work quite as we would want. The time we want to set is
|
|
||||||
rounded to the nearest second and that time is used. Also, the
|
|
||||||
clock appears to start from that second boundary plus about 4ms.
|
|
||||||
For now we'll tolerate this small error. */
|
|
||||||
|
|
||||||
rounded_new_time.tv_usec = 0;
|
|
||||||
if (new_time.tv_usec >= 500000) {
|
|
||||||
rounded_new_time.tv_sec = new_time.tv_sec + 1;
|
|
||||||
} else {
|
|
||||||
rounded_new_time.tv_sec = new_time.tv_sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&rounding_error, &rounded_new_time, &new_time);
|
|
||||||
|
|
||||||
if (settimeofday(&new_time, NULL) < 0) {
|
|
||||||
LOG_FATAL(LOGF_SysSolaris, "settimeofday() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&T0, offset, &T1);
|
|
||||||
T0 = T1;
|
|
||||||
|
|
||||||
offset_register += rounding_error;
|
|
||||||
|
|
||||||
start_adjust();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static double
|
|
||||||
set_frequency(double new_freq_ppm)
|
|
||||||
{
|
|
||||||
stop_adjust();
|
|
||||||
current_freq = new_freq_ppm * 1.0e-6;
|
|
||||||
start_adjust();
|
|
||||||
|
|
||||||
return current_freq * 1.0e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static double
|
|
||||||
read_frequency(void)
|
|
||||||
{
|
|
||||||
return current_freq * 1.0e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_offset_correction(struct timeval *raw,
|
|
||||||
double *corr, double *err)
|
|
||||||
{
|
|
||||||
stop_adjust();
|
|
||||||
*corr = -offset_register;
|
|
||||||
start_adjust();
|
|
||||||
if (err)
|
|
||||||
*err = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
immediate_step(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
/* Interval in seconds between adjustments to cancel systematic drift */
|
|
||||||
#define DRIFT_REMOVAL_INTERVAL (4.0)
|
|
||||||
|
|
||||||
static int drift_removal_running = 0;
|
|
||||||
static SCH_TimeoutID drift_removal_id;
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
/* This is the timer callback routine which is called periodically to
|
|
||||||
invoke a time adjustment to take out the machine's drift.
|
|
||||||
Otherwise, times reported through this software (e.g. by running
|
|
||||||
ntpdate from another machine) show the machine being correct (since
|
|
||||||
they correct for drift build-up), but any program on this machine
|
|
||||||
that reads the system time will be given an erroneous value, the
|
|
||||||
degree of error depending on how long it is since
|
|
||||||
get_offset_correction was last called. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
drift_removal_timeout(SCH_ArbitraryArgument not_used)
|
|
||||||
{
|
|
||||||
stop_adjust();
|
|
||||||
start_adjust();
|
|
||||||
drift_removal_id = SCH_AddTimeoutByDelay(DRIFT_REMOVAL_INTERVAL, drift_removal_timeout, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_need_dosynctodr(void)
|
|
||||||
{
|
|
||||||
struct utsname name;
|
|
||||||
int result;
|
|
||||||
int major, minor, veryminor, n_fields;
|
|
||||||
|
|
||||||
result = uname(&name);
|
|
||||||
if (result < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Cannot use uname to detect Solaris version");
|
|
||||||
need_dosynctodr = 0; /* Assume recent Solaris where it isn't needed */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_fields = sscanf(name.release, "%d.%d.%d\n", &major, &minor, &veryminor);
|
|
||||||
|
|
||||||
if (n_fields < 2) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Solaris version doesn't appear to be of the form X.Y[.Z]");
|
|
||||||
need_dosynctodr = 0; /* Assume recent Solaris where it isn't needed */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (major != 5) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Solaris major version doesn't appear to be 5");
|
|
||||||
need_dosynctodr = 0; /* Assume recent Solaris where it isn't needed */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The 'rule of thumb' is that from Solaris 2.6 onwards, dosynctodr() doesn't
|
|
||||||
* need to be called, and in fact it is counter-productive to do so. For
|
|
||||||
* earlier versions, it is required. */
|
|
||||||
|
|
||||||
if (minor < 6) {
|
|
||||||
need_dosynctodr = 1;
|
|
||||||
} else {
|
|
||||||
need_dosynctodr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_dosynctodr(unsigned long on_off)
|
|
||||||
{
|
|
||||||
static struct nlist nl[] = {
|
|
||||||
{"dosynctodr"},
|
|
||||||
{NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
kvm_t *kt;
|
|
||||||
unsigned long read_back;
|
|
||||||
|
|
||||||
assert(on_off == 1 || on_off == 0);
|
|
||||||
|
|
||||||
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
|
|
||||||
if (!kt) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Cannot open kvm to change dosynctodr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_nlist(kt, nl) < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Cannot read dosynctodr in nlist");
|
|
||||||
kvm_close(kt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_write(kt, nl[0].n_value, (char *)(&on_off), sizeof(unsigned long)) < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Cannot write to dosynctodr");
|
|
||||||
kvm_close(kt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kvm_read(kt, nl[0].n_value, (char *)(&read_back), sizeof(unsigned long)) < 0) {
|
|
||||||
LOG(LOGS_ERR, LOGF_SysSolaris, "Cannot read from dosynctodr");
|
|
||||||
kvm_close(kt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
kvm_close(kt);
|
|
||||||
|
|
||||||
assert(read_back == on_off);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SYS_Solaris_Initialise(void)
|
SYS_Solaris_Initialise(void)
|
||||||
{
|
{
|
||||||
|
/* The kernel allows the frequency to be set in the full range off int32_t */
|
||||||
check_need_dosynctodr();
|
SYS_Timex_InitialiseWithFunctions(32500, 1.0 / 100, NULL, NULL, NULL);
|
||||||
|
|
||||||
/* Need to do KVM stuff to turn off dosynctodr. */
|
|
||||||
|
|
||||||
clock_initialise();
|
|
||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
|
||||||
accrue_offset, apply_step_offset,
|
|
||||||
get_offset_correction,
|
|
||||||
NULL /* set_leap */,
|
|
||||||
NULL /* set_sync_status */);
|
|
||||||
|
|
||||||
/* Turn off the kernel switch that keeps the system clock in step
|
|
||||||
with the non-volatile clock */
|
|
||||||
if (need_dosynctodr) {
|
|
||||||
set_dosynctodr(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
drift_removal_id = SCH_AddTimeoutByDelay(DRIFT_REMOVAL_INTERVAL, drift_removal_timeout, NULL);
|
|
||||||
drift_removal_running = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -444,21 +45,5 @@ SYS_Solaris_Initialise(void)
|
|||||||
void
|
void
|
||||||
SYS_Solaris_Finalise(void)
|
SYS_Solaris_Finalise(void)
|
||||||
{
|
{
|
||||||
|
SYS_Timex_Finalise();
|
||||||
if (drift_removal_running) {
|
|
||||||
SCH_RemoveTimeout(drift_removal_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_finalise();
|
|
||||||
|
|
||||||
/* When exiting, we want to return the machine to its 'autonomous'
|
|
||||||
tracking mode */
|
|
||||||
if (need_dosynctodr) {
|
|
||||||
set_dosynctodr(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
#endif /* SOLARIS */
|
|
||||||
|
|
||||||
|
|||||||
243
sys_timex.c
Normal file
243
sys_timex.c
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
|
* Copyright (C) Miroslav Lichvar 2009-2012, 2014-2015
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Driver for systems that implement the adjtimex()/ntp_adjtime() system call
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "sysincl.h"
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "sys_timex.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
#define NTP_ADJTIME adjtimex
|
||||||
|
#define NTP_ADJTIME_NAME "adjtimex"
|
||||||
|
#else
|
||||||
|
#define NTP_ADJTIME ntp_adjtime
|
||||||
|
#define NTP_ADJTIME_NAME "ntp_adjtime"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum frequency offset accepted by the kernel (in ppm) */
|
||||||
|
#define MAX_FREQ 500.0
|
||||||
|
|
||||||
|
/* Frequency scale to convert from ppm to the timex freq */
|
||||||
|
#define FREQ_SCALE (double)(1 << 16)
|
||||||
|
|
||||||
|
/* Threshold for the timex maxerror when the kernel sets the UNSYNC flag */
|
||||||
|
#define MAX_SYNC_ERROR 16.0
|
||||||
|
|
||||||
|
/* Minimum assumed rate at which the kernel updates the clock frequency */
|
||||||
|
#define MIN_TICK_RATE 100
|
||||||
|
|
||||||
|
/* Saved timex status */
|
||||||
|
static int status;
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static double
|
||||||
|
read_frequency(void)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
txc.modes = 0;
|
||||||
|
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
|
return txc.freq / -FREQ_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static double
|
||||||
|
set_frequency(double freq_ppm)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
txc.modes = MOD_FREQUENCY;
|
||||||
|
txc.freq = freq_ppm * -FREQ_SCALE;
|
||||||
|
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
|
return txc.freq / -FREQ_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_leap(int leap)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
int applied;
|
||||||
|
|
||||||
|
applied = 0;
|
||||||
|
if (!leap) {
|
||||||
|
txc.modes = 0;
|
||||||
|
if (SYS_Timex_Adjust(&txc, 1) == TIME_WAIT)
|
||||||
|
applied = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status &= ~(STA_INS | STA_DEL);
|
||||||
|
|
||||||
|
if (leap > 0)
|
||||||
|
status |= STA_INS;
|
||||||
|
else if (leap < 0)
|
||||||
|
status |= STA_DEL;
|
||||||
|
|
||||||
|
txc.modes = MOD_STATUS;
|
||||||
|
txc.status = status;
|
||||||
|
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
|
LOG(LOGS_INFO, LOGF_SysTimex, "System clock status %s leap second",
|
||||||
|
leap ? (leap > 0 ? "set to insert" : "set to delete") :
|
||||||
|
(applied ? "reset after" : "set to not insert/delete"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sync_status(int synchronised, double est_error, double max_error)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
if (synchronised) {
|
||||||
|
if (est_error > MAX_SYNC_ERROR)
|
||||||
|
est_error = MAX_SYNC_ERROR;
|
||||||
|
if (max_error >= MAX_SYNC_ERROR) {
|
||||||
|
max_error = MAX_SYNC_ERROR;
|
||||||
|
synchronised = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
est_error = max_error = MAX_SYNC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
/* On Linux clear the UNSYNC flag only if rtcsync is enabled */
|
||||||
|
if (!CNF_GetRtcSync())
|
||||||
|
synchronised = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (synchronised)
|
||||||
|
status &= ~STA_UNSYNC;
|
||||||
|
else
|
||||||
|
status |= STA_UNSYNC;
|
||||||
|
|
||||||
|
txc.modes = MOD_STATUS | MOD_ESTERROR | MOD_MAXERROR;
|
||||||
|
txc.status = status;
|
||||||
|
txc.esterror = est_error * 1.0e6;
|
||||||
|
txc.maxerror = max_error * 1.0e6;
|
||||||
|
|
||||||
|
SYS_Timex_Adjust(&txc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
initialise_timex(void)
|
||||||
|
{
|
||||||
|
struct timex txc;
|
||||||
|
|
||||||
|
status = STA_UNSYNC;
|
||||||
|
|
||||||
|
/* Reset PLL offset */
|
||||||
|
txc.modes = MOD_OFFSET | MOD_STATUS;
|
||||||
|
txc.status = STA_PLL | status;
|
||||||
|
txc.offset = 0;
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
|
||||||
|
/* Turn PLL off */
|
||||||
|
txc.modes = MOD_STATUS;
|
||||||
|
txc.status = status;
|
||||||
|
SYS_Timex_Adjust(&txc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
SYS_Timex_Initialise(void)
|
||||||
|
{
|
||||||
|
SYS_Timex_InitialiseWithFunctions(MAX_FREQ, 1.0 / MIN_TICK_RATE, NULL, NULL, NULL,
|
||||||
|
0.0, 0.0, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
SYS_Timex_InitialiseWithFunctions(double max_set_freq_ppm, double max_set_freq_delay,
|
||||||
|
lcl_ReadFrequencyDriver sys_read_freq,
|
||||||
|
lcl_SetFrequencyDriver sys_set_freq,
|
||||||
|
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
||||||
|
double min_fastslew_offset, double max_fastslew_rate,
|
||||||
|
lcl_AccrueOffsetDriver sys_accrue_offset,
|
||||||
|
lcl_OffsetCorrectionDriver sys_get_offset_correction)
|
||||||
|
{
|
||||||
|
initialise_timex();
|
||||||
|
|
||||||
|
SYS_Generic_CompleteFreqDriver(max_set_freq_ppm, max_set_freq_delay,
|
||||||
|
sys_read_freq ? sys_read_freq : read_frequency,
|
||||||
|
sys_set_freq ? sys_set_freq : set_frequency,
|
||||||
|
sys_apply_step_offset,
|
||||||
|
min_fastslew_offset, max_fastslew_rate,
|
||||||
|
sys_accrue_offset, sys_get_offset_correction,
|
||||||
|
set_leap, set_sync_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
SYS_Timex_Finalise(void)
|
||||||
|
{
|
||||||
|
SYS_Generic_Finalise();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
SYS_Timex_Adjust(struct timex *txc, int ignore_error)
|
||||||
|
{
|
||||||
|
int state;
|
||||||
|
|
||||||
|
#ifdef SOLARIS
|
||||||
|
/* The kernel seems to check the constant even when it's not being set */
|
||||||
|
if (!(txc->modes & MOD_TIMECONST))
|
||||||
|
txc->constant = 10;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state = NTP_ADJTIME(txc);
|
||||||
|
|
||||||
|
if (state < 0) {
|
||||||
|
if (!ignore_error)
|
||||||
|
LOG_FATAL(LOGF_SysTimex, NTP_ADJTIME_NAME"(0x%x) failed : %s",
|
||||||
|
txc->modes, strerror(errno));
|
||||||
|
else
|
||||||
|
DEBUG_LOG(LOGF_SysTimex, NTP_ADJTIME_NAME"(0x%x) failed : %s",
|
||||||
|
txc->modes, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
50
sys_timex.h
Normal file
50
sys_timex.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Header file for a driver based on the adjtimex()/ntp_adjtime() function
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GOT_SYS_TIMEX_H
|
||||||
|
#define GOT_SYS_TIMEX_H
|
||||||
|
|
||||||
|
#include <sys/timex.h>
|
||||||
|
|
||||||
|
#include "localp.h"
|
||||||
|
|
||||||
|
extern void SYS_Timex_Initialise(void);
|
||||||
|
|
||||||
|
/* Initialise with some driver functions replaced with special versions */
|
||||||
|
extern void SYS_Timex_InitialiseWithFunctions(double max_set_freq_ppm, double max_set_freq_delay,
|
||||||
|
lcl_ReadFrequencyDriver sys_read_freq,
|
||||||
|
lcl_SetFrequencyDriver sys_set_freq,
|
||||||
|
lcl_ApplyStepOffsetDriver sys_apply_step_offset,
|
||||||
|
double min_fastslew_offset, double max_fastslew_rate,
|
||||||
|
lcl_AccrueOffsetDriver sys_accrue_offset,
|
||||||
|
lcl_OffsetCorrectionDriver sys_get_offset_correction);
|
||||||
|
|
||||||
|
extern void SYS_Timex_Finalise(void);
|
||||||
|
|
||||||
|
/* Wrapper for adjtimex()/ntp_adjtime() */
|
||||||
|
extern int SYS_Timex_Adjust(struct timex *txc, int ignore_error);
|
||||||
|
|
||||||
|
#endif /* GOT_SYS_GENERIC_H */
|
||||||
64
sysincl.h
64
sysincl.h
@@ -29,22 +29,16 @@
|
|||||||
#ifndef GOT_SYSINCL_H
|
#ifndef GOT_SYSINCL_H
|
||||||
#define GOT_SYSINCL_H
|
#define GOT_SYSINCL_H
|
||||||
|
|
||||||
#if defined (SOLARIS) || defined(SUNOS) || defined(LINUX) || defined(__NetBSD__)
|
|
||||||
|
|
||||||
#if !defined(__NetBSD__) && !defined(__FreeBSD__)
|
|
||||||
#include <alloca.h>
|
|
||||||
#endif
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#if !defined(__FreeBSD__)
|
#include <glob.h>
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -61,6 +55,7 @@
|
|||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
#ifdef HAVE_INTTYPES_H
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -70,62 +65,9 @@
|
|||||||
/* Tough */
|
/* Tough */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* One or other of these to make getsid() visible */
|
|
||||||
#define __EXTENSIONS__ 1
|
|
||||||
#define __USE_XOPEN_EXTENDED 1
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FEAT_IPV6
|
#ifdef FEAT_IPV6
|
||||||
/* For inet_ntop() */
|
/* For inet_ntop() */
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (SOLARIS) || defined(SUNOS)
|
|
||||||
/* Only needed on these platforms, and doesn't exist on some Linux
|
|
||||||
versions. */
|
|
||||||
#include <nlist.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (WINNT)
|
|
||||||
|
|
||||||
/* Designed to work with the GCC from the GNAT-3.10 for Win32
|
|
||||||
distribution */
|
|
||||||
|
|
||||||
#define Win32_Winsock
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Cheat and inline the necessary bits from <errno.h>. We don't
|
|
||||||
include it directly because it redefines some EXXX constants that
|
|
||||||
conflict with <windows32/sockets.h> (included by <windows.h>) */
|
|
||||||
|
|
||||||
int* _errno();
|
|
||||||
int* __doserrno();
|
|
||||||
|
|
||||||
#define errno (*_errno())
|
|
||||||
#define _doserrno (*__doserrno())
|
|
||||||
|
|
||||||
#define ENOENT 2
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <float.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* GOT_SYSINCL_H */
|
#endif /* GOT_SYSINCL_H */
|
||||||
|
|||||||
@@ -5,8 +5,14 @@
|
|||||||
cd ../..
|
cd ../..
|
||||||
|
|
||||||
for opts in \
|
for opts in \
|
||||||
|
"--enable-debug" \
|
||||||
"--disable-asyncdns" \
|
"--disable-asyncdns" \
|
||||||
|
"--disable-ipv6" \
|
||||||
|
"--disable-privdrop" \
|
||||||
|
"--disable-readline" \
|
||||||
"--disable-rtc" \
|
"--disable-rtc" \
|
||||||
|
"--disable-scfilter" \
|
||||||
|
"--disable-sechash" \
|
||||||
"--disable-cmdmon" \
|
"--disable-cmdmon" \
|
||||||
"--disable-ntp" \
|
"--disable-ntp" \
|
||||||
"--disable-refclock" \
|
"--disable-refclock" \
|
||||||
@@ -15,5 +21,5 @@ for opts in \
|
|||||||
"--disable-cmdmon --disable-ntp --disable-refclock"
|
"--disable-cmdmon --disable-ntp --disable-refclock"
|
||||||
do
|
do
|
||||||
./configure $opts
|
./configure $opts
|
||||||
make || exit 1
|
make "$@" || exit 1
|
||||||
done
|
done
|
||||||
|
|||||||
7
test/kernel/Makefile
Normal file
7
test/kernel/Makefile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
CFLAGS=-O2 -Wall
|
||||||
|
PROGS=adjtime ntpadjtime
|
||||||
|
|
||||||
|
all: $(PROGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PROGS)
|
||||||
185
test/kernel/adjtime.c
Normal file
185
test/kernel/adjtime.c
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Test the system adjtime() function. Check the range of supported offset,
|
||||||
|
support for readonly operation, and slew rate with different update
|
||||||
|
intervals and offsets. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
diff_tv(struct timeval *tv1, struct timeval *tv2)
|
||||||
|
{
|
||||||
|
return 1000000 * (tv1->tv_sec - tv2->tv_sec) + (tv1->tv_usec - tv2->tv_usec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct timeval
|
||||||
|
usec_to_tv(int usec)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = usec / 1000000;
|
||||||
|
tv.tv_usec = usec % 1000000;
|
||||||
|
|
||||||
|
return tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
try_adjtime(struct timeval *new, struct timeval *old)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = adjtime(new, old);
|
||||||
|
if (r)
|
||||||
|
printf("adjtime() failed : %s ", strerror(errno));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_adjtime(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv = usec_to_tv(0);
|
||||||
|
try_adjtime(&tv, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_range(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("range:\n");
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (time_t) * 8; i++) {
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
tv.tv_sec = (1ULL << i) - 1;
|
||||||
|
printf("%20lld s : ", (long long)tv.tv_sec);
|
||||||
|
printf("%s\n", !try_adjtime(&tv, NULL) ? "ok" : "");
|
||||||
|
tv.tv_sec = ~tv.tv_sec;
|
||||||
|
printf("%20lld s : ", (long long)tv.tv_sec);
|
||||||
|
printf("%s\n", !try_adjtime(&tv, NULL) ? "ok" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_readonly(void)
|
||||||
|
{
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
printf("readonly:\n");
|
||||||
|
|
||||||
|
for (i = 0; i <= 20; i++) {
|
||||||
|
tv1 = usec_to_tv(1 << i);
|
||||||
|
|
||||||
|
printf("%9d us : ", 1 << i);
|
||||||
|
try_adjtime(&tv1, NULL);
|
||||||
|
r = !try_adjtime(NULL, &tv2) && !diff_tv(&tv1, &tv2);
|
||||||
|
printf("%s\n", r ? "ok" : "fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_readwrite(void)
|
||||||
|
{
|
||||||
|
struct timeval tv1, tv2, tv3;
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
printf("readwrite:\n");
|
||||||
|
|
||||||
|
for (i = 0; i <= 20; i++) {
|
||||||
|
tv1 = usec_to_tv(1 << i);
|
||||||
|
tv3 = usec_to_tv(0);
|
||||||
|
|
||||||
|
printf("%9d us : ", 1 << i);
|
||||||
|
try_adjtime(&tv1, NULL);
|
||||||
|
r = !try_adjtime(&tv3, &tv2) && !diff_tv(&tv1, &tv2);
|
||||||
|
printf("%s\n", r ? "ok" : "fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xusleep(int usec)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv = usec_to_tv(usec);
|
||||||
|
select(0, NULL, NULL, NULL, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_slew(void)
|
||||||
|
{
|
||||||
|
struct timeval tv1, tv2, tv3;
|
||||||
|
int i, j, k, diff, min, has_min;
|
||||||
|
|
||||||
|
printf("slew:\n");
|
||||||
|
|
||||||
|
for (i = 9; i <= 20; i++) {
|
||||||
|
printf("%9d us : ", 1 << i);
|
||||||
|
for (j = 4; j <= 20; j += 4) {
|
||||||
|
for (min = has_min = 0, k = 4; k < 16; k += 2) {
|
||||||
|
|
||||||
|
tv1 = usec_to_tv(1 << j);
|
||||||
|
tv3 = usec_to_tv(0);
|
||||||
|
|
||||||
|
xusleep(1 << i);
|
||||||
|
reset_adjtime();
|
||||||
|
|
||||||
|
xusleep(1 << i);
|
||||||
|
if (try_adjtime(&tv1, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
xusleep(1 << i);
|
||||||
|
if (try_adjtime(&tv3, &tv2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
diff = diff_tv(&tv1, &tv2);
|
||||||
|
if (!has_min || min > diff) {
|
||||||
|
min = diff;
|
||||||
|
has_min = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_min)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf(" %5d (%d)", min, 1 << j);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
test_range();
|
||||||
|
test_readonly();
|
||||||
|
test_readwrite();
|
||||||
|
test_slew();
|
||||||
|
|
||||||
|
reset_adjtime();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
75
test/kernel/ntpadjtime.c
Normal file
75
test/kernel/ntpadjtime.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Miroslav Lichvar 2015
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check the frequency range of the system ntp_adjtime() implementation */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/timex.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
try_ntpadjtime(struct timex *t)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = ntp_adjtime(t);
|
||||||
|
if (r < 0)
|
||||||
|
printf("ntp_adjtime() failed : %s ", strerror(errno));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_ntpadjtime(void)
|
||||||
|
{
|
||||||
|
struct timex t;
|
||||||
|
|
||||||
|
t.modes = MOD_OFFSET | MOD_FREQUENCY;
|
||||||
|
t.offset = 0;
|
||||||
|
t.freq = 0;
|
||||||
|
try_ntpadjtime(&t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_freqrange(void)
|
||||||
|
{
|
||||||
|
struct timex t;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("freq range:\n");
|
||||||
|
|
||||||
|
for (i = 0; i <= 1000; i += 50) {
|
||||||
|
t.modes = MOD_FREQUENCY;
|
||||||
|
t.freq = i << 16;
|
||||||
|
printf("%4d ppm => ", i);
|
||||||
|
if (try_ntpadjtime(&t) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf("%4ld ppm : ", t.freq / (1 << 16));
|
||||||
|
printf("%s\n", t.freq == i << 16 ? "ok" : "fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
test_freqrange();
|
||||||
|
|
||||||
|
reset_ntpadjtime();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ test_start "source selection"
|
|||||||
|
|
||||||
# Falsetickers should be detected if their number is less than half of all
|
# Falsetickers should be detected if their number is less than half of all
|
||||||
|
|
||||||
|
base_delay=1e-3
|
||||||
servers=5
|
servers=5
|
||||||
|
|
||||||
for falsetickers in 1 2; do
|
for falsetickers in 1 2; do
|
||||||
@@ -29,7 +30,7 @@ done
|
|||||||
|
|
||||||
servers=3
|
servers=3
|
||||||
falsetickers=0
|
falsetickers=0
|
||||||
base_delay="(+ $default_base_delay (equal 0.1 to 2) (equal 0.1 to 3))"
|
base_delay="(+ 1e-3 (equal 0.1 to 2) (equal 0.1 to 3))"
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
|
|||||||
@@ -5,17 +5,42 @@ test_start "leap second"
|
|||||||
|
|
||||||
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]
|
||||||
limit=$[4 * 24 * 3600]
|
limit=$[4 * 24 * 3600]
|
||||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||||
leapsectz right/UTC"
|
leapsectz right/UTC"
|
||||||
server_step="(* 1.0 (equal 0.1 (sum 1.0) $[2 * 24 * 3600 + 1]))"
|
|
||||||
client_step="(* 1.0 (equal 0.1 (sum 1.0) $[2 * 24 * 3600 + 1]))"
|
|
||||||
refclock_jitter=1e-9
|
refclock_jitter=1e-9
|
||||||
|
refclock_offset="(* -1.0 (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||||
|
|
||||||
run_test || test_fail
|
for leapmode in system step slew; do
|
||||||
check_chronyd_exit || test_fail
|
client_conf="leapsecmode $leapmode"
|
||||||
check_source_selection || test_fail
|
if [ $leapmode = slew ]; then
|
||||||
check_packet_interval || test_fail
|
max_sync_time=$[$leap + 12]
|
||||||
check_sync || test_fail
|
else
|
||||||
|
max_sync_time=$[$leap]
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
done
|
||||||
|
|
||||||
|
for smoothmode in "" "leaponly"; do
|
||||||
|
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||||
|
leapsectz right/UTC
|
||||||
|
leapsecmode slew
|
||||||
|
smoothtime 400 0.001 $smoothmode"
|
||||||
|
client_conf="leapsecmode system"
|
||||||
|
min_sync_time=230000
|
||||||
|
max_sync_time=240000
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
done
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ test_start "presend option"
|
|||||||
|
|
||||||
min_sync_time=140
|
min_sync_time=140
|
||||||
max_sync_time=260
|
max_sync_time=260
|
||||||
client_server_options="presend 6"
|
client_server_options="presend 6 maxdelay 16"
|
||||||
|
client_conf="maxdistance 10"
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
|
|||||||
23
test/simulation/117-fallbackdrift
Executable file
23
test/simulation/117-fallbackdrift
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. test.common
|
||||||
|
test_start "fallback drift"
|
||||||
|
|
||||||
|
limit=100000
|
||||||
|
wander=0.0
|
||||||
|
jitter=1e-6
|
||||||
|
time_offset=10
|
||||||
|
freq_offset="(* 1e-4 (sine 1000))"
|
||||||
|
base_delay="(* -1.0 (equal 0.1 (min time 4250) 4250))"
|
||||||
|
client_server_options="minpoll 4 maxpoll 4"
|
||||||
|
client_conf="fallbackdrift 6 10"
|
||||||
|
time_max_limit=1e0
|
||||||
|
time_rms_limit=1e0
|
||||||
|
freq_max_limit=5e-4
|
||||||
|
freq_rms_limit=5e-4
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
test_pass
|
||||||
28
test/simulation/118-maxdelay
Executable file
28
test/simulation/118-maxdelay
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. test.common
|
||||||
|
test_start "maxdelay options"
|
||||||
|
|
||||||
|
max_sync_time=2000
|
||||||
|
base_delay=1e-5
|
||||||
|
jitter=1e-5
|
||||||
|
wander=0.0
|
||||||
|
freq_offset="(sum 1e-10)"
|
||||||
|
time_rms_limit=2e-4
|
||||||
|
|
||||||
|
client_server_options="maxdelay 3e-5 maxdelayratio 2.0 maxdelaydevratio 2.0"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
for client_server_options in "maxdelay 2e-5" \ "maxdelayratio 1.001"; do
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync && test_fail
|
||||||
|
done
|
||||||
|
|
||||||
|
test_pass
|
||||||
68
test/simulation/119-smoothtime
Executable file
68
test/simulation/119-smoothtime
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. test.common
|
||||||
|
test_start "smoothtime option"
|
||||||
|
|
||||||
|
server_strata=2
|
||||||
|
server_conf="smoothtime 400 0.001"
|
||||||
|
min_sync_time=250
|
||||||
|
max_sync_time=1000
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
limit=10000
|
||||||
|
refclock_jitter=1e-4
|
||||||
|
refclock_offset="(* 10.0 (equal 0.1 (max (sum 1.0) 1000) 1000))"
|
||||||
|
server_step="(* -10.0 (equal 0.1 (sum 1.0) 1))"
|
||||||
|
server_strata=1
|
||||||
|
server_conf="refclock SHM 0 dpoll 4 poll 6
|
||||||
|
smoothtime 2000 1"
|
||||||
|
time_offset=-10
|
||||||
|
client_server_options="minpoll 6 maxpoll 6"
|
||||||
|
client_conf="corrtimeratio 100"
|
||||||
|
min_sync_time=8000
|
||||||
|
max_sync_time=8500
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
min_sync_time=$default_min_sync_time
|
||||||
|
max_sync_time=$default_max_sync_time
|
||||||
|
time_max_limit=11
|
||||||
|
time_rms_limit=11
|
||||||
|
freq_max_limit=1e-2
|
||||||
|
freq_rms_limit=2e-3
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
refclock_jitter=1e-9
|
||||||
|
refclock_offset="(* 1e-1 (triangle 1000) (+ -1.0 (pulse 1000 10000)))"
|
||||||
|
server_step=""
|
||||||
|
server_conf="refclock SHM 0 dpoll 4 poll 6 minsamples 4 maxsamples 4
|
||||||
|
smoothtime 1e4 1e-6"
|
||||||
|
client_server_options="minpoll 4 maxpoll 4"
|
||||||
|
time_offset=0.1
|
||||||
|
jitter=1e-6
|
||||||
|
wander=0.0
|
||||||
|
min_sync_time=30
|
||||||
|
max_sync_time=40
|
||||||
|
time_max_limit=1e-5
|
||||||
|
time_rms_limit=5e-6
|
||||||
|
freq_max_limit=1e-6
|
||||||
|
freq_rms_limit=1e-7
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
test_pass
|
||||||
21
test/simulation/202-prefer
Executable file
21
test/simulation/202-prefer
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. test.common
|
||||||
|
|
||||||
|
# Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629
|
||||||
|
|
||||||
|
test_start "prefer option"
|
||||||
|
|
||||||
|
servers=3
|
||||||
|
client_server_conf="
|
||||||
|
server 192.168.123.1
|
||||||
|
server 192.168.123.2
|
||||||
|
server 192.168.123.3 prefer"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
test_pass
|
||||||
@@ -18,7 +18,7 @@ export PATH=../../:$PATH
|
|||||||
export CLKNETSIM_PATH=clknetsim
|
export CLKNETSIM_PATH=clknetsim
|
||||||
|
|
||||||
# Known working clknetsim revision
|
# Known working clknetsim revision
|
||||||
clknetsim_revision=565e593b4403d035b459b4f8516dacaeaeeb7739
|
clknetsim_revision=1e56224dee1db69c0027e9bd63c2a202d4765959
|
||||||
clknetsim_url=https://github.com/mlichvar/clknetsim/archive/$clknetsim_revision.tar.gz
|
clknetsim_url=https://github.com/mlichvar/clknetsim/archive/$clknetsim_revision.tar.gz
|
||||||
|
|
||||||
# Only Linux is supported
|
# Only Linux is supported
|
||||||
@@ -49,6 +49,7 @@ default_base_delay=1e-4
|
|||||||
default_jitter=1e-4
|
default_jitter=1e-4
|
||||||
default_wander=1e-9
|
default_wander=1e-9
|
||||||
default_refclock_jitter=""
|
default_refclock_jitter=""
|
||||||
|
default_refclock_offset=0.0
|
||||||
|
|
||||||
default_update_interval=0
|
default_update_interval=0
|
||||||
default_shift_pll=2
|
default_shift_pll=2
|
||||||
@@ -64,6 +65,7 @@ default_chronyc_start=1000.0
|
|||||||
default_server_step=""
|
default_server_step=""
|
||||||
default_client_step=""
|
default_client_step=""
|
||||||
|
|
||||||
|
default_client_server_conf=""
|
||||||
default_server_server_options=""
|
default_server_server_options=""
|
||||||
default_client_server_options=""
|
default_client_server_options=""
|
||||||
default_server_peer_options=""
|
default_server_peer_options=""
|
||||||
@@ -168,7 +170,7 @@ get_delay_expr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_refclock_expr() {
|
get_refclock_expr() {
|
||||||
echo "(* $refclock_jitter (normal))"
|
echo "(+ $refclock_offset (* $refclock_jitter (normal)))"
|
||||||
}
|
}
|
||||||
|
|
||||||
get_chronyd_nodes() {
|
get_chronyd_nodes() {
|
||||||
@@ -191,9 +193,13 @@ get_chronyd_conf() {
|
|||||||
done
|
done
|
||||||
echo "$server_conf"
|
echo "$server_conf"
|
||||||
else
|
else
|
||||||
for i in $(seq 1 $servers); do
|
if [ -n "$client_server_conf" ]; then
|
||||||
echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options"
|
echo "$client_server_conf"
|
||||||
done
|
else
|
||||||
|
for i in $(seq 1 $servers); do
|
||||||
|
echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options"
|
||||||
|
done
|
||||||
|
fi
|
||||||
for i in $(seq 1 $peers); do
|
for i in $(seq 1 $peers); do
|
||||||
[ $i -eq $peer -o $i -gt $clients ] && continue
|
[ $i -eq $peer -o $i -gt $clients ] && continue
|
||||||
echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $client_peer_options"
|
echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $client_peer_options"
|
||||||
@@ -261,7 +267,7 @@ check_source_selection() {
|
|||||||
for i in $(seq $[$servers * $server_strata + 1] $(get_chronyd_nodes)); do
|
for i in $(seq $[$servers * $server_strata + 1] $(get_chronyd_nodes)); do
|
||||||
test_message 3 0 "node $i:"
|
test_message 3 0 "node $i:"
|
||||||
|
|
||||||
! grep -q 'no majority\|no reachable sources' tmp/log.$i && \
|
! grep -q 'no majority\|no selectable sources' tmp/log.$i && \
|
||||||
grep -q 'Selected source' tmp/log.$i && \
|
grep -q 'Selected source' tmp/log.$i && \
|
||||||
test_ok || test_bad
|
test_ok || test_bad
|
||||||
[ $? -eq 0 ] || ret=1
|
[ $? -eq 0 ] || ret=1
|
||||||
|
|||||||
314
util.c
314
util.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009, 2012-2013
|
* Copyright (C) Miroslav Lichvar 2009, 2012-2015
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -29,12 +29,14 @@
|
|||||||
|
|
||||||
#include "sysincl.h"
|
#include "sysincl.h"
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_TimevalToDouble(struct timeval *a, double *b)
|
UTI_TimevalToDouble(struct timeval *a, double *b)
|
||||||
{
|
{
|
||||||
*b = (double)(a->tv_sec) + 1.0e-6 * (double)(a->tv_usec);
|
*b = (double)(a->tv_sec) + 1.0e-6 * (double)(a->tv_usec);
|
||||||
@@ -43,20 +45,22 @@ UTI_TimevalToDouble(struct timeval *a, double *b)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_DoubleToTimeval(double a, struct timeval *b)
|
UTI_DoubleToTimeval(double a, struct timeval *b)
|
||||||
{
|
{
|
||||||
long int_part, frac_part;
|
long int_part;
|
||||||
|
double frac_part;
|
||||||
int_part = (long)(a);
|
int_part = (long)(a);
|
||||||
frac_part = (long)(0.5 + 1.0e6 * (a - (double)(int_part)));
|
frac_part = 1.0e6 * (a - (double)(int_part));
|
||||||
|
frac_part = frac_part > 0 ? frac_part + 0.5 : frac_part - 0.5;
|
||||||
b->tv_sec = int_part;
|
b->tv_sec = int_part;
|
||||||
b->tv_usec = frac_part;
|
b->tv_usec = (long)frac_part;
|
||||||
UTI_NormaliseTimeval(b);
|
UTI_NormaliseTimeval(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC int
|
int
|
||||||
UTI_CompareTimevals(struct timeval *a, struct timeval *b)
|
UTI_CompareTimevals(struct timeval *a, struct timeval *b)
|
||||||
{
|
{
|
||||||
if (a->tv_sec < b->tv_sec) {
|
if (a->tv_sec < b->tv_sec) {
|
||||||
@@ -76,7 +80,7 @@ UTI_CompareTimevals(struct timeval *a, struct timeval *b)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_NormaliseTimeval(struct timeval *x)
|
UTI_NormaliseTimeval(struct timeval *x)
|
||||||
{
|
{
|
||||||
/* Reduce tv_usec to within +-1000000 of zero. JGH */
|
/* Reduce tv_usec to within +-1000000 of zero. JGH */
|
||||||
@@ -95,7 +99,7 @@ UTI_NormaliseTimeval(struct timeval *x)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_DiffTimevals(struct timeval *result,
|
UTI_DiffTimevals(struct timeval *result,
|
||||||
struct timeval *a,
|
struct timeval *a,
|
||||||
struct timeval *b)
|
struct timeval *b)
|
||||||
@@ -112,7 +116,7 @@ UTI_DiffTimevals(struct timeval *result,
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
/* Calculate result = a - b and return as a double */
|
/* Calculate result = a - b and return as a double */
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_DiffTimevalsToDouble(double *result,
|
UTI_DiffTimevalsToDouble(double *result,
|
||||||
struct timeval *a,
|
struct timeval *a,
|
||||||
struct timeval *b)
|
struct timeval *b)
|
||||||
@@ -123,7 +127,7 @@ UTI_DiffTimevalsToDouble(double *result,
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_AddDoubleToTimeval(struct timeval *start,
|
UTI_AddDoubleToTimeval(struct timeval *start,
|
||||||
double increment,
|
double increment,
|
||||||
struct timeval *end)
|
struct timeval *end)
|
||||||
@@ -147,7 +151,7 @@ UTI_AddDoubleToTimeval(struct timeval *start,
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
/* Calculate the average and difference (as a double) of two timevals */
|
/* Calculate the average and difference (as a double) of two timevals */
|
||||||
INLINE_STATIC void
|
void
|
||||||
UTI_AverageDiffTimevals (struct timeval *earlier,
|
UTI_AverageDiffTimevals (struct timeval *earlier,
|
||||||
struct timeval *later,
|
struct timeval *later,
|
||||||
struct timeval *average,
|
struct timeval *average,
|
||||||
@@ -485,6 +489,55 @@ UTI_IPAndPortToSockaddr(IPAddr *ip, unsigned short port, struct sockaddr *sa)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
char *UTI_SockaddrToString(struct sockaddr *sa)
|
||||||
|
{
|
||||||
|
unsigned short port;
|
||||||
|
IPAddr ip;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
result = NEXT_BUFFER;
|
||||||
|
|
||||||
|
switch (sa->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
#ifdef AF_INET6
|
||||||
|
case AF_INET6:
|
||||||
|
#endif
|
||||||
|
UTI_SockaddrToIPAndPort(sa, &ip, &port);
|
||||||
|
snprintf(result, BUFFER_LENGTH, "%s:%hu", UTI_IPToString(&ip), port);
|
||||||
|
break;
|
||||||
|
case AF_UNIX:
|
||||||
|
snprintf(result, BUFFER_LENGTH, "%s", ((struct sockaddr_un *)sa)->sun_path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(result, BUFFER_LENGTH, "[UNKNOWN]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
UTI_SockaddrFamilyToString(int family)
|
||||||
|
{
|
||||||
|
switch (family) {
|
||||||
|
case AF_INET:
|
||||||
|
return "IPv4";
|
||||||
|
#ifdef AF_INET6
|
||||||
|
case AF_INET6:
|
||||||
|
return "IPv6";
|
||||||
|
#endif
|
||||||
|
case AF_UNIX:
|
||||||
|
return "Unix";
|
||||||
|
case AF_UNSPEC:
|
||||||
|
return "UNSPEC";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
UTI_TimeToLogForm(time_t t)
|
UTI_TimeToLogForm(time_t t)
|
||||||
{
|
{
|
||||||
@@ -606,6 +659,59 @@ UTI_Int64ToTimeval(NTP_int64 *src,
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
/* Maximum offset between two sane times */
|
||||||
|
#define MAX_OFFSET 4294967296.0
|
||||||
|
|
||||||
|
/* Minimum allowed distance from maximum 32-bit time_t */
|
||||||
|
#define MIN_ENDOFTIME_DISTANCE (365 * 24 * 3600)
|
||||||
|
|
||||||
|
int
|
||||||
|
UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
|
||||||
|
{
|
||||||
|
double t;
|
||||||
|
|
||||||
|
/* Handle nan correctly here */
|
||||||
|
if (!(offset > -MAX_OFFSET && offset < MAX_OFFSET))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UTI_TimevalToDouble(tv, &t);
|
||||||
|
t += offset;
|
||||||
|
|
||||||
|
/* Time before 1970 is not considered valid */
|
||||||
|
if (t < 0.0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_LONG_TIME_T
|
||||||
|
/* Check if it's in the interval to which NTP time is mapped */
|
||||||
|
if (t < (double)NTP_ERA_SPLIT || t > (double)(NTP_ERA_SPLIT + (1LL << 32)))
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
/* Don't get too close to 32-bit time_t overflow */
|
||||||
|
if (t > (double)(0x7fffffff - MIN_ENDOFTIME_DISTANCE))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
double
|
||||||
|
UTI_Log2ToDouble(int l)
|
||||||
|
{
|
||||||
|
if (l >= 0) {
|
||||||
|
if (l > 31)
|
||||||
|
l = 31;
|
||||||
|
return (uint32_t)1 << l;
|
||||||
|
} else {
|
||||||
|
if (l < -31)
|
||||||
|
l = -31;
|
||||||
|
return 1.0 / ((uint32_t)1 << -l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
|
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
|
||||||
{
|
{
|
||||||
@@ -670,7 +776,11 @@ UTI_FloatHostToNetwork(double x)
|
|||||||
if (x < 0.0) {
|
if (x < 0.0) {
|
||||||
x = -x;
|
x = -x;
|
||||||
neg = 1;
|
neg = 1;
|
||||||
|
} else if (x >= 0.0) {
|
||||||
|
neg = 0;
|
||||||
} else {
|
} else {
|
||||||
|
/* Save NaN as zero */
|
||||||
|
x = 0.0;
|
||||||
neg = 0;
|
neg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,3 +890,183 @@ UTI_DecodePasswordFromText(char *key)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
UTI_SetQuitSignalsHandler(void (*handler)(int))
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
sa.sa_handler = handler;
|
||||||
|
sa.sa_flags = SA_RESTART;
|
||||||
|
if (sigemptyset(&sa.sa_mask) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef SIGINT
|
||||||
|
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM
|
||||||
|
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
#ifdef SIGQUIT
|
||||||
|
if (sigaction(SIGQUIT, &sa, NULL) < 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
#ifdef SIGHUP
|
||||||
|
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
char *
|
||||||
|
UTI_PathToDir(const char *path)
|
||||||
|
{
|
||||||
|
char *dir, *slash;
|
||||||
|
|
||||||
|
slash = strrchr(path, '/');
|
||||||
|
|
||||||
|
if (!slash)
|
||||||
|
return Strdup(".");
|
||||||
|
|
||||||
|
if (slash == path)
|
||||||
|
return Strdup("/");
|
||||||
|
|
||||||
|
dir = Malloc(slash - path + 1);
|
||||||
|
snprintf(dir, slash - path + 1, "%s", path);
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_dir(char *p, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
/* See if directory exists */
|
||||||
|
status = stat(p, &buf);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Could not access %s : %s", p, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (S_ISDIR(buf.st_mode))
|
||||||
|
return 1;
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "%s is not directory", p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the directory */
|
||||||
|
if (mkdir(p, mode) < 0) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Could not create directory %s : %s", p, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set its owner */
|
||||||
|
if (chown(p, uid, gid) < 0) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Could not change ownership of %s : %s", p, strerror(errno));
|
||||||
|
/* Don't leave it there with incorrect ownership */
|
||||||
|
rmdir(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
/* Return 0 if the directory couldn't be created, 1 if it could (or
|
||||||
|
already existed) */
|
||||||
|
int
|
||||||
|
UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int i, j, k, last;
|
||||||
|
|
||||||
|
/* Don't try to create current directory */
|
||||||
|
if (!strcmp(path, "."))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
p = (char *)Malloc(1 + strlen(path));
|
||||||
|
|
||||||
|
i = k = 0;
|
||||||
|
while (1) {
|
||||||
|
p[i++] = path[k++];
|
||||||
|
|
||||||
|
if (path[k] == '/' || !path[k]) {
|
||||||
|
/* Check whether its end of string, a trailing / or group of / */
|
||||||
|
last = 1;
|
||||||
|
j = k;
|
||||||
|
while (path[j]) {
|
||||||
|
if (path[j] != '/') {
|
||||||
|
/* Pick up a / into p[] thru the assignment at the top of the loop */
|
||||||
|
k = j - 1;
|
||||||
|
last = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[i] = 0;
|
||||||
|
|
||||||
|
if (!create_dir(p, last ? mode : 0755, last ? uid : 0, last ? gid : 0)) {
|
||||||
|
Free(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path[k])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Free(p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
if (stat(path, &buf)) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Could not access %s : %s", path, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISDIR(buf.st_mode)) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "%s is not directory", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((buf.st_mode & 0777) & ~perm) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Wrong permissions on %s", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.st_uid != uid) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Wrong owner of %s (%s != %d)", path, "UID", uid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.st_gid != gid) {
|
||||||
|
LOG(LOGS_ERR, LOGF_Util, "Wrong owner of %s (%s != %d)", path, "GID", gid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
28
util.h
28
util.h
@@ -88,6 +88,8 @@ extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
|
|||||||
|
|
||||||
extern void UTI_SockaddrToIPAndPort(struct sockaddr *sa, IPAddr *ip, unsigned short *port);
|
extern void UTI_SockaddrToIPAndPort(struct sockaddr *sa, IPAddr *ip, unsigned short *port);
|
||||||
extern int UTI_IPAndPortToSockaddr(IPAddr *ip, unsigned short port, struct sockaddr *sa);
|
extern int UTI_IPAndPortToSockaddr(IPAddr *ip, unsigned short port, struct sockaddr *sa);
|
||||||
|
extern char *UTI_SockaddrToString(struct sockaddr *sa);
|
||||||
|
extern const char *UTI_SockaddrFamilyToString(int family);
|
||||||
|
|
||||||
extern char *UTI_TimeToLogForm(time_t t);
|
extern char *UTI_TimeToLogForm(time_t t);
|
||||||
|
|
||||||
@@ -104,6 +106,12 @@ extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fu
|
|||||||
|
|
||||||
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
|
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
|
||||||
|
|
||||||
|
/* Check if time + offset is sane */
|
||||||
|
extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset);
|
||||||
|
|
||||||
|
/* Get 2 raised to power of a signed integer */
|
||||||
|
extern double UTI_Log2ToDouble(int l);
|
||||||
|
|
||||||
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
|
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
|
||||||
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
||||||
|
|
||||||
@@ -121,11 +129,19 @@ extern int UTI_CheckNTPAuth(int hash_id, const unsigned char *key, int key_len,
|
|||||||
/* Decode password encoded in ASCII or HEX */
|
/* Decode password encoded in ASCII or HEX */
|
||||||
extern int UTI_DecodePasswordFromText(char *key);
|
extern int UTI_DecodePasswordFromText(char *key);
|
||||||
|
|
||||||
#if defined (INLINE_UTILITIES)
|
extern int UTI_SetQuitSignalsHandler(void (*handler)(int));
|
||||||
#define INLINE_STATIC inline static
|
|
||||||
#include "util.c"
|
/* Get directory (as an allocated string) for a path */
|
||||||
#else
|
extern char *UTI_PathToDir(const char *path);
|
||||||
#define INLINE_STATIC
|
|
||||||
#endif /* defined (INLINE_UTILITIES) */
|
/* Create a directory with a specified mode (umasked) and set its uid/gid.
|
||||||
|
Create also any parent directories that don't exist with mode 755 and
|
||||||
|
default uid/gid. Returns 1 if created or already exists (even with
|
||||||
|
different mode/uid/gid), 0 otherwise. */
|
||||||
|
extern int UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
|
/* Check if a directory is secure. It must not have other than the specified
|
||||||
|
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);
|
||||||
|
|
||||||
#endif /* GOT_UTIL_H */
|
#endif /* GOT_UTIL_H */
|
||||||
|
|||||||
182
wrap_adjtimex.c
182
wrap_adjtimex.c
@@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
|
||||||
|
|
||||||
**********************************************************************
|
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
|
||||||
* Copyright (C) Miroslav Lichvar 2011-2012, 2014
|
|
||||||
*
|
|
||||||
* 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 is a wrapper around the Linux adjtimex system call.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "wrap_adjtimex.h"
|
|
||||||
|
|
||||||
#include <sys/timex.h>
|
|
||||||
|
|
||||||
/* Definitions used if missing in the system headers */
|
|
||||||
#ifndef ADJ_TAI
|
|
||||||
#define ADJ_TAI 0x0080 /* set TAI offset */
|
|
||||||
#endif
|
|
||||||
#ifndef ADJ_SETOFFSET
|
|
||||||
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
|
|
||||||
#endif
|
|
||||||
#ifndef ADJ_NANO
|
|
||||||
#define ADJ_NANO 0x2000 /* select nanosecond resolution */
|
|
||||||
#endif
|
|
||||||
#ifndef ADJ_OFFSET_SS_READ
|
|
||||||
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Frequency offset scale (shift) */
|
|
||||||
#define SHIFT_USEC 16
|
|
||||||
|
|
||||||
static int status = 0;
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_ResetOffset(void)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
/* Reset adjtime() offset */
|
|
||||||
txc.modes = ADJ_OFFSET_SINGLESHOT;
|
|
||||||
txc.offset = 0;
|
|
||||||
if (adjtimex(&txc) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Reset PLL offset */
|
|
||||||
txc.modes = ADJ_OFFSET | ADJ_STATUS;
|
|
||||||
txc.status = STA_PLL;
|
|
||||||
txc.offset = 0;
|
|
||||||
if (adjtimex(&txc) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Set status back */
|
|
||||||
txc.modes = ADJ_STATUS;
|
|
||||||
txc.modes = status;
|
|
||||||
if (adjtimex(&txc) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_SetFrequency(double *freq, long tick)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
txc.modes = ADJ_TICK | ADJ_FREQUENCY;
|
|
||||||
|
|
||||||
txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
|
|
||||||
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
|
||||||
txc.tick = tick;
|
|
||||||
|
|
||||||
return adjtimex(&txc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_GetFrequency(double *freq, long *tick)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
int result;
|
|
||||||
txc.modes = 0; /* pure read */
|
|
||||||
result = adjtimex(&txc);
|
|
||||||
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
|
||||||
*tick = txc.tick;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_SetLeap(int leap)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
status &= ~(STA_INS | STA_DEL);
|
|
||||||
|
|
||||||
if (leap > 0) {
|
|
||||||
status |= STA_INS;
|
|
||||||
} else if (leap < 0) {
|
|
||||||
status |= STA_DEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
txc.modes = ADJ_STATUS;
|
|
||||||
txc.status = status;
|
|
||||||
|
|
||||||
return adjtimex(&txc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int TMX_SetSync(int sync, double est_error, double max_error)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
if (sync) {
|
|
||||||
status &= ~STA_UNSYNC;
|
|
||||||
} else {
|
|
||||||
status |= STA_UNSYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
txc.modes = ADJ_STATUS | ADJ_ESTERROR | ADJ_MAXERROR;
|
|
||||||
txc.status = status;
|
|
||||||
txc.esterror = est_error * 1.0e6;
|
|
||||||
txc.maxerror = max_error * 1.0e6;
|
|
||||||
|
|
||||||
return adjtimex(&txc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_TestStepOffset(void)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
/* Zero maxerror and check it's reset to a maximum after ADJ_SETOFFSET.
|
|
||||||
This seems to be the only way how to verify that the kernel really
|
|
||||||
supports the ADJ_SETOFFSET mode as it doesn't return an error on unknown
|
|
||||||
mode. */
|
|
||||||
|
|
||||||
txc.modes = ADJ_MAXERROR;
|
|
||||||
txc.maxerror = 0;
|
|
||||||
if (adjtimex(&txc) < 0 || txc.maxerror != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
txc.modes = ADJ_SETOFFSET | ADJ_NANO;
|
|
||||||
txc.time.tv_sec = 0;
|
|
||||||
txc.time.tv_usec = 0;
|
|
||||||
if (adjtimex(&txc) < 0 || txc.maxerror < 100000)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
TMX_ApplyStepOffset(double offset)
|
|
||||||
{
|
|
||||||
struct timex txc;
|
|
||||||
|
|
||||||
txc.modes = ADJ_SETOFFSET | ADJ_NANO;
|
|
||||||
if (offset >= 0) {
|
|
||||||
txc.time.tv_sec = offset;
|
|
||||||
} else {
|
|
||||||
txc.time.tv_sec = offset - 1;
|
|
||||||
}
|
|
||||||
txc.time.tv_usec = 1.0e9 * (offset - txc.time.tv_sec);
|
|
||||||
|
|
||||||
return adjtimex(&txc);
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
|
||||||
|
|
||||||
**********************************************************************
|
|
||||||
* Copyright (C) Richard P. Curnow 1997-2002
|
|
||||||
*
|
|
||||||
* 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 the adjtimex wrapper
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GOT_WRAP_ADJTIMEX_H
|
|
||||||
#define GOT_WRAP_ADJTIMEX_H
|
|
||||||
|
|
||||||
int TMX_ResetOffset(void);
|
|
||||||
int TMX_SetFrequency(double *freq, long tick);
|
|
||||||
int TMX_GetFrequency(double *freq, long *tick);
|
|
||||||
int TMX_SetLeap(int leap);
|
|
||||||
int TMX_SetSync(int sync, double est_error, double max_error);
|
|
||||||
int TMX_TestStepOffset(void);
|
|
||||||
int TMX_ApplyStepOffset(double offset);
|
|
||||||
|
|
||||||
#endif /* GOT_WRAP_ADJTIMEX_H */
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user