Compare commits

...

108 Commits

Author SHA1 Message Date
Miroslav Lichvar
0da5cf9163 Update NEWS 2013-07-17 16:19:45 +02:00
Miroslav Lichvar
f6a39d75a7 Treat address bind errors as non-fatal 2013-07-17 13:45:36 +02:00
Miroslav Lichvar
25aa9f5b42 Update chrony.spec.sample 2013-07-01 19:00:06 +02:00
Miroslav Lichvar
829b3adac3 Update copyright in chronyc GPL string 2013-07-01 17:53:27 +02:00
Miroslav Lichvar
4847a3a259 Update NEWS 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
551541d9c8 Update example config files more 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
f996f4c9fb Document port directive set to 0 as random port 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
ac78ad60f3 Use texi2html only if it's available 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
42d7cf8922 Don't ship faqgen.pl 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
e811ba7b4c Fix possible leaks of temporary file names 2013-06-21 16:09:20 +02:00
Miroslav Lichvar
cb464cac4d Fix memset calls 2013-06-21 14:39:33 +02:00
Miroslav Lichvar
fa409ddc8f Update documentation 2013-06-20 18:00:32 +02:00
Miroslav Lichvar
821226e473 Update example config files 2013-06-20 17:23:32 +02:00
Miroslav Lichvar
0e298bedf6 Create /etc and /var/lib/chrony on installation 2013-06-20 14:47:06 +02:00
Miroslav Lichvar
aa76760268 Avoid sentences written in first person 2013-06-20 13:24:24 +02:00
Miroslav Lichvar
8bf87bbfde Update comparison with ntpd 2013-06-20 13:24:24 +02:00
Miroslav Lichvar
38e889c85c Remove fixed problems from FAQ 2013-06-19 14:40:20 +02:00
Miroslav Lichvar
d5b737cce8 Update copyright years 2013-06-19 12:50:26 +02:00
Miroslav Lichvar
6ba764b5be Don't call finalise functions on fatal error
Also, return with non-zero exit code.
2013-06-19 12:28:00 +02:00
Miroslav Lichvar
707b857b68 Combine source frequencies by skew 2013-06-19 12:11:27 +02:00
Miroslav Lichvar
f8d609fee5 Add minimum skew limit to sourcestats 2013-06-19 10:22:49 +02:00
Miroslav Lichvar
01f797ac05 Fix printing of outlier status 2013-06-18 16:13:17 +02:00
Miroslav Lichvar
6fa11a853a Add more entries to tracking log
Add number of combined sources, remaining offset correction from
previous update and estimated stddev of the combined offset.
2013-06-17 18:32:16 +02:00
Miroslav Lichvar
9c78ad708b Fix maxchange offset check 2013-06-17 18:32:16 +02:00
Miroslav Lichvar
57f8160d6c Call maybe_log_offset and update_leap_status after adjusting clock 2013-06-17 18:32:16 +02:00
Miroslav Lichvar
8d80ce444f Fix spelling 2013-06-17 18:26:48 +02:00
Miroslav Lichvar
95c3acf67e Log manual entries with MANU refid in tracking log 2013-06-17 18:26:48 +02:00
Miroslav Lichvar
561f7a66dd Fix log message to not include newline 2013-06-17 18:26:48 +02:00
Miroslav Lichvar
0193688671 Fix printing of negative offset with settime command 2013-06-17 18:26:48 +02:00
Miroslav Lichvar
6d7605a3d0 Reuse REF_SetReference code with manual reference 2013-06-17 18:26:47 +02:00
Miroslav Lichvar
e0171f6e96 Write freq and skew to drift file with six decimal places 2013-06-14 19:24:03 +02:00
Miroslav Lichvar
4ef1c6f2c8 Use fscanf to read drift file 2013-06-14 19:24:03 +02:00
Miroslav Lichvar
f7e2d7c2ec Modify minimum skew checking 2013-06-14 16:27:15 +02:00
Miroslav Lichvar
3d1be1cd75 Replace bzero with memset 2013-06-14 13:48:16 +02:00
Miroslav Lichvar
2d509eb8bd Remove changelog from conf.c 2013-06-14 13:44:15 +02:00
Miroslav Lichvar
6ca73bf670 Cleanup including of system headers 2013-06-14 13:41:16 +02:00
Miroslav Lichvar
f7802f0111 Don't abort on EINTR select errors 2013-06-14 12:37:24 +02:00
Miroslav Lichvar
2f3ef235a1 Replace LOG_FATAL call with assert in SCH_MailLoop 2013-06-14 12:35:51 +02:00
Miroslav Lichvar
1ad22e9a02 Don't apply outlyer penalty at beginning
Wait until the reach register is full to allow marking a source as
outlyer for 32 updates. This makes start nicer with iburst.
2013-06-13 18:20:53 +02:00
Miroslav Lichvar
6d2fb9f782 Add minsamples and maxsamples directives
Allow configuration of the maximum and minimum number of samples per
source.
2013-06-13 16:23:32 +02:00
Miroslav Lichvar
22e5ed44c2 Modify SST_GetSelectionData to return only necessary data 2013-06-12 16:06:33 +02:00
Miroslav Lichvar
9666831818 Use UTI_DiffTimevalsToDouble to calculate theta 2013-06-12 15:30:28 +02:00
Miroslav Lichvar
ff8e04f9ba Fix fabs use on delay 2013-06-12 15:30:28 +02:00
Miroslav Lichvar
52272f4dc5 Limit sources included in combining
Combine only sources whose distance is shorter than distance of the
selected source multiplied by the value of combinelimit and their
estimated frequencies are close to the frequency of the selected source.
Add outlyer status for sources which are selectable, but not included in
the combining. The status is displayed as '-' in the chronyc sources
output.
2013-06-12 10:25:46 +02:00
Miroslav Lichvar
18a66a2ba8 Resurrect source combining
This is based on the code that was removed in CVS revision 1.3 of
sources.c. The weighting is simplified and the code is moved to a new
function.
2013-06-11 16:36:50 +02:00
Miroslav Lichvar
8aa9eb19c8 Remove unnecessary adjtimex calls 2013-06-06 19:38:36 +02:00
Miroslav Lichvar
62027f1b47 Fix rounding in UTI_AddDoubleToTimeval with negative increments 2013-06-06 16:30:37 +02:00
Miroslav Lichvar
41805d572f Adjust last_select_ts on slew 2013-06-06 16:29:50 +02:00
Miroslav Lichvar
58f768928a Rename SCH_GetFileReadyTime() and extend it to return raw time 2013-06-05 18:07:05 +02:00
Miroslav Lichvar
0074135097 Drop duplicated int64_to_timeval() 2013-06-05 13:11:53 +02:00
Miroslav Lichvar
8eb7ce8581 Fix UTI_DoubleToInt32 to check for overflow 2013-06-05 13:05:54 +02:00
Miroslav Lichvar
2ceb3c89ca Move NTP_int32 conversion functions to util.c 2013-06-05 12:49:47 +02:00
Miroslav Lichvar
d46e2a69a1 Add --enable-trace to configure 2013-06-05 12:22:07 +02:00
Miroslav Lichvar
20f9454be3 Fix configure help message 2013-06-05 11:58:13 +02:00
Miroslav Lichvar
8092366897 Abort on parse errors in refclock directive 2013-06-05 11:48:48 +02:00
Miroslav Lichvar
066254b6c8 Fix burst command with specified address
This was broken in commit 0f8def4ca4.
2013-06-05 10:39:58 +02:00
Miroslav Lichvar
79811bf3e2 Allow hostnames in offline, online and burst commands 2013-06-05 10:39:58 +02:00
Miroslav Lichvar
32bf32e7d5 Don't use uninitialized value in receive_packet() 2013-06-05 09:56:37 +02:00
Miroslav Lichvar
df968ca47c Fix stratum setting when source with non-minimum stratum is selected 2013-06-05 09:55:00 +02:00
Miroslav Lichvar
cce7a5f15e Improve peer polling in symmetric mode
If the remote stratum is higher than ours, try to lock on the peer's
polling to minimize our response time by slightly extending our delay or
waiting for the peer to catch up with us as the random part in the
actual interval is reduced. If the remote stratum is equal to ours, try
to interleave evenly with the peer.
2013-06-05 09:32:20 +02:00
Miroslav Lichvar
288043c13b Save remote poll only with valid packets 2013-06-04 15:43:59 +02:00
Miroslav Lichvar
78ae4ebfaa Fix peer polling with shorter remote poll
If the remote peer uses a polling interval shorter than the local
minimum, the local peer will be unable to send any packets as the
timeout will be updated on every received valid packet and will never
expire.

Modify the delay calculation to aim at poll interval away since the last
transmit.

Also, share the delay calculation code with transmit_timeout().
2013-06-04 12:52:49 +02:00
Miroslav Lichvar
cf700a0084 Requeue transmit timeout only with valid packets 2013-06-04 12:45:47 +02:00
Miroslav Lichvar
60a25f6e71 Ignore packets from offline sources
Rework the logic in transmit_timeout() to change the online status on
the following timeout to allow ignoring packets from offline sources.
2013-06-03 18:57:55 +02:00
Miroslav Lichvar
3eff836b2e Set stratum from last sample instead of best 2013-06-03 18:57:54 +02:00
Miroslav Lichvar
2b9fe764d5 Drop unused SST_GetReferenceData() 2013-06-03 16:03:07 +02:00
Miroslav Lichvar
030e3b2dab Make receive_packet() more readable 2013-06-03 16:03:07 +02:00
Miroslav Lichvar
5079f6bbff In burst count only accumulated samples as good 2013-06-03 16:03:07 +02:00
Miroslav Lichvar
afceb9d24e Slew only non-zero local timestamps in ntp core 2013-06-03 16:03:07 +02:00
Miroslav Lichvar
a2656a20bc Fix poll timeout with symmetric peer and poll 0 2013-06-03 16:03:05 +02:00
Miroslav Lichvar
359d444343 Remove unncessary return statements 2013-05-21 15:08:34 +02:00
Miroslav Lichvar
d510154ba2 Add recommendation on password security to keyfile description 2013-05-21 14:02:45 +02:00
Miroslav Lichvar
1c901b82dc Add option to generate command key on start
With generatecommandkey directive, if no command key is found in the key
file on start, one will be generated automatically from /dev/urandom.
2013-05-21 14:02:31 +02:00
Miroslav Lichvar
ea3672df4e Fix some error messages 2013-05-20 18:21:30 +02:00
Miroslav Lichvar
72d0b3c913 Create sockets only in selected family with -4 or -6 option 2013-05-20 15:37:25 +02:00
Miroslav Lichvar
51a2d8dfd8 Set paths in documentation by configure 2013-05-16 14:20:16 +02:00
Miroslav Lichvar
bc25380950 Document default value of commandkey 2013-05-16 14:19:03 +02:00
Miroslav Lichvar
ae1e3bf73c Add option to authenticate automatically on chronyc start 2013-05-16 14:18:57 +02:00
Miroslav Lichvar
9673a2726c Refactor key parsing 2013-05-16 14:18:33 +02:00
Miroslav Lichvar
02524397c1 Try linking readline without ncurses first 2013-05-15 11:50:58 +02:00
Joachim Wiedorn
5e5dde1a67 Various spelling fixes
Reviewed-By: Rogério Theodoro de Brito <rbrito@ime.usp.br>
2013-05-15 11:43:25 +02:00
Miroslav Lichvar
0f8def4ca4 Refactor command parsing
- normalize command line before parsing
- compare whole words
- check for missing/extra arguments in config parsing
- use strdup for string allocation
- share code for reporting syntax errors
- avoid using function pointers
- cleanup the code a bit
2013-05-15 11:27:38 +02:00
Miroslav Lichvar
182ec04e24 Abort on errors when parsing config 2013-05-15 11:14:27 +02:00
Miroslav Lichvar
ebae435398 Log online/offline status change for burst sources too. 2013-05-15 11:03:18 +02:00
Miroslav Lichvar
52657945d8 Don't send uninitialized fields in dump and local requests 2013-05-15 11:02:53 +02:00
Miroslav Lichvar
12166f8a47 Accept float value as initstepslew threshold 2013-05-14 17:16:41 +02:00
Miroslav Lichvar
c5f1dd8615 Update .gitignore 2013-05-14 17:16:41 +02:00
Miroslav Lichvar
10e67e3c1d Terminate batch processing in chronyc on quit command 2013-05-07 17:01:16 +02:00
Miroslav Lichvar
4e8ceaae86 Define DEFAULT_CONF_FILE in config.h 2013-05-07 16:35:40 +02:00
Miroslav Lichvar
73d4eaafbb Reply to NTPv1 and NTPv2 packets with same version 2013-05-02 11:10:48 +02:00
Miroslav Lichvar
cf00179964 Reply to NTPv1 packets 2013-05-02 11:10:25 +02:00
Miroslav Lichvar
edda0c60b3 Add user directive for dropping root privileges
This is equivalent to the -u option.
2013-04-26 17:38:40 +02:00
Miroslav Lichvar
f2eb6b165a Add option to ignore initstepslew and makestep directives
When chronyd is started with -R, the initstepslew directive and the
makestep directive with a positive limit will be ignored. This is useful
when restarting chronyd to avoid unnecessary clock adjustments. It can
be used with -r.
2013-04-26 17:38:37 +02:00
victor lum
4933c216b2 Fix crash with duplicated initstepslew address
When there are duplicate ntp servers listed on the initstepslew line, 2
SourceRecords are created (sourceA and sourceB), and two timers are
created (timerA and timerB).  When ntp responses are received, only
sourceA is updated because of the way read_from_socket searches for a
matching record.  Eventually, the criteria for sourceA are met, causing
timerA to stop and n_completed_sources to increment.  timerB continues
to trigger, sending ntp poll messages to the ntp server.  Responses from
that server are assigned to sourceA, triggering the criteria for sourceA
and causing n_completed_sources to increment improperly.  Once this
happens enough times, n_complete_sources == number of servers and all
SourceRecords are deleted.  The next time timerB triggers, it attempts
to access sourceB, which was already been deleted, causing the core.
2013-04-26 14:36:17 +02:00
Miroslav Lichvar
0655def57f Fix crash in config parsing with too many servers 2013-04-26 14:17:21 +02:00
Miroslav Lichvar
6eafff2450 Update URL of NTP server list in example config 2013-03-08 14:39:20 +01:00
Miroslav Lichvar
0bb772c575 Fix delta calculation with extreme frequency offsets
This should prevent chronyd from getting stuck and refusing new samples
due to failing test4 when the current measured frequency offset is close
to 1.0. That can happen when the system clock is stepped forward behind
chronyd's back.
2013-03-08 14:39:13 +01:00
Miroslav Lichvar
b261693095 Use texi2html to generate html 2013-02-01 18:40:50 +01:00
Miroslav Lichvar
129db63e30 Update NEWS 2013-02-01 15:47:43 +01:00
Miroslav Lichvar
1759d89d8a Print error message when MD5 init fails in chronyc 2013-01-24 19:04:49 +01:00
Miroslav Lichvar
0540b17fb9 Replace printf calls with echo in configure 2013-01-24 19:04:49 +01:00
Miroslav Lichvar
8893dda350 Save compiler messages to config.log in configure 2013-01-24 18:57:39 +01:00
Miroslav Lichvar
b14689d59b Fix crash and hangs in RGR_FindBestRobustRegression 2012-11-29 16:23:22 +01:00
Miroslav Lichvar
1ca844af98 Check for errors when writing new drift files 2012-09-10 17:31:56 +02:00
Miroslav Lichvar
3059747c35 Add format string to printf in client.c 2012-09-10 17:31:56 +02:00
Miroslav Lichvar
bbbb3633a7 Add support for nanoseconds in SHM 2012-09-10 17:31:56 +02:00
Miroslav Lichvar
df6c2a432f Fuzz transmit timestamp
Add random bits below clock precision to the timestamp to make
it less predictable.
2012-05-23 12:06:16 +02:00
Miroslav Lichvar
d0acfc2652 Log uncooked offset in refclocks log for PPS samples 2012-03-13 13:17:03 +01:00
67 changed files with 2402 additions and 1946 deletions

14
.gitignore vendored
View File

@@ -1,7 +1,19 @@
.deps .deps
*.swp .vimrc
*.o *.o
*.swp
RELEASES
Makefile Makefile
chrony.conf.5
chrony.info
chrony.html
chrony.texi
chrony.txt
chronyc chronyc
chronyc.1
chronyd chronyd
chronyd.8
config.h
config.log
tags
version.h version.h

12
INSTALL
View File

@@ -81,12 +81,14 @@ Now that the software is successfully installed, the next step is to
set up a configuration file. The contents of this depend on the set up a configuration file. The contents of this depend on the
network environment in which the computer operates. Typical scenarios network environment in which the computer operates. Typical scenarios
are described in the manual. The simplest case is for a computer with are described in the manual. The simplest case is for a computer with
a permanent Internet connection - suppose you want to use the NTP a permanent Internet connection - suppose you want to use public NTP
server ntp1.foobar.com as your time reference. You would create an servers from the pool.ntp.org project as your time reference. You would
/etc/chrony.conf file containing create an /etc/chrony.conf file containing
server ntp1.foobar.com server 0.pool.ntp.org
driftfile /etc/chrony.drift server 1.pool.ntp.org
server 2.pool.ntp.org
driftfile /var/lib/chrony/drift
and then run /usr/local/sbin/chronyd. and then run /usr/local/sbin/chronyd.

View File

@@ -27,6 +27,8 @@ SBINDIR=@SBINDIR@
MANDIR=@MANDIR@ MANDIR=@MANDIR@
INFODIR=@INFODIR@ INFODIR=@INFODIR@
DOCDIR=@DOCDIR@ DOCDIR=@DOCDIR@
LOCALSTATEDIR=@LOCALSTATEDIR@
CHRONYVARDIR=@CHRONYVARDIR@
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
@@ -77,9 +79,10 @@ $(HASH_OBJ) : $(patsubst %.o,%.c,$(HASH_OBJ))
distclean : clean distclean : clean
-rm -f Makefile -rm -f Makefile
-rm -f chrony.conf.5 chrony.texi chronyc.1 chronyd.8
clean : clean :
-rm -f *.o *.s chronyc chronyd core *~ -rm -f *.o *.s chronyc chronyd core *~ chrony.info chrony.html chrony.txt
-rm -rf .deps -rm -rf .deps
getdate.c : ; getdate.c : ;
@@ -90,6 +93,7 @@ getdate :
# seem to vary between systems. # seem to vary between systems.
install: chronyd chronyc install: chronyd chronyc
[ -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)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
@@ -97,6 +101,7 @@ install: chronyd chronyc
[ -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)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
[ -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
cp chronyd $(DESTDIR)$(SBINDIR)/chronyd cp chronyd $(DESTDIR)$(SBINDIR)/chronyd
@@ -124,9 +129,6 @@ install: chronyd chronyc
%.s : %.c %.s : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -S $< $(CC) $(CFLAGS) $(CPPFLAGS) -S $<
# makeinfo v4 required to generate plain text and html
MAKEINFO:=makeinfo
install-docs : docs install-docs : docs
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR) [ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
@@ -140,13 +142,14 @@ install-docs : docs
docs : chrony.txt chrony.html chrony.info docs : chrony.txt chrony.html chrony.info
chrony.txt : chrony.texi chrony.txt : chrony.texi
$(MAKEINFO) --no-headers --number-sections -o chrony.txt chrony.texi makeinfo --no-headers --number-sections -o chrony.txt chrony.texi
chrony.html : chrony.texi chrony.html : chrony.texi
$(MAKEINFO) --no-split --html --number-sections -o chrony.html chrony.texi command -v texi2html > /dev/null 2>&1 && texi2html chrony.texi || \
makeinfo --no-split --html --number-sections -o chrony.html chrony.texi
chrony.info : chrony.texi chrony.info : chrony.texi
$(MAKEINFO) chrony.texi makeinfo chrony.texi
# This is only relevant if you're maintaining the website! # This is only relevant if you're maintaining the website!
faq.php : faq.txt faqgen.pl faq.php : faq.txt faqgen.pl

26
NEWS
View File

@@ -1,16 +1,42 @@
New in version 1.28
===================
* Combine sources to improve accuracy
* Make config and command parser strict
* Add -a option to chronyc to authenticate automatically
* Add -R option to ignore initstepslew and makestep directives
* Add generatecommandkey, minsamples, maxsamples and user directives
* Improve compatibility with NTPv1 and NTPv2 clients
* Create sockets only in selected family with -4/-6 option
* Treat address bind errors as non-fatal
* Extend tracking log
* Accept float values as initstepslew threshold
* Allow hostnames in offline, online and burst commands
* Fix and improve peer polling
* Fix crash in config parsing with too many servers
* Fix crash with duplicated initstepslew address
* Fix delta calculation with extreme frequency offsets
* Set local stratum correctly
* Remove unnecessary adjtimex calls
* Set paths in documentation by configure
* Update chrony.spec
New in version 1.27 New in version 1.27
=================== ===================
* Support for stronger keys via NSS or libtomcrypt library * Support for stronger keys via NSS or libtomcrypt library
* Support reading leap second data from tz database * Support reading leap second data from tz database
* Support for precise clock stepping on Linux * Support for precise clock stepping on Linux
* Support for nanoseconds in SHM refclock
* Make offset corrections smoother on Linux * Make offset corrections smoother on Linux
* Make transmit timestamps random below clock precision
* Add corrtimeratio and maxchange directives * Add corrtimeratio and maxchange directives
* Extend tracking, sources and activity reports * Extend tracking, sources and activity reports
* Wait in foreground process until daemon is fully initialized * Wait in foreground process until daemon is fully initialized
* Fix crash with slow name resolving * Fix crash with slow name resolving
* Fix iburst with jittery sources * Fix iburst with jittery sources
* Fix offset stored in rtc data right after trimrtc * Fix offset stored in rtc data right after trimrtc
* Fix crash and hang with RTC or manual samples
* Don't use readonly adjtime on Linux kernels before 2.6.28 * Don't use readonly adjtime on Linux kernels before 2.6.28
* Changed chronyc protocol, incompatible with older versions * Changed chronyc protocol, incompatible with older versions

21
README
View File

@@ -10,7 +10,7 @@ time. This does most of the work.
chronyc is a command-line interface program which can be used to chronyc is a command-line interface program which can be used to
monitor chronyd's performance and to change various operating monitor chronyd's performance and to change various operating
parateters whilst it is running. parameters whilst it is running.
chronyd's main function is to obtain measurements of the true (UTC) chronyd's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock time from one of several sources, and correct the system clock
@@ -21,12 +21,12 @@ between measurements from the reference.
The reference time can be derived from Network Time Protocol (NTP) The reference time can be derived from Network Time Protocol (NTP)
servers, reference clocks, or wristwatch-and-keyboard (via chronyc). servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
http://www.eecis.udel.edu/~ntp. http://www.ntp.org.
It is designed so that it can work on computers which only have It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet. Of course, it will work use a dial-up account to access the Internet or laptops. Of course, it
on computers with permanent connections too. will work well on computers with permanent connections too.
In addition, on Linux it can monitor the system's real time clock In addition, on Linux it can monitor the system's real time clock
performance, so the system can maintain accurate time even across performance, so the system can maintain accurate time even across
@@ -48,10 +48,7 @@ What will chrony run on?
Chrony can be successfully built and run on Chrony can be successfully built and run on
1. Linux v1.2.13, v2.0.x, 2.1.x (partially), 2.2.x, 2.3.x, 2.4.x, 2.6.x. 1. Linux 2.2.x, 2.3.x, 2.4.x, 2.6.x, 3.x
Real time clock support is limited to 2.0.32 onwards and to 2.2, 2.3,
2.4 and 2.6 series only. i386, x86_64, PowerPC are known to be
supported.
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms) 2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
@@ -88,12 +85,6 @@ through the URL
http://chrony.tuxfamily.org/ http://chrony.tuxfamily.org/
What can chrony not do?
=======================
Compared to the `reference' RFC1305 implementation xntpd, chronyd does
not support broadcast modes.
Where are new versions announced? Where are new versions announced?
================================= =================================
@@ -252,5 +243,3 @@ Doug Woodward <dougw@whistler.com>
Many other people have contributed bug reports and suggestions. I'm Many other people have contributed bug reports and suggestions. I'm
sorry I can't identify all of you individually. sorry I can't identify all of you individually.
vim:tw=72

View File

@@ -94,7 +94,7 @@ static int n_sources;
static int n_started_sources; static int n_started_sources;
static int n_completed_sources; static int n_completed_sources;
static int init_slew_threshold = -1; static double init_slew_threshold;
union sockaddr_in46 { union sockaddr_in46 {
struct sockaddr_in in4; struct sockaddr_in in4;
@@ -143,7 +143,6 @@ static SCH_TimeoutID source_start_timeout_id;
void void
ACQ_Initialise(void) ACQ_Initialise(void)
{ {
return;
} }
@@ -152,7 +151,6 @@ ACQ_Initialise(void)
void void
ACQ_Finalise(void) ACQ_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -201,7 +199,7 @@ prepare_socket(int family)
} }
if (bind(sock_fd, &my_addr.u, addrlen) < 0) { if (bind(sock_fd, &my_addr.u, addrlen) < 0) {
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno)); LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s", strerror(errno));
/* but keep running */ /* but keep running */
} }
} }
@@ -240,8 +238,6 @@ finalise_io(void)
} }
sock_fd6 = -1; sock_fd6 = -1;
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -256,6 +252,7 @@ probe_source(SourceRecord *src)
union sockaddr_in46 his_addr; union sockaddr_in46 his_addr;
int sock_fd; int sock_fd;
socklen_t addrlen; socklen_t addrlen;
uint32_t ts_fuzz;
#if 0 #if 0
printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples); printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
@@ -268,8 +265,8 @@ probe_source(SourceRecord *src)
pkt.stratum = 0; pkt.stratum = 0;
pkt.poll = 4; pkt.poll = 4;
pkt.precision = -6; /* as ntpdate */ pkt.precision = -6; /* as ntpdate */
pkt.root_delay = double_to_int32(1.0); /* 1 second */ pkt.root_delay = UTI_DoubleToInt32(1.0); /* 1 second */
pkt.root_dispersion = double_to_int32(1.0); /* likewise */ pkt.root_dispersion = UTI_DoubleToInt32(1.0); /* likewise */
pkt.reference_id = 0; pkt.reference_id = 0;
pkt.reference_ts.hi = 0; /* Set to 0 */ pkt.reference_ts.hi = 0; /* Set to 0 */
pkt.reference_ts.lo = 0; /* Set to 0 */ pkt.reference_ts.lo = 0; /* Set to 0 */
@@ -304,8 +301,9 @@ probe_source(SourceRecord *src)
} }
ts_fuzz = UTI_GetNTPTsFuzz(LCL_GetSysPrecisionAsLog());
LCL_ReadCookedTime(&cooked, NULL); LCL_ReadCookedTime(&cooked, NULL);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts); UTI_TimevalToInt64(&cooked, &pkt.transmit_ts, ts_fuzz);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE, if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
0, 0,
@@ -320,8 +318,6 @@ probe_source(SourceRecord *src)
++(src->n_dead_probes); ++(src->n_dead_probes);
src->timer_running = 1; src->timer_running = 1;
src->timeout_id = SCH_AddTimeoutByDelay(RETRANSMISSION_TIMEOUT, transmit_timeout, (void *) src); src->timeout_id = SCH_AddTimeoutByDelay(RETRANSMISSION_TIMEOUT, transmit_timeout, (void *) src);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -397,8 +393,8 @@ process_receive(NTP_Packet *msg, SourceRecord *src, struct timeval *now)
return; return;
} }
root_delay = int32_to_double(msg->root_delay); root_delay = UTI_Int32ToDouble(msg->root_delay);
root_dispersion = int32_to_double(msg->root_dispersion); root_dispersion = UTI_Int32ToDouble(msg->root_dispersion);
UTI_Int64ToTimeval(&src->last_tx, &local_orig); UTI_Int64ToTimeval(&src->last_tx, &local_orig);
UTI_Int64ToTimeval(&msg->receive_ts, &remote_rx); UTI_Int64ToTimeval(&msg->receive_ts, &remote_rx);
@@ -453,7 +449,7 @@ read_from_socket(void *anything)
his_addr_len = sizeof(his_addr); his_addr_len = sizeof(his_addr);
/* Get timestamp */ /* Get timestamp */
SCH_GetFileReadyTime(&now, NULL); SCH_GetLastEventTime(&now, NULL, NULL);
sock_fd = (long)anything; sock_fd = (long)anything;
status = recvfrom (sock_fd, (char *)&msg, message_length, flags, status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
@@ -699,7 +695,7 @@ process_measurements(void)
the system clock is fast of the reference, i.e. it needs to be the system clock is fast of the reference, i.e. it needs to be
stepped backwards. */ stepped backwards. */
if (fabs(estimated_offset) > (double) init_slew_threshold) { if (fabs(estimated_offset) > init_slew_threshold) {
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (step)", LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (step)",
fabs(estimated_offset), fabs(estimated_offset),
(estimated_offset >= 0) ? "fast" : "slow"); (estimated_offset >= 0) ? "fast" : "slow");
@@ -751,10 +747,11 @@ start_source_timeout_handler(void *not_used)
/* ================================================== */ /* ================================================== */
void void
ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything) ACQ_StartAcquisition(int n, IPAddr *ip_addrs, double threshold, void (*after_hook)(void *), void *anything)
{ {
int i, ip4, ip6; int i, ip4, ip6;
int k, duplicate_ip;
saved_after_hook = after_hook; saved_after_hook = after_hook;
saved_after_hook_anything = anything; saved_after_hook_anything = anything;
@@ -763,26 +760,37 @@ ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(
n_started_sources = 0; n_started_sources = 0;
n_completed_sources = 0; n_completed_sources = 0;
n_sources = n; n_sources = 0;
sources = MallocArray(SourceRecord, n); sources = MallocArray(SourceRecord, n);
for (i = ip4 = ip6 = 0; i < n; i++) { for (i = ip4 = ip6 = 0; i < n; i++) {
sources[i].ip_addr = ip_addrs[i]; /* check for duplicate IP addresses and ignore them */
sources[i].n_samples = 0; duplicate_ip = 0;
sources[i].n_total_samples = 0; for (k = 0; k < i; k++) {
sources[i].n_dead_probes = 0; duplicate_ip |= UTI_CompareIPs(&(sources[k].ip_addr),
&ip_addrs[i],
NULL) == 0;
}
if (!duplicate_ip) {
sources[n_sources].ip_addr = ip_addrs[i];
sources[n_sources].n_samples = 0;
sources[n_sources].n_total_samples = 0;
sources[n_sources].n_dead_probes = 0;
if (ip_addrs[i].family == IPADDR_INET4) if (ip_addrs[i].family == IPADDR_INET4)
ip4++; ip4++;
else if (ip_addrs[i].family == IPADDR_INET6) else if (ip_addrs[i].family == IPADDR_INET6)
ip6++; ip6++;
n_sources++;
} else {
LOG(LOGS_WARN, LOGF_Acquire, "Ignoring duplicate source: %s",
UTI_IPToString(&ip_addrs[i]));
}
} }
initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6)); initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
/* Start sampling first source */ /* Start sampling first source */
start_next_source(); start_next_source();
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -35,7 +35,7 @@ extern void ACQ_Initialise(void);
extern void ACQ_Finalise(void); extern void ACQ_Finalise(void);
extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold, extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, double init_slew_threshold,
void (*after_hook)(void *), void *anything); void (*after_hook)(void *), void *anything);
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance); extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);

View File

@@ -116,8 +116,6 @@ close_node(TableNode *node)
Free(node->extended); Free(node->extended);
node->extended = NULL; node->extended = NULL;
} }
return;
} }
@@ -141,7 +139,6 @@ open_node(TableNode *node)
child_node->extended = NULL; child_node->extended = NULL;
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -408,7 +405,6 @@ static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, i
print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4); print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
} }
} }
return;
} }
@@ -423,7 +419,6 @@ static void print_table(ADF_AuthTable table)
memset(addr, 0, sizeof (addr)); memset(addr, 0, sizeof (addr));
printf("IPv6 table:\n"); printf("IPv6 table:\n");
print_node(&table->base6, addr, 4, 124, 0); print_node(&table->base6, addr, 4, 124, 0);
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -49,7 +49,6 @@ static int max_destinations = 0;
void void
BRD_Initialise(void) BRD_Initialise(void)
{ {
return; /* Nothing to do */
} }
/* ================================================== */ /* ================================================== */
@@ -57,7 +56,6 @@ BRD_Initialise(void)
void void
BRD_Finalise(void) BRD_Finalise(void)
{ {
return; /* Nothing to do */
} }
/* ================================================== */ /* ================================================== */
@@ -73,7 +71,7 @@ timeout_handler(void *arbitrary)
int leap; int leap;
int are_we_synchronised, our_stratum; int are_we_synchronised, our_stratum;
NTP_Leap leap_status; NTP_Leap leap_status;
uint32_t our_ref_id; 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;
struct timeval local_transmit; struct timeval local_transmit;
@@ -101,20 +99,21 @@ timeout_handler(void *arbitrary)
/* If we're sending a client mode packet and we aren't synchronized yet, /* If we're sending a client mode packet and we aren't synchronized yet,
we might have to set up artificial values for some of these parameters */ we might have to set up artificial values for some of these parameters */
message.root_delay = double_to_int32(our_root_delay); message.root_delay = UTI_DoubleToInt32(our_root_delay);
message.root_dispersion = double_to_int32(our_root_dispersion); message.root_dispersion = UTI_DoubleToInt32(our_root_dispersion);
message.reference_id = htonl((NTP_int32) our_ref_id); message.reference_id = htonl((NTP_int32) our_ref_id);
/* Now fill in timestamps */ /* Now fill in timestamps */
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts); UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, 0);
message.originate_ts.hi = 0UL; message.originate_ts.hi = 0UL;
message.originate_ts.lo = 0UL; message.originate_ts.lo = 0UL;
message.receive_ts.hi = 0UL; message.receive_ts.hi = 0UL;
message.receive_ts.lo = 0UL; message.receive_ts.lo = 0UL;
ts_fuzz = UTI_GetNTPTsFuzz(message.precision);
LCL_ReadCookedTime(&local_transmit, NULL); LCL_ReadCookedTime(&local_transmit, NULL);
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts); UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz);
NIO_SendNormalPacket(&message, &d->addr); NIO_SendNormalPacket(&message, &d->addr);
/* Requeue timeout. Don't care if interval drifts gradually, so just do it /* Requeue timeout. Don't care if interval drifts gradually, so just do it

View File

@@ -507,7 +507,7 @@ typedef struct {
#define RPY_SD_ST_FALSETICKER 2 #define RPY_SD_ST_FALSETICKER 2
#define RPY_SD_ST_JITTERY 3 #define RPY_SD_ST_JITTERY 3
#define RPY_SD_ST_CANDIDATE 4 #define RPY_SD_ST_CANDIDATE 4
#define RPY_SD_ST_OUTLYER 5 #define RPY_SD_ST_OUTLIER 5
#define RPY_SD_FLAG_NOSELECT 0x1 #define RPY_SD_FLAG_NOSELECT 0x1
#define RPY_SD_FLAG_PREFER 0x2 #define RPY_SD_FLAG_PREFER 0x2

View File

@@ -21,7 +21,7 @@ to the Internet, and it can also act as an RFC1305-compatible NTP server.
.SH USAGE .SH USAGE
\fIchronyc\fR is a command-line interface program which can be used to \fIchronyc\fR is a command-line interface program which can be used to
monitor \fIchronyd\fR's performance and to change various operating monitor \fIchronyd\fR's performance and to change various operating
parateters whilst it is running. parameters whilst it is running.
\fIchronyd\fR's main function is to obtain measurements of the true (UTC) \fIchronyd\fR's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock time from one of several sources, and correct the system clock
@@ -32,16 +32,16 @@ between measurements from the reference.
The reference time can be derived from either Network Time Protocol The reference time can be derived from either Network Time Protocol
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR). (NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
\fIhttp://www.eecis.udel.edu/~ntp\fR. \fIhttp://www.ntp.org\fR.
It is designed so that it can work on computers which only have It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet. Of course, it will work use a dial-up account to access the Internet or laptops. Of course, it
on computers with permanent connections too. will work well on computers with permanent connections too.
In addition, for Linux 2.0.x (for x >= 32) or 2.2 onwards, chronyd can monitor In addition, on Linux it can monitor the system's real time clock
the system's real time clock performance, so the system can maintain accurate performance, so the system can maintain accurate time even across
time even across reboots. reboots.
Typical accuracies available between 2 machines are Typical accuracies available between 2 machines are

View File

@@ -3,7 +3,7 @@
chrony.conf \- chronyd configuration file chrony.conf \- chronyd configuration file
.SH SYNOPSIS .SH SYNOPSIS
.B /etc/chrony.conf .B @SYSCONFDIR@/chrony.conf
.SH DESCRIPTION .SH DESCRIPTION
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer \fIchrony\fR is a pair of programs for maintaining the accuracy of computer
@@ -12,7 +12,7 @@ boot time.
Assuming that you have found some servers, you need to set up a Assuming that you have found some servers, you need to set up a
configuration file to run \fIchrony\fR. The (compiled-in) default location configuration file to run \fIchrony\fR. The (compiled-in) default location
for this file is \fB/etc/chrony.conf\fR. Assuming that your ntp servers for this file is \fB@SYSCONFDIR@/chrony.conf\fR. Assuming that your ntp servers
are called `a.b.c' and `d.e.f', your \fBchrony.conf\fR file could contain are called `a.b.c' and `d.e.f', your \fBchrony.conf\fR file could contain
as a minimum as a minimum
@@ -29,9 +29,9 @@ useful configuration file would look something like
server a.b.c server a.b.c
server d.e.f server d.e.f
server g.h.i server g.h.i
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
commandkey 1 commandkey 1
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -1,38 +1,43 @@
%global chrony_version @@VERSION@@
%if 0%(echo %{chrony_version} | grep -q pre && echo 1)
%global prerelease %(echo %{chrony_version} | sed 's/.*-//')
%endif
Summary: An NTP client/server Summary: An NTP client/server
Name: chrony Name: chrony
Version: @@VERSION@@ Version: %(echo %{chrony_version} | sed 's/-.*//')
Release: 1 Release: %{!?prerelease:1}%{?prerelease:0.1.%{prerelease}}
Source: chrony-%{version}.tar.gz Source: chrony-%{version}%{?prerelease:-%{prerelease}}.tar.gz
Copyright: GPL License: GPLv2
Group: Applications/Utilities Group: Applications/Utilities
Packager: Richard P. Curnow <rc@rc0.org.uk>
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n) BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
Requires: info Requires: info
%description %description
A pair of programs for keeping computer clocks accurate. chronyd is a chrony is a client and server for the Network Time Protocol (NTP).
background (daemon) program and chronyc is a command-line interface to it. This program keeps your computer's clock accurate. It was specially
Time reference sources for chronyd can be RFC1305 NTP servers, human (via designed to support systems with intermittent Internet connections,
keyboard and chronyc), and the computer's real-time clock at boot time (Linux but it also works well in permanently connected environments. It can
only). chronyd can determine the rate at which the computer gains or loses also use hardware reference clocks, the system real-time clock, or
time and compensate for it whilst no external reference is present. chronyd's manual input as time references.
use of NTP servers can be switched on and off (through chronyc) to support
computers with dial-up/intermittent access to the Internet. chronyd can also
act as an RFC1305-compatible NTP server.
%prep %prep
%setup %setup -q -n %{name}-%{version}%{?prerelease:-%{prerelease}}
%build %build
./configure --prefix=%{_prefix} --mandir=%{_mandir} ./configure \
make CC=gcc CFLAGS=-O2 prefix=%{_prefix} --prefix=%{_prefix} \
make chrony.txt prefix=%{_prefix} --bindir=%{_bindir} \
make chrony.info prefix=%{_prefix} --sbindir=%{_sbindir} \
--infodir=%{_infodir} \
--mandir=%{_mandir}
make
make chrony.txt
make chrony.info
%install %install
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
cd $RPM_BUILD_DIR/chrony-%{version} make install DESTDIR=$RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix} rm -rf $RPM_BUILD_ROOT%{_docdir}
mkdir -p $RPM_BUILD_ROOT%{_infodir} mkdir -p $RPM_BUILD_ROOT%{_infodir}
cp chrony.info* $RPM_BUILD_ROOT%{_infodir} cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
@@ -47,6 +52,6 @@ cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
%doc README %doc README
%doc chrony.txt %doc chrony.txt
%doc COPYING %doc COPYING
%doc examples/chrony.conf.example %doc examples/chrony.conf.example*
%doc examples/chrony.keys.example %doc examples/chrony.keys.example

View File

@@ -93,10 +93,10 @@ Data Security, Inc. MD5 Message-Digest Algorithm} for authenticating
messages between different machines on the network. messages between different machines on the network.
In writing the @code{chronyd} program, extensive use has been made of In writing the @code{chronyd} program, extensive use has been made of
RFC1305, written by David Mills. I have occasionally referred to the RFC1305, written by David Mills. The @code{ntp} suite's source code has
@code{xntp} suite's source code to check details of the protocol that been occasionally used to check details of the protocol that the RFC did
the RFC did not make absolutely clear. The core algorithms in not make absolutely clear. The core algorithms in @code{chronyd} are
@code{chronyd} are all completely distinct from @code{xntp}, however. all completely distinct from @code{ntp}, however.
@c }}} @c }}}
@c {{{ S:Availability @c {{{ S:Availability
@node Availability @node Availability
@@ -148,34 +148,50 @@ requires access to such systems to test out the driver.
@node Other time synchronisation packages @node Other time synchronisation packages
@section Relationship to other software packages @section Relationship to other software packages
@menu @menu
* Comparison with xntpd:: * Comparison with ntpd::
* Comparison with timed:: * Comparison with timed::
@end menu @end menu
@node Comparison with xntpd @node Comparison with ntpd
@subsection xntpd @subsection ntpd
The `reference' implementation of the Network Time Protocol is the The `reference' implementation of the Network Time Protocol is the
program @code{xntpd}, available via program @code{ntpd}, available via
@uref{http://www.eecis.udel.edu/~ntp, The NTP home page}. @uref{http://www.ntp.org/, The NTP home page}.
@code{xntpd} is designed to support all the operating modes defined by One of the main differences between @code{ntpd} and @code{chronyd} is in
RFC1305, and has driver support for a large number of reference clocks the algorithms used to control the computer's clock. Things
(such as GPS receivers) that can be connected directly to a computer, @code{chronyd} can do better than @code{ntpd}:
thereby providing a so-called 'stratum 1' server.
Things @code{chronyd} can do that @code{xntpd} can't:
@itemize @bullet @itemize @bullet
@item @item
@code{chronyd} can perform usefully in an environment where access to @code{chronyd} can perform usefully in an environment where access to
the time reference is intermittent. @code{chronyd} estimates the time reference is intermittent. @code{ntpd} needs regular polling
@emph{both} the current time offset @emph{and} the rate at which the of the reference to work well.
computer's clock gains or loses time, and can use that rate estimate to @item
trim the clock after the reference disappears. @code{xntpd} corrects @code{chronyd} can usually synchronise the clock faster and with better
any time offset by speeding up and slowing down the computer clock, and time accuracy.
so could be left with a significant rate error if the reference @item
disappears whilst it is trying to correct a big offset. @code{chronyd} quickly adapts to sudden changes in the rate of the clock
(e.g. due to changes in the temperature of the crystal oscillator).
@code{ntpd} may need a long time to settle down again.
@item
@code{chronyd} can perform well even when the network is congested for
longer periods of time.
@item
@code{chronyd} in the default configuration never steps the time to not
upset other running programs. @code{ntpd} can be configured to never
step the time too, but it has to use a different means of adjusting the
clock, which has some
disadvantages.
@item
@code{chronyd} can adjust the rate of the clock on Linux in a larger
range, which allows it to operate even on machines with broken or
unstable clock (e.g. in some virtual machines).
@end itemize
Things @code{chronyd} can do that @code{ntpd} can't:
@itemize @bullet
@item @item
@code{chronyd} provides support for isolated networks whether the only @code{chronyd} provides support for isolated networks whether the only
method of time correction is manual entry (e.g. by the administrator method of time correction is manual entry (e.g. by the administrator
@@ -189,33 +205,27 @@ subsequently.
`real-time clock', i.e. the clock that maintains the time when the `real-time clock', i.e. the clock that maintains the time when the
computer is turned off. It can use this data when the system boots to computer is turned off. It can use this data when the system boots to
set the system time from a corrected version of the real-time clock. set the system time from a corrected version of the real-time clock.
These real-time clock facilities are only available on certain releases These real-time clock facilities are only available on Linux, so far.
of Linux, so far.
@item
The @code{xntpd} program is supported by other programs to carry out
certain functions. @code{ntpdate} is used to provide an initial
correction to the system clock based on a `one-shot' sampling of other
NTP servers. @code{tickadj} is used to adjust certain operating system
parameters to make @code{xntpd} work better. All this functionality is
integrated into @code{chronyd}.
@end itemize @end itemize
Things @code{xntpd} can do that @code{chronyd} can't: Things @code{ntpd} can do that @code{chronyd} can't:
@itemize @bullet @itemize @bullet
@item @item
@code{xntpd} supports effectively all of RFC1305, including broadcast / @code{ntpd} fully supports NTP version 4 (RFC5905), including broadcast,
multicast clients and extra encryption schemes for authenticating multicast, manycast clients / servers and the orphan mode. It also
data packets. supports extra authentication schemes based on public-key cryptography
(RFC5906). @code{chronyd} uses NTP version 3 (RFC1305), which is
compatible with version 4.
@item @item
@code{xntpd} has been ported to more types of computer / operating @code{ntpd} has been ported to more types of computer / operating
system (so far). system.
@item @item
xntpd is designed to work solely with integer arithmetic (i.e. does not @code{ntpd} includes drivers for many reference clocks. @code{chronyd}
require floating point support from its host). relies on other programs (e.g. gpsd) to access the data from the
reference clocks.
@end itemize @end itemize
@node Comparison with timed @node Comparison with timed
@@ -303,9 +313,9 @@ different architectures (Alpha, Sparc, MIPS as well as x86 of course).
@item Porting to Windows NT @item Porting to Windows NT
I did a small amount of work on this under Cygwin. Only the sorting out of the A small amount of work on this was done under Cygwin. Only the sorting
include files has really been achieved so far. The two main areas still to out of the include files has really been achieved so far. The two main
address are areas still to address are
@enumerate @enumerate
@item The system clock driver. @item The system clock driver.
@@ -560,11 +570,14 @@ customers.
stratum 1 and stratum 2 servers. You should find one or more servers stratum 1 and stratum 2 servers. You should find one or more servers
that are near to you --- check that their access policy allows you to that are near to you --- check that their access policy allows you to
use their facilities. use their facilities.
@item Use public servers from
@uref{http://www.pool.ntp.org/, the pool.ntp.org project}.
@end itemize @end itemize
Assuming that you have found some servers, you need to set up a Assuming that you have found some servers, you need to set up a
configuration file to run chrony. The (compiled-in) default location configuration file to run chrony. The (compiled-in) default location
for this file is @file{/etc/chrony.conf}. Assuming that your ntp for this file is @file{@SYSCONFDIR@/chrony.conf}. Assuming that your ntp
servers are called @code{a.b.c} and @code{d.e.f}, your servers are called @code{a.b.c} and @code{d.e.f}, your
@file{chrony.conf} file could contain as a minimum @file{chrony.conf} file could contain as a minimum
@@ -583,9 +596,9 @@ useful configuration file would look something like
server a.b.c server a.b.c
server d.e.f server d.e.f
server g.h.i server g.h.i
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
commandkey 1 commandkey 1
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
@end example @end example
@c }}} @c }}}
@c {{{ S:Infrequent connection @c {{{ S:Infrequent connection
@@ -595,7 +608,7 @@ In this section we discuss how to configure chrony for computers that
have occasional connections to the internet. have occasional connections to the internet.
@menu @menu
* Configuration for infrequent connections:: How to set up the @code{/etc/chrony} file * Configuration for infrequent connections:: How to set up the @code{@SYSCONFDIR@/chrony.conf} file
* Advising chronyd of internet availability:: How to tell chronyd when the link is available * Advising chronyd of internet availability:: How to tell chronyd when the link is available
@end menu @end menu
@@ -619,49 +632,35 @@ server d.e.f
server g.h.i server g.h.i
@end example @end example
However, the following issues need to be addressed: However, your computer will keep trying to contact the servers to obtain
@enumerate 1
@item
Your computer probably doesn't have DNS access whilst offline to turn
the machine names into IP addresses.
@item
Your computer will keep trying to contact the servers to obtain
timestamps, even whilst offline. If you operate a dial-on-demand timestamps, even whilst offline. If you operate a dial-on-demand
system, things are even worse, because the link to the internet will system, things are even worse, because the link to the internet will
keep getting established. keep getting established.
@end enumerate
For this reason, it would be better to specify this part of your For this reason, it would be better to specify this part of your
configuration file in the following way: configuration file in the following way:
@example @example
server 1.2.3.4 offline server a.b.c offline
server 5.6.7.8 offline server d.e.f offline
server 9.10.11.12 offline server g.h.i offline
@end example @end example
Because numeric IP addresses have been used, the first problem is The @code{offline} keyword indicates that the servers start
overcome. The @code{offline} keyword indicates that the servers start
in an offline state, and that they should not be contacted until @code{chronyd} in an offline state, and that they should not be contacted until @code{chronyd}
receives notification that the link to the internet is present. receives notification that the link to the internet is present.
An alternative is to use the names of the NTP servers, and put entries for them
into your @file{/etc/hosts} file. This will be OK as long as @samp{files}
comes before @samp{dns} in the @samp{hosts} line of the
@file{/etc/nsswitch.conf} file.
In order to notify @code{chronyd} of the presence of the link, you will need to In order to notify @code{chronyd} of the presence of the link, you will need to
be able to log in to it with the program chronyc. To do this, @code{chronyd} be able to log in to it with the program chronyc. To do this, @code{chronyd}
needs to be configured with an administrator password. To set up an needs to be configured with an administrator password. To set up an
administrator password, you can create a file @file{/etc/chrony.keys} administrator password, you can create a file @file{@SYSCONFDIR@/chrony.keys}
containing a single line containing a single line
@example @example
1 xyzzy 1 ALongAndRandomPassword
@end example @end example
and add the following line to @file{/etc/chrony.conf} (the order of the and add the following line to @file{@SYSCONFDIR@/chrony.conf} (the order of the
lines does not matter) lines does not matter)
@example @example
@@ -671,12 +670,12 @@ commandkey 1
The smallest useful configuration file would look something like The smallest useful configuration file would look something like
@example @example
server 1.2.3.4 offline server a.b.c offline
server 5.6.7.8 offline server d.e.f offline
server 9.10.11.12 offline server g.h.i offline
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
commandkey 1 commandkey 1
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
@end example @end example
The next section describes how to tell @code{chronyd} when the internet link The next section describes how to tell @code{chronyd} when the internet link
@@ -685,33 +684,27 @@ goes up and down.
@node Advising chronyd of internet availability @node Advising chronyd of internet availability
@subsection How to tell chronyd when the internet link is available. @subsection How to tell chronyd when the internet link is available.
To use this option, you will need to configure a command key in To use this option, you will need to configure a command key in
@code{chronyd's} configuration file @file{/etc/chrony.conf}, as described in @code{chronyd's} configuration file @file{@SYSCONFDIR@/chrony.conf}, as described in
the previous section. the previous section.
To tell @code{chronyd} when to start and finish sampling the servers, the To tell @code{chronyd} when to start and finish sampling the servers, the
@code{online} and @code{offline} commands of chronyc need to be used. @code{online} and @code{offline} commands of chronyc need to be used.
To give an example of their use, we assume that @code{pppd} is the To give an example of their use, we assume that @code{pppd} is the
program being used to connect to the internet, and that chronyc has been program being used to connect to the internet, and that chronyc has been
installed at its default location @file{/usr/local/bin/chronyc}. We installed at its default location @file{@BINDIR@/chronyc}. We
also assume that the command key has been set up as described in the also assume that the command key has been set up as described in the
previous section. previous section.
In the file @file{/etc/ppp/ip-up} we add the command sequence In the file @file{/etc/ppp/ip-up} we add the command sequence
@example @example
/usr/local/bin/chronyc <<EOF @BINDIR@/chronyc -a online
password xyzzy
online
EOF
@end example @end example
and in the file @file{/etc/ppp/ip-down} we add the sequence and in the file @file{/etc/ppp/ip-down} we add the sequence
@example @example
/usr/local/bin/chronyc <<EOF @BINDIR@/chronyc -a offline
password xyzzy
offline
EOF
@end example @end example
@code{chronyd's} polling of the servers will now only occur whilst the @code{chronyd's} polling of the servers will now only occur whilst the
@@ -746,9 +739,9 @@ be (assuming the clients are in the 192.168.165.x subnet and that the
master's address is 192.168.169.170) master's address is 192.168.169.170)
@example @example
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
commandkey 25 commandkey 25
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
initstepslew 10 client1 client3 client6 initstepslew 10 client1 client3 client6
local stratum 8 local stratum 8
manual manual
@@ -760,10 +753,10 @@ the configuration file might be
@example @example
server master server master
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
logdir /var/log/chrony logdir /var/log/chrony
log measurements statistics tracking log measurements statistics tracking
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
commandkey 24 commandkey 24
local stratum 10 local stratum 10
initstepslew 20 master initstepslew 20 master
@@ -895,102 +888,58 @@ option should not be used if you want your disc to spin down.
To illustrate how a dial-up home computer might be configured, example To illustrate how a dial-up home computer might be configured, example
configuration files are shown in this section. configuration files are shown in this section.
For the @file{/etc/chrony.conf} file, the following can be used as an For the @file{@SYSCONFDIR@/chrony.conf} file, the following can be used as an
example. @emph{NOTE : The @code{server} directives are only applicable example.
to customers of Demon Internet; users of other ISPs will need to use
their own ISP's NTP servers or public NTP servers.}
@example @example
server 158.152.1.65 minpoll 5 maxpoll 10 maxdelay 0.4 offline server 0.pool.ntp.org minpoll 5 maxpoll 10 maxdelay 0.4 offline
server 158.152.1.76 minpoll 5 maxpoll 10 maxdelay 0.4 offline server 1.pool.ntp.org minpoll 5 maxpoll 10 maxdelay 0.4 offline
server 194.159.253.2 minpoll 5 maxpoll 10 maxdelay 0.4 offline server 2.pool.ntp.org minpoll 5 maxpoll 10 maxdelay 0.4 offline
logdir /var/log/chrony logdir /var/log/chrony
log statistics measurements tracking log statistics measurements tracking
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
commandkey 25 commandkey 25
maxupdateskew 100.0 maxupdateskew 100.0
dumponexit dumponexit
dumpdir /var/log/chrony dumpdir @CHRONYVARDIR@
rtcfile /etc/chrony.rtc rtcfile @CHRONYVARDIR@/rtc
@end example @end example
With Freeserve as the ISP, I use the following server lines : @code{pppd} is used for connecting to the internet. This runs two scripts
@example
server 194.152.64.68 minpoll 5 maxpoll 10 maxdelay 0.4 offline
server 194.152.64.35 minpoll 5 maxpoll 10 maxdelay 0.4 offline
server 194.152.64.34 minpoll 5 maxpoll 10 maxdelay 0.4 offline
@end example
I use @code{pppd} for connecting to my ISP. This runs two scripts
@file{/etc/ppp/ip-up} and @file{/etc/ppp/ip-down} when the link goes @file{/etc/ppp/ip-up} and @file{/etc/ppp/ip-down} when the link goes
online and offline respectively. online and offline respectively.
The relevant part of the @file{/etc/ppp/ip-up} file is (with a dummy The relevant part of the @file{/etc/ppp/ip-up} file is
password)
@example @example
/usr/local/bin/chronyc <<EOF @BINDIR@/chronyc -a online
password xxxxxxxx
online
EOF
@end example @end example
and the relevant part of the @file{/etc/ppp/ip-down} script is and the relevant part of the @file{/etc/ppp/ip-down} script is
@example @example
/usr/local/bin/chronyc <<EOF @BINDIR@/chronyc -a -m offline dump writertc
password xxxxxxxx
offline
dump
writertc
EOF
@end example @end example
(Because they have to contain the administrator password, it would be To start @code{chronyd} during the boot sequence, the following
desirable to make the files readable only by root on a multiuser is in @file{/etc/rc.d/rc.local} (this is a Slackware system)
machine).
To start @code{chronyd} during the boot sequence, I have the following
in @file{/etc/rc.d/rc.local} (this is a Slackware system)
@example @example
if [ -f /usr/local/sbin/chronyd -a -f /etc/chrony.conf ]; then if [ -f @SBINDIR@/chronyd -a -f @SYSCONFDIR@/chrony.conf ]; then
/usr/local/sbin/chronyd -r -s @SBINDIR@/chronyd -r -s
echo "Start chronyd" echo "Start chronyd"
fi fi
@end example @end example
The placement of this command may be important on some systems. In The placement of this command may be important on some systems. In
particular, @code{chronyd} may need to be started several seconds (about particular, @code{chronyd} may need to be started before any software
10 as a minimum) before any software that depends on the system clock that depends on the system clock not jumping or moving backwards,
not jumping or moving backwards, depending on the directives in depending on the directives in @code{chronyd's} configuration file.
@code{chronyd's} configuration file.
For the system shutdown, @code{chronyd} should receive a SIGTERM several For the system shutdown, @code{chronyd} should receive a SIGTERM several
seconds before the final SIGKILL; the SIGTERM causes the measurement seconds before the final SIGKILL; the SIGTERM causes the measurement
histories and RTC information to be saved out. There should be no need histories and RTC information to be saved out.
to add anything to the shutdown sequence, unless (as my system had)
there is no pause between the SIGTERM and SIGKILL being delivered to the
remaining processes. So if you find something like
@example
killall5 -15
killall5 -9
@end example
in your @code{/etc/rc.d/rc.0} script, you will need to insert a sleep, e.g.
@example
killall5 -15
sleep 5
killall5 -9
@end example
Otherwise, @code{chronyd} will not always save information on shutdown,
which could be a problem if you don't use @code{dump} and
@code{writertc} when you go offline.
@c }}} @c }}}
@c {{{ S:Other config options @c {{{ S:Other config options
@node Configuration options overview @node Configuration options overview
@@ -1008,14 +957,14 @@ determination is taking place.
To avoid this problem, @code{chronyd} allows the gain or loss rate to be To avoid this problem, @code{chronyd} allows the gain or loss rate to be
stored in a file, which can be read back in when the program is stored in a file, which can be read back in when the program is
restarted. This file is called the drift file, and might typically be restarted. This file is called the drift file, and might typically be
stored in @file{/etc/chrony.drift}. By specifying an option like the stored in @file{@CHRONYVARDIR@/drift}. By specifying an option like the
following following
@example @example
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
@end example @end example
in the configuration file (@file{/etc/chrony.conf}), the drift file in the configuration file (@file{@SYSCONFDIR@/chrony.conf}), the drift file
facility will be activated. facility will be activated.
@c }}} @c }}}
@c }}} @c }}}
@@ -1034,11 +983,11 @@ facility will be activated.
@node Starting chronyd @node Starting chronyd
@section Starting chronyd @section Starting chronyd
If @code{chronyd} has been installed to its default location If @code{chronyd} has been installed to its default location
@file{/usr/local/sbin/chronyd}, starting it is simply a matter of @file{@SBINDIR@/chronyd}, starting it is simply a matter of
entering the command entering the command
@example @example
/usr/local/sbin/chronyd @SBINDIR@/chronyd
@end example @end example
Information messages and warnings will be logged to syslog. Information messages and warnings will be logged to syslog.
@@ -1055,7 +1004,7 @@ terminal, and all messages will be sent to the terminal instead of to
syslog. syslog.
@item -f <conf-file> @item -f <conf-file>
This option can be used to specify an alternate location for the This option can be used to specify an alternate location for the
configuration file (default @file{/etc/chrony.conf}). configuration file (default @file{@SYSCONFDIR@/chrony.conf}).
@item -r @item -r
This option will reload sample histories for each of the servers being This option will reload sample histories for each of the servers being
used. These histories are created by using the @code{dump} command in used. These histories are created by using the @code{dump} command in
@@ -1067,6 +1016,12 @@ maintain clock compensation whilst not under @code{chronyd's} control.
The only version where this happens so far is Linux. On systems where The only version where this happens so far is Linux. On systems where
this is not the case, e.g. Solaris and SunOS the option should not be this is not the case, e.g. Solaris and SunOS the option should not be
used. used.
@item -R
When this option is used, the @code{initstepslew} directive and the
@code{makestep} directive used with a positive limit will be ignored.
This option is useful when restarting @code{chronyd} and can be used
in conjuction with the `-r' option.
@item -s @item -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. This is analogous to supplying the `-s' flag to the clock. This is analogous to supplying the `-s' flag to the
@@ -1102,15 +1057,17 @@ supported only on Linux.
This option will lock chronyd into RAM so that it will never be paged This option will lock chronyd into RAM so that it will never be paged
out. This mode is only supported on Linux. out. This mode is only supported on Linux.
@item -4 @item -4
With this option hostnames will be resolved only to IPv4 addresses. With this option hostnames will be resolved only to IPv4 addresses and only
IPv4 sockets will be created.
@item -6 @item -6
With this option hostnames will be resolved only to IPv6 addresses. With this option hostnames will be resolved only to IPv6 addresses and only
IPv6 sockets will be created.
@end table @end table
On systems that support an @file{/etc/rc.local} file for starting On systems that support an @file{/etc/rc.local} file for starting
programs at boot time, @code{chronyd} can be started from there. programs at boot time, @code{chronyd} can be started from there.
On systems with a System V style initialisation (e.g. Solaris), a On systems with a System V style initialisation, a
suitable start/stop script might be as shown below. This might be suitable start/stop script might be as shown below. This might be
placed in the file @file{/etc/rc2.d/S83chrony}. placed in the file @file{/etc/rc2.d/S83chrony}.
@@ -1130,7 +1087,7 @@ killproc() @{ # kill the named process(es)
case "$1" in case "$1" in
'start') 'start')
if [ -f /opt/free/sbin/chronyd -a -f /etc/chrony.conf ]; then if [ -f /opt/free/sbin/chronyd -a -f @SYSCONFDIR@/chrony.conf ]; then
/opt/free/sbin/chronyd /opt/free/sbin/chronyd
fi fi
;; ;;
@@ -1155,7 +1112,7 @@ service.)
@node Configuration file @node Configuration file
@section The chronyd configuration file @section The chronyd configuration file
@c {{{ section top @c {{{ section top
The configuration file is normally called @file{/etc/chrony.conf}; in The configuration file is normally called @file{@SYSCONFDIR@/chrony.conf}; in
fact, this is the compiled-in default. However, other locations can be fact, this is the compiled-in default. However, other locations can be
specified with a command line option. specified with a command line option.
@@ -1172,6 +1129,7 @@ directives can occur in any order in the file.
* broadcast directive:: Make chronyd act as an NTP broadcast server * broadcast directive:: Make chronyd act as an NTP broadcast server
* cmdallow directive:: Give control access to chronyc on other computers * cmdallow directive:: Give control access to chronyc on other computers
* cmddeny directive:: Deny control access to chronyc on other computers * cmddeny directive:: Deny control access to chronyc on other computers
* combinelimit directive:: Limit sources included in combining algorithm
* commandkey directive:: Set runtime command key * commandkey directive:: Set runtime command key
* corrtimeratio directive:: Set correction time ratio * corrtimeratio directive:: Set correction time ratio
* cmdport directive:: Set port to use for runtime commanding * cmdport directive:: Set port to use for runtime commanding
@@ -1180,6 +1138,7 @@ directives can occur in any order in the file.
* dumpdir directive:: Specify directory for dumping measurements * dumpdir directive:: Specify directory for dumping measurements
* dumponexit directive:: Dump measurements when daemon exits * dumponexit directive:: Dump measurements when daemon exits
* fallbackdrift directive:: Specify fallback drift intervals * fallbackdrift directive:: Specify fallback drift intervals
* generatecommandkey directive:: Generate command key automatically
* include directive:: Include a configuration file * include directive:: Include a configuration file
* initstepslew directive:: Trim the system clock on boot-up. * initstepslew directive:: Trim the system clock on boot-up.
* keyfile directive:: Specify location of file containing keys * keyfile directive:: Specify location of file containing keys
@@ -1196,7 +1155,9 @@ directives can occur in any order in the file.
* maxchange directive:: Set maximum allowed offset * maxchange directive:: Set maximum allowed offset
* manual directive:: Allow manual entry using chronyc's settime cmd. * manual directive:: Allow manual entry using chronyc's settime cmd.
* maxclockerror directive:: Set maximum frequency error of local clock * maxclockerror directive:: Set maximum frequency error of local clock
* maxsamples directive:: Set maximum number of samples per source
* maxupdateskew directive:: Stop bad estimates upsetting machine clock * maxupdateskew directive:: Stop bad estimates upsetting machine clock
* minsamples directive:: Set minimum number of samples per source
* noclientlog directive:: Prevent chronyd from gathering data about clients * noclientlog directive:: Prevent chronyd from gathering data about clients
* clientloglimit directive:: Set client log memory limit * clientloglimit directive:: Set client log memory limit
* peer directive:: Specify an NTP peer * peer directive:: Specify an NTP peer
@@ -1213,6 +1174,7 @@ directives can occur in any order in the file.
* stratumweight directive:: Specify how important is stratum when selecting source * stratumweight directive:: Specify how important is stratum when selecting source
* lock_all directive:: Require that chronyd be locked into RAM. * lock_all directive:: Require that chronyd be locked into RAM.
* tempcomp directive:: Specify temperature sensor and compensation coefficients * tempcomp directive:: Specify temperature sensor and compensation coefficients
* user directive:: Specify user for dropping root privileges
@end menu @end menu
@c }}} @c }}}
@@ -1410,12 +1372,12 @@ chronyd is running.
You can have more than 1 @code{broadcast} directive if you have more than 1 You can have more than 1 @code{broadcast} directive if you have more than 1
network interface onto which you wish to send NTP broadcast packets. network interface onto which you wish to send NTP broadcast packets.
Chronyd itself cannot currently act as a broadcast client; it must always be @code{chronyd} itself cannot currently act as a broadcast client; it must always be
configured as a point-to-point client by defining specific NTP servers and configured as a point-to-point client by defining specific NTP servers and
peers. This broadcast server feature is intended for providing a time source peers. This broadcast server feature is intended for providing a time source
to other NTP software (e.g. various MS Windows clients). to other NTP software (e.g. various MS Windows clients).
If xntpd is used as the broadcast client, it will try to use a point-to-point If ntpd is used as the broadcast client, it will try to use a point-to-point
client/server NTP access to measure the round-trip delay. Thus, the broadcast client/server NTP access to measure the round-trip delay. Thus, the broadcast
subnet should also be the subject of an @code{allow} directive (@pxref{allow subnet should also be the subject of an @code{allow} directive (@pxref{allow
directive}). directive}).
@@ -1448,6 +1410,30 @@ The syntax is identical.
There is also a @code{cmddeny all} directive with similar behaviour to the There is also a @code{cmddeny all} directive with similar behaviour to the
@code{cmdallow all} directive. @code{cmdallow all} directive.
@c }}} @c }}}
@c {{{ combinelimit
@node combinelimit directive
@subsection combinelimit
When @code{chronyd} has multiple sources available for synchronization, it has
to select one source as the synchronization source. The measured offsets and
frequencies of the system clock relative to the other sources, however, can be
combined with the selected source to improve the accuracy of the system clock.
The @code{combinelimit} directive limits which sources are included in the
combining algorithm. Their synchronization distance has to be shorter than the
distance of the selected source multiplied by the value of the limit. Also,
their measured frequencies have to be close to the frequency of the selected
source.
By default, the limit is 3. Setting the limit to 0 effectively disables the
source combining algorithm and only the selected source will be used to
control the system clock.
The syntax is
@example
combinelimit <limit>
@end example
@c }}}
@c {{{ commandkey @c {{{ commandkey
@node commandkey directive @node commandkey directive
@subsection commandkey @subsection commandkey
@@ -1462,11 +1448,13 @@ An example of the commandkey command is
commandkey 20 commandkey 20
@end example @end example
By default, the key number is 0.
In the key file (see the keyfile command) there should be a line of In the key file (see the keyfile command) there should be a line of
the form the form
@example @example
20 foobar 20 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC
@end example @end example
When running the chronyc program to perform run-time configuration, When running the chronyc program to perform run-time configuration,
@@ -1477,7 +1465,8 @@ password foobar
@end example @end example
must be entered before any commands affecting the operation of the must be entered before any commands affecting the operation of the
daemon can be entered. daemon can be entered, or chronyc must be started with the `-a' option to run
the password command automatically.
@c }}} @c }}}
@c {{{ cmdport @c {{{ cmdport
@node cmdport directive @node cmdport directive
@@ -1569,7 +1558,7 @@ which the true rate actually lies.
An example of the driftfile command is An example of the driftfile command is
@example @example
driftfile /etc/chrony.drift driftfile @CHRONYVARDIR@/drift
@end example @end example
@c }}} @c }}}
@c {{{ dumpdir @c {{{ dumpdir
@@ -1595,12 +1584,12 @@ directory where the measurement histories are saved.
An example of the command is An example of the command is
@example @example
dumpdir /var/log/chrony dumpdir @CHRONYVARDIR@
@end example @end example
A source whose reference id (the IP address for IPv4 sources) is A source whose reference id (the IP address for IPv4 sources) is
1.2.3.4 would have its measurement history saved in the file 1.2.3.4 would have its measurement history saved in the file
@file{/var/log/chrony/1.2.3.4.dat}. @file{/var/lib/chrony/1.2.3.4.dat}.
@c }}} @c }}}
@c {{{ dumponexit @c {{{ dumponexit
@node dumponexit directive @node dumponexit directive
@@ -1637,6 +1626,16 @@ By default (or if the specified maximum or minimum is 0), no fallbacks
will be used and the clock frequency will stay at the last value will be used and the clock frequency will stay at the last value
calculated before synchronisation was lost. calculated before synchronisation was lost.
@c }}} @c }}}
@c {{{ generatecommandkey
@node generatecommandkey directive
@subsection generatecommandkey
With this directive, if the command key is not found on start in the file
specified by the @code{keyfile} directive, @code{chronyd} will generate a new
command key from the /dev/urandom file and write it to the key file.
The generated key will use SHA1 if @code{chronyd} is compiled with the support,
otherwise MD5 will be used.
@c }}}
@c {{{ include @c {{{ include
@node include directive @node include directive
@subsection include @subsection include
@@ -1645,7 +1644,7 @@ This is useful when maintaining configuration on multiple hosts to
keep the differences in a separate file. keep the differences in a separate file.
@example @example
include /etc/chrony/local.conf include @SYSCONFDIR@/chrony/local.conf
@end example @end example
@c }}} @c }}}
@c {{{ initstepslew @c {{{ initstepslew
@@ -1720,7 +1719,7 @@ ID/key pairs for the following 2 uses:
The format of the command is shown in the example below The format of the command is shown in the example below
@example @example
keyfile /etc/chrony.keys keyfile @SYSCONFDIR@/chrony.keys
@end example @end example
The argument is simply the name of the file containing the ID/key The argument is simply the name of the file containing the ID/key
@@ -1743,8 +1742,13 @@ password can be encoded as a string of characters not containing a space with
optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:} optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:}
prefix. prefix.
The ID for the chronyc authentication key is specified with the For maximum security, it's recommended to use SHA1 or stronger hash function.
commandkey command (see earlier). The passwords should be random and they should be as long as the output size of
the configured hash function, e.g. 160 bits with SHA1.
The ID for the chronyc authentication key is specified with the commandkey
command (see earlier). The command key can be generated automatically on
start with the @code{generatecommandkey} directive.
@c }}} @c }}}
@c {{{ leapsectz @c {{{ leapsectz
@node leapsectz directive @node leapsectz directive
@@ -2030,7 +2034,8 @@ An example line (which actually appears as a single line in the file)
from the tracking log file is shown below. from the tracking log file is shown below.
@example @example
2012-02-23 05:40:50 158.152.1.76 3 340.529 1.606 1.046e-03 N 2012-02-23 05:40:50 158.152.1.76 3 340.529 1.606 1.046e-03 N \
4 6.849e-03 -4.670e-04
@end example @end example
The columns are as follows (the quantities in square brackets are the The columns are as follows (the quantities in square brackets are the
@@ -2060,6 +2065,14 @@ system is fast of UTC). [1.046e-3]
Leap status (@code{N} means normal, @code{+} means that the last minute Leap status (@code{N} means normal, @code{+} means that the last minute
of this month has 61 seconds, @code{-} means that the last minute of the month of this month has 61 seconds, @code{-} means that the last minute of the month
has 59 seconds, @code{?} means the clock is not currently synchronised.) [N] has 59 seconds, @code{?} means the clock is not currently synchronised.) [N]
@item
The number of combined sources. [4]
@item
The estimated standard deviation of the combined offset (in seconds).
[6.849e-03]
@item
The remaining offset correction from the previous update (in seconds, positive
means the system clock is slow of UTC). [-4.670e-04]
@end enumerate @end enumerate
A banner is periodically written to the log file to indicate the A banner is periodically written to the log file to indicate the
@@ -2332,6 +2345,19 @@ Typical values for <error-in-ppm> might be 10 for a low quality clock
to 0.1 for a high quality clock using a temperature compensated to 0.1 for a high quality clock using a temperature compensated
crystal oscillator. crystal oscillator.
@c }}} @c }}}
@c {{{ maxsamples
@node maxsamples directive
@subsection maxsamples
The @code{maxsamples} directive sets the maximum number of samples
@code{chronyd} should keep for each source. The default is 0, which
disables the configurable limit, and the useful range is 4 to 64.
The syntax is
@example
maxsamples <samples>
@end example
@c }}}
@c {{{ maxupdateskew @c {{{ maxupdateskew
@node maxupdateskew directive @node maxupdateskew directive
@subsection maxupdateskew @subsection maxupdateskew
@@ -2366,6 +2392,19 @@ highly-reliable master estimate and a new estimate is generated which
has large error bounds, the existing master estimate will dominate in has large error bounds, the existing master estimate will dominate in
the new master estimate. the new master estimate.
@c }}} @c }}}
@c {{{ minsamples
@node minsamples directive
@subsection minsamples
The @code{minsamples} directive sets the minimum number of samples
@code{chronyd} should try to keep for each source. The default is 0 and the
useful range is 4 to 64.
The syntax is
@example
minsamples <samples>
@end example
@c }}}
@c {{{ noclientlog @c {{{ noclientlog
@node noclientlog directive @node noclientlog directive
@subsection noclientlog @subsection noclientlog
@@ -2413,7 +2452,8 @@ on your machine.
The compiled in default is udp/123, the standard NTP port. It is The compiled in default is udp/123, the standard NTP port. It is
unlikely that you would ever need to change this value. A possible unlikely that you would ever need to change this value. A possible
exception would be if you wanted to operate strictly in client-only exception would be if you wanted to operate strictly in client-only
mode and never be available as a server to xntpd clients. mode and never be available as a server to ntpd clients. If set to 0,
the kernel will assign a random port.
An example of the port command is An example of the port command is
@@ -2468,7 +2508,7 @@ Some examples of applications that can be used as SHM sources are @code{gpsd},
@item SOCK @item SOCK
Unix domain socket driver. It is similar to the SHM driver, but uses a Unix domain socket driver. It is similar to the SHM driver, but uses a
different format and uses a socket instead of shared memory. It does not different format and uses a socket instead of shared memory. It does not
require polling, the offset resolution is not limited to microseconds and it require polling and it
supports transmitting of PPS data. The parameter is a path to the socket which supports transmitting of PPS data. The parameter is a path to the socket which
will be created by @code{chronyd} and used to receive the messages. The format will be created by @code{chronyd} and used to receive the messages. The format
of messages sent over the socket is described in the of messages sent over the socket is described in the
@@ -2581,7 +2621,7 @@ of the system's real-time clock (RTC).
The syntax is illustrated in the following example The syntax is illustrated in the following example
@example @example
rtcfile /etc/chrony.rtc rtcfile @CHRONYVARDIR@/rtc
@end example @end example
@code{chronyd} saves information in this file when it exits and when the @code{chronyd} saves information in this file when it exits and when the
@@ -2652,12 +2692,12 @@ This mode is supported only on Linux.
This directive uses the Linux sched_setscheduler() system call to This directive uses the Linux sched_setscheduler() system call to
instruct the kernel to use the SCHED_FIFO first-in, first-out instruct the kernel to use the SCHED_FIFO first-in, first-out
real-time scheduling policy for Chronyd with the specified priority. real-time scheduling policy for @code{chronyd} with the specified priority.
This means that whenever Chronyd is ready to run it will run, This means that whenever @code{chronyd} is ready to run it will run,
interrupting whatever else is running unless it is a higher priority interrupting whatever else is running unless it is a higher priority
real-time process. This should not impact performance as Chronyd's real-time process. This should not impact performance as @code{chronyd's}
resource requirements are modest, but it should result in lower and resource requirements are modest, but it should result in lower and
more consistent latency since Chronyd will not need to wait for the more consistent latency since @code{chronyd} will not need to wait for the
scheduler to get around to running it. You should not use this unless scheduler to get around to running it. You should not use this unless
you really need it. The sched_setscheduler man page has more details. you really need it. The sched_setscheduler man page has more details.
@c }}} @c }}}
@@ -2687,10 +2727,10 @@ ignore stratum when selecting the source.
The @code{lock_all} directive will lock chronyd into RAM so that it The @code{lock_all} directive will lock chronyd into RAM so that it
will never be paged out. This mode is only supported on Linux. This will never be paged out. This mode is only supported on Linux. This
directive uses the Linux mlockall() system call to prevent Chronyd directive uses the Linux mlockall() system call to prevent @code{chronyd}
from ever being swapped out. This should result in lower and more from ever being swapped out. This should result in lower and more
consistent latency. It should not have significant impact on consistent latency. It should not have significant impact on
performance as Chronyd's memory usage is modest. The mlockall man performance as @code{chronyd's} memory usage is modest. The mlockall man
page has more details. page has more details.
@c }}} @c }}}
@c {{{ server @c {{{ server
@@ -2876,6 +2916,15 @@ every 30 seconds. When the temperature is 26 degress (26000), the system clock
frequency will not be adjusted. When it is 27 degrees (27000), the clock will frequency will not be adjusted. When it is 27 degrees (27000), the clock will
be set to run 0.183ppm faster than it would be without the compensation, etc. be set to run 0.183ppm faster than it would be without the compensation, etc.
@c }}}
@c {{{ user
@node user directive
@subsection user
The @code{user} directive sets the name of the user to which will
@code{chronyd} drop root privileges after the initialisation. So far, it works
only on Linux when compiled with capabilities support.
By default, root privileges are not dropped.
@c }}} @c }}}
@c }}} @c }}}
@c {{{ S:Running chronyc @c {{{ S:Running chronyc
@@ -2941,6 +2990,14 @@ With this option hostnames will be resolved only to IPv6 addresses.
@item -m @item -m
With this option multiple commands can be specified on the command line. With this option multiple commands can be specified on the command line.
Each argument will be interpreted as a whole command. Each argument will be interpreted as a whole command.
@item -f <conf-file>
This option can be used to specify an alternate location of the @code{chronyd}
configuration file (default @file{@SYSCONFDIR@/chrony.conf}). The configuration file is
needed for the `-a' option.
@item -a
With this option @code{chronyc} will try to authenticate automatically on
start. It will read the configuration file, read the command key from the
keyfile and run the authhash and password commands.
@end table @end table
@c }}} @c }}}
@c {{{ SS:Security with chronyc @c {{{ SS:Security with chronyc
@@ -2951,7 +3008,7 @@ power to reconfigure the run-time behaviour of @code{chronyd}. Consequently,
@code{chronyc} is quite dangerous for the integrity of the target @code{chronyc} is quite dangerous for the integrity of the target
system's clock performance. Having access to @code{chronyd} via chronyc is system's clock performance. Having access to @code{chronyd} via chronyc is
more or less equivalent to being able to modify @code{chronyd's} configuration more or less equivalent to being able to modify @code{chronyd's} configuration
file (typically @file{/etc/chrony.conf}) and to restart @code{chronyd}. file (typically @file{@SYSCONFDIR@/chrony.conf}) and to restart @code{chronyd}.
Chronyc also provides a number of monitoring (as opposed to commanding) Chronyc also provides a number of monitoring (as opposed to commanding)
commands, which will not affect the behaviour of @code{chronyd}. However, you commands, which will not affect the behaviour of @code{chronyd}. However, you
@@ -3172,6 +3229,9 @@ An example is
@example @example
authhash SHA1 authhash SHA1
@end example @end example
The authhash command is run automatically on start if @code{chronyc} was
started with the `-a' option.
@c }}} @c }}}
@c {{{ burst @c {{{ burst
@node burst command @node burst command
@@ -3190,6 +3250,7 @@ The syntax of the burst command is as follows
@example @example
burst <n-good-measurements>/<max-measurements> [<mask>/<masked-address>] burst <n-good-measurements>/<max-measurements> [<mask>/<masked-address>]
burst <n-good-measurements>/<max-measurements> [<masked-address>/<masked-bits>] burst <n-good-measurements>/<max-measurements> [<masked-address>/<masked-bits>]
burst <n-good-measurements>/<max-measurements> [<address>]
@end example @end example
The mask and masked-address arguments are optional, in which case The mask and masked-address arguments are optional, in which case
@@ -3222,6 +3283,10 @@ then the burst command is applied to that source.
This can be used with @code{masked-address} for CIDR notation, which is a This can be used with @code{masked-address} for CIDR notation, which is a
shorter alternative to the form with mask. shorter alternative to the form with mask.
@item address
This is an IP address or a hostname. The burst command is applied only to that
source.
@end table @end table
If no mask or masked address arguments are provided, every source will If no mask or masked address arguments are provided, every source will
@@ -3248,6 +3313,12 @@ In the first case, the two out of ten sampling will only be applied to
sources whose IPv4 addresses are of the form @code{1.2.x.y}, where x and y sources whose IPv4 addresses are of the form @code{1.2.x.y}, where x and y
are arbitrary. In the second case, the sampling will be applied to sources are arbitrary. In the second case, the sampling will be applied to sources
whose IPv6 addresses have first 48 bits equal to @code{2001:db8:789a}. whose IPv6 addresses have first 48 bits equal to @code{2001:db8:789a}.
Example of the three-argument form of the command is
@example
burst 2/10 foo.bar.com
@end example
@c }}} @c }}}
@c {{{ clients @c {{{ clients
@node clients command @node clients command
@@ -3352,12 +3423,7 @@ periodically purged. An example of how to do this is shown below.
@example @example
% mv /var/log/chrony/measurements.log /var/log/chrony/measurements1.log % mv /var/log/chrony/measurements.log /var/log/chrony/measurements1.log
% chronyc % chronyc -a cyclelogs
chronyc> password aardvark
200 OK
chronyc> cyclelogs
200 OK
chronyc> exit
% ls -l /var/log/chrony % ls -l /var/log/chrony
-rw-r--r-- 1 root root 0 Jun 8 18:17 measurements.log -rw-r--r-- 1 root root 0 Jun 8 18:17 measurements.log
-rw-r--r-- 1 root root 12345 Jun 8 18:17 measurements1.log -rw-r--r-- 1 root root 12345 Jun 8 18:17 measurements1.log
@@ -3778,15 +3844,17 @@ the @code{offline} command being used, @code{chronyd} would assume that the
source had failed and would attempt to pick another synchronisation source had failed and would attempt to pick another synchronisation
source. source.
There are three forms of the @code{offline} command. The first form is a There are four forms of the @code{offline} command. The first form is a
wildcard, meaning all sources. The second form allows a IP address mask wildcard, meaning all sources. The second form allows an IP address mask
and a masked address to be specified. The third form uses the CIDR and a masked address to be specified. The third form uses the CIDR
notation. These forms are illustrated below. notation. The fourth form uses an IP address or a hostname. These forms are
illustrated below.
@example @example
offline offline
offline 255.255.255.0/1.2.3.0 offline 255.255.255.0/1.2.3.0
offline 2001:db8:789a::/48 offline 2001:db8:789a::/48
offline foo.bar.com
@end example @end example
The second form means that the @code{offline} command is to be applied The second form means that the @code{offline} command is to be applied
@@ -3794,7 +3862,8 @@ to any source whose IPv4 address is in the @code{1.2.3} subnet. (The host's
address is logically and-ed with the mask, and if the result matches the address is logically and-ed with the mask, and if the result matches the
masked-address the host is processed). The third form means that the masked-address the host is processed). The third form means that the
command is to be applied to all sources whose IPv6 addresses have first command is to be applied to all sources whose IPv6 addresses have first
48 bits equal to @code{2001:db8:789a}. 48 bits equal to @code{2001:db8:789a}. The fourth form means that the command
is to be applied only to that one source.
The wildcard form of the address is actually equivalent to The wildcard form of the address is actually equivalent to
@@ -3842,6 +3911,9 @@ The password can be encoded as a string of characters not containing a space
with optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:} with optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:}
prefix. It has to match @code{chronyd's} currently defined command key prefix. It has to match @code{chronyd's} currently defined command key
(@pxref{commandkey directive}). (@pxref{commandkey directive}).
The password command is run automatically on start if @code{chronyc} was
started with the `-a' option.
@c }}} @c }}}
@c {{{ polltarget @c {{{ polltarget
@node polltarget command @node polltarget command
@@ -3962,8 +4034,6 @@ chronyc (@pxref{manual command}).
It should be noted that the computer's sense of time will only be as It should be noted that the computer's sense of time will only be as
accurate as the reference you use for providing this input (e.g. your accurate as the reference you use for providing this input (e.g. your
watch), as well as how well you can time the press of the return key. watch), as well as how well you can time the press of the return key.
When inputting time to an isolated network, I have a battery operated
alarm clock that is synchronised to the Rugby MSF time signal in the UK.
Providing your computer's time zone is set up properly, you will be able Providing your computer's time zone is set up properly, you will be able
to enter a local time (rather than UTC). to enter a local time (rather than UTC).
@@ -4026,12 +4096,15 @@ reference clock.
@item S @item S
This column indicates the state of the sources. @code{*} indicates the This column indicates the state of the sources. @code{*} indicates the
source to which @code{chronyd} is current synchronised. @code{+} indicates source to which @code{chronyd} is currently synchronised. @code{+}
other acceptable sources. @code{?} indicates sources to which indicates acceptable sources which are combined with the selected
connectivity has been lost. @code{x} indicates a clock which @code{chronyd} source. @code{-} indicates acceptable sources which are excluded by
the combining algorithm. @code{?} indicates sources to which
connectivity has been lost or whose packets don't pass all tests.
@code{x} indicates a clock which @code{chronyd}
thinks is is a falseticker (i.e. its time is inconsistent with a thinks is is a falseticker (i.e. its time is inconsistent with a
majority of other sources). @code{~} indicates a source whose time majority of other sources). @code{~} indicates a source whose time
appears to have too much variability. The @code{~} condition is also appears to have too much variability. The @code{?} condition is also
shown at start-up, until at least 3 samples have been gathered from it. shown at start-up, until at least 3 samples have been gathered from it.
@item Name/IP address @item Name/IP address
@@ -4188,7 +4261,7 @@ the computer is currently synchronised. If this is @code{127.127.1.1}
it means the computer is not synchronised to any external source and it means the computer is not synchronised to any external source and
that you have the `local' mode operating (via the @code{local} command that you have the `local' mode operating (via the @code{local} command
in @code{chronyc} (@pxref{local command}), or the @code{local} directive in @code{chronyc} (@pxref{local command}), or the @code{local} directive
in the @file{/etc/chrony.conf} file (@pxref{local directive})). in the @file{@SYSCONFDIR@/chrony.conf} file (@pxref{local directive})).
@item Stratum @item Stratum
The stratum indicates how many hops away from a computer with an The stratum indicates how many hops away from a computer with an
@@ -4233,10 +4306,8 @@ ppm (parts per million). For example, a value of 1ppm would mean that
when the system's clock thinks it has advanced 1 second, it has actually when the system's clock thinks it has advanced 1 second, it has actually
advanced by 1.000001 seconds relative to true time. advanced by 1.000001 seconds relative to true time.
As you can see in the example, the clock in the computer I developed As you can see in the example, the clock in the computer is not a very
@code{chrony} on is not a very good one - it gains about 30 seconds per good one - it gains about 30 seconds per day!
day! This was the reason I started to write @code{chrony} in the first
place.
@item Residual freq @item Residual freq
This shows the `residual frequency' for the currently selected reference This shows the `residual frequency' for the currently selected reference

View File

@@ -12,7 +12,7 @@ clocks.
\fBchronyc\fR is a command-line interface program which can be used to \fBchronyc\fR is a command-line interface program which can be used to
monitor \fIchronyd\fR's performance and to change various operating monitor \fIchronyd\fR's performance and to change various operating
parateters whilst it is running. parameters whilst it is running.
.SH USAGE .SH USAGE
A detailed description of all commands supported by \fBchronyc\fR is available A detailed description of all commands supported by \fBchronyc\fR is available
@@ -42,6 +42,16 @@ resolve hostnames only to IPv6 addresses
allow multiple commands to be specified on the command line. Each argument 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
This option can be used to specify an alternate location for the
configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR). The configuration file is
needed for the \fB-a\fR option.
.TP
\fB\-a\fR
With this option chronyc will try to authenticate automatically on
start. It will read the configuration file, read the command key from the
keyfile and run the authhash and password commands.
.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
interactively. interactively.

View File

@@ -21,13 +21,13 @@ gains or loses time, and compensates for this.
.SH USAGE .SH USAGE
\fBchronyd\fR is usually started at boot-time and requires superuser \fBchronyd\fR is usually started at boot-time and requires superuser
priviliges. privileges.
If \fBchronyd\fR has been installed to its default location If \fBchronyd\fR has been installed to its default location
\fI/usr/local/sbin/chronyd\fR, starting it is simply a matter of entering the \fI@SBINDIR@/chronyd\fR, starting it is simply a matter of entering the
command: command:
\fI/usr/local/sbin/chronyd\fR \fI@SBINDIR@/chronyd\fR
Information messages and warnings will be logged to syslog. Information messages and warnings will be logged to syslog.
@@ -56,7 +56,7 @@ to syslog.
.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 can be used to specify an alternate location for the
configuration file (default \fI/etc/chrony.conf\fR). configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR).
.TP .TP
.B \-r .B \-r
This option will reload sample histories for each of the servers being used. This option will reload sample histories for each of the servers being used.
@@ -69,6 +69,12 @@ systems where the kernel can maintain clock compensation whilst not under
On systems where this is not the case, e.g. Solaris and SunOS the option On systems where this is not the case, e.g. Solaris and SunOS the option
should not be used. should not be used.
.TP .TP
.B \-R
When this option is used, the \fIinitstepslew\fR directive and the
\fImakestep\fR directive used with a positive limit will be ignored. This
option is useful when restarting \fBchronyd\fR and can be used in conjuction
with the \fB-r\fR option.
.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. This is analogous to supplying the \fI-s\fR flag to the clock. This is analogous to supplying the \fI-s\fR flag to the
@@ -100,13 +106,13 @@ user. So far, it works only on Linux when compiled with capabilities support.
This option displays \fBchronyd\fR's version number to the terminal and exits This option displays \fBchronyd\fR's version number to the terminal and exits
.TP .TP
.B \-4 .B \-4
Resolve hostnames only to IPv4 addresses. Resolve hostnames only to IPv4 addresses and create only IPv4 sockets.
.TP .TP
.B \-6 .B \-6
Resolve hostnames only to IPv6 addresses. Resolve hostnames only to IPv6 addresses and create only IPv6 sockets.
.SH FILES .SH FILES
\fI/etc/chrony.conf\fR \fI@SYSCONFDIR@/chrony.conf\fR
.SH BUGS .SH BUGS
To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
@@ -119,8 +125,7 @@ from \fIhttp://go.to/chrony\fR
.BR chrony(1), .BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chrony.conf(5), .BR chrony.conf(5),
.BR clock(8), .BR hwclock(8),
.BR xntpd(8),
.BR ntpd(8) .BR ntpd(8)
.SH AUTHOR .SH AUTHOR

481
client.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2012 * Copyright (C) Miroslav Lichvar 2009-2013
* *
* 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
@@ -48,12 +48,6 @@
#endif #endif
#endif #endif
#ifdef HAS_STDINT_H
#include <stdint.h>
#elif defined(HAS_INTTYPES_H)
#include <inttypes.h>
#endif
/* ================================================== */ /* ================================================== */
union sockaddr_in46 { union sockaddr_in46 {
@@ -127,7 +121,7 @@ read_line(void)
} }
return( line ); return( line );
#else #else
printf(prompt); printf("%s", prompt);
#endif #endif
} }
if (fgets(line, sizeof(line), stdin)) { if (fgets(line, sizeof(line), stdin)) {
@@ -182,8 +176,6 @@ open_io(const char *hostname, int port)
perror("Can't create socket"); perror("Can't create socket");
exit(1); exit(1);
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -239,7 +231,6 @@ read_mask_address(char *line, IPAddr *mask, IPAddr *address)
char *p, *q; char *p, *q;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
mask->family = address->family = IPADDR_UNSPEC; mask->family = address->family = IPADDR_UNSPEC;
return 1; return 1;
@@ -249,8 +240,6 @@ read_mask_address(char *line, IPAddr *mask, IPAddr *address)
*q++ = 0; *q++ = 0;
if (UTI_StringToIP(p, mask)) { if (UTI_StringToIP(p, mask)) {
p = q; p = q;
while (*q && !isspace((unsigned char)*q)) q++;
*q = 0;
if (UTI_StringToIP(p, address)) { if (UTI_StringToIP(p, address)) {
if (address->family == mask->family) if (address->family == mask->family)
return 1; return 1;
@@ -261,9 +250,12 @@ read_mask_address(char *line, IPAddr *mask, IPAddr *address)
} }
} }
} else { } else {
if (UTI_StringToIP(p, address)) { if (DNS_Name2IPAddress(p, address) == DNS_Success) {
bits_to_mask(-1, address->family, mask); bits_to_mask(-1, address->family, mask);
return 1; return 1;
} else {
fprintf(stderr, "Could not get address for hostname\n");
return 0;
} }
} }
} }
@@ -320,10 +312,13 @@ process_cmd_online(CMD_Request *msg, char *line)
static int static int
read_address_integer(char *line, IPAddr *address, int *value) read_address_integer(char *line, IPAddr *address, int *value)
{ {
char hostname[2048]; char *hostname;
int ok = 0; int ok = 0;
if (sscanf(line, "%2047s %d", hostname, value) != 2) { hostname = line;
line = CPS_SplitWord(line);
if (sscanf(line, "%d", value) != 1) {
fprintf(stderr, "Invalid syntax for address value\n"); fprintf(stderr, "Invalid syntax for address value\n");
ok = 0; ok = 0;
} else { } else {
@@ -345,10 +340,13 @@ read_address_integer(char *line, IPAddr *address, int *value)
static int static int
read_address_double(char *line, IPAddr *address, double *value) read_address_double(char *line, IPAddr *address, double *value)
{ {
char hostname[2048]; char *hostname;
int ok = 0; int ok = 0;
if (sscanf(line, "%2047s %lf", hostname, value) != 2) { hostname = line;
line = CPS_SplitWord(line);
if (sscanf(line, "%lf", value) != 1) {
fprintf(stderr, "Invalid syntax for address value\n"); fprintf(stderr, "Invalid syntax for address value\n");
ok = 0; ok = 0;
} else { } else {
@@ -545,6 +543,7 @@ static void
process_cmd_dump(CMD_Request *msg, char *line) process_cmd_dump(CMD_Request *msg, char *line)
{ {
msg->command = htons(REQ_DUMP); msg->command = htons(REQ_DUMP);
msg->data.dump.pad = htonl(0);
} }
/* ================================================== */ /* ================================================== */
@@ -577,23 +576,27 @@ static int
process_cmd_burst(CMD_Request *msg, char *line) process_cmd_burst(CMD_Request *msg, char *line)
{ {
int n_good_samples, n_total_samples; int n_good_samples, n_total_samples;
int n_parsed; char *s1, *s2;
char s[101];
IPAddr address, mask; IPAddr address, mask;
n_parsed = sscanf(line, "%d/%d %100s", &n_good_samples, &n_total_samples, s); s1 = line;
s2 = CPS_SplitWord(s1);
CPS_SplitWord(s2);
if (sscanf(s1, "%d/%d", &n_good_samples, &n_total_samples) != 2) {
fprintf(stderr, "Invalid syntax for burst command\n");
return 0;
}
mask.family = address.family = IPADDR_UNSPEC;
if (*s2 && !read_mask_address(s2, &mask, &address)) {
return 0;
}
msg->command = htons(REQ_BURST); msg->command = htons(REQ_BURST);
msg->data.burst.n_good_samples = ntohl(n_good_samples); msg->data.burst.n_good_samples = ntohl(n_good_samples);
msg->data.burst.n_total_samples = ntohl(n_total_samples); msg->data.burst.n_total_samples = ntohl(n_total_samples);
mask.family = address.family = IPADDR_UNSPEC;
if (n_parsed < 2 || (n_parsed == 3 && !read_mask_address(s, &mask, &address))) {
fprintf(stderr, "Invalid syntax for burst command\n");
return 0;
}
UTI_IPHostToNetwork(&mask, &msg->data.burst.mask); UTI_IPHostToNetwork(&mask, &msg->data.burst.mask);
UTI_IPHostToNetwork(&address, &msg->data.burst.address); UTI_IPHostToNetwork(&address, &msg->data.burst.address);
@@ -609,12 +612,12 @@ process_cmd_local(CMD_Request *msg, const char *line)
int stratum; int stratum;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
return 0; return 0;
} else if (!strncmp(p, "off", 3)) { } else if (!strcmp(p, "off")) {
msg->data.local.on_off = htonl(0); msg->data.local.on_off = htonl(0);
msg->data.local.stratum = htonl(0);
} else if (sscanf(p, "stratum%d", &stratum) == 1) { } else if (sscanf(p, "stratum%d", &stratum) == 1) {
msg->data.local.on_off = htonl(1); msg->data.local.on_off = htonl(1);
msg->data.local.stratum = htonl(stratum); msg->data.local.stratum = htonl(stratum);
@@ -635,15 +638,14 @@ process_cmd_manual(CMD_Request *msg, const char *line)
const char *p; const char *p;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
return 0; return 0;
} else if (!strncmp(p, "off", 3)) { } else if (!strcmp(p, "off")) {
msg->data.manual.option = htonl(0); msg->data.manual.option = htonl(0);
} else if (!strncmp(p, "on", 2)) { } else if (!strcmp(p, "on")) {
msg->data.manual.option = htonl(1); msg->data.manual.option = htonl(1);
} else if (!strncmp(p, "reset", 5)) { } else if (!strcmp(p, "reset")) {
msg->data.manual.option = htonl(2); msg->data.manual.option = htonl(2);
} else { } else {
return 0; return 0;
@@ -660,10 +662,9 @@ parse_allow_deny(CMD_Request *msg, char *line)
{ {
unsigned long a, b, c, d, n; unsigned long a, b, c, d, n;
IPAddr ip; IPAddr ip;
char *p, *q; char *p;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) p++;
if (!*p) { if (!*p) {
/* blank line - applies to all addresses */ /* blank line - applies to all addresses */
ip.family = IPADDR_UNSPEC; ip.family = IPADDR_UNSPEC;
@@ -679,11 +680,6 @@ parse_allow_deny(CMD_Request *msg, char *line)
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) { (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {
/* Try to parse as the name of a machine */ /* Try to parse as the name of a machine */
q = p;
while (*q) {
if (*q == '\n') *q = 0;
q++;
}
if (DNS_Name2IPAddress(p, &ip) != DNS_Success) { if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
fprintf(stderr, "Could not read address\n"); fprintf(stderr, "Could not read address\n");
return 0; return 0;
@@ -842,9 +838,8 @@ accheck_getaddr(char *line, IPAddr *addr)
{ {
unsigned long a, b, c, d; unsigned long a, b, c, d;
IPAddr ip; IPAddr ip;
char *p, *q; char *p;
p = line; p = line;
while (*p && isspace(*p)) p++;
if (!*p) { if (!*p) {
return 0; return 0;
} else { } else {
@@ -853,11 +848,6 @@ accheck_getaddr(char *line, IPAddr *addr)
addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d; addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
return 1; return 1;
} else { } else {
q = p;
while (*q) {
if (*q == '\n') *q = 0;
q++;
}
if (DNS_Name2IPAddress(p, &ip) != DNS_Success) { if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
return 0; return 0;
} else { } else {
@@ -932,7 +922,6 @@ cvt_to_sec_usec(double x, long *sec, long *usec) {
*sec = s; *sec = s;
*usec = us; *usec = us;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1069,13 +1058,15 @@ process_cmd_add_peer(CMD_Request *msg, char *line)
static int static int
process_cmd_delete(CMD_Request *msg, char *line) process_cmd_delete(CMD_Request *msg, char *line)
{ {
char hostname[2048]; char *hostname;
int ok = 0; int ok = 0;
IPAddr address; IPAddr address;
msg->command = htons(REQ_DEL_SOURCE); msg->command = htons(REQ_DEL_SOURCE);
hostname = line;
CPS_SplitWord(line);
if (sscanf(line, "%2047s", hostname) != 1) { if (!*hostname) {
fprintf(stderr, "Invalid syntax for address\n"); fprintf(stderr, "Invalid syntax for address\n");
ok = 0; ok = 0;
} else { } else {
@@ -1103,7 +1094,7 @@ static int auth_hash_id;
static int static int
process_cmd_password(CMD_Request *msg, char *line) process_cmd_password(CMD_Request *msg, char *line)
{ {
char *p, *q; char *p;
struct timeval now; struct timeval now;
int i, len; int i, len;
@@ -1116,13 +1107,6 @@ process_cmd_password(CMD_Request *msg, char *line)
} }
p = line; p = line;
while (*p && isspace((unsigned char)*p))
p++;
/* Get rid of trailing newline */
for (q=p; *q; q++) {
if (isspace((unsigned char)*q)) *q = 0;
}
if (!*p) { if (!*p) {
/* blank line, prompt for password */ /* blank line, prompt for password */
@@ -1669,8 +1653,7 @@ static int
check_for_verbose_flag(char *line) check_for_verbose_flag(char *line)
{ {
char *p = line; char *p = line;
while (*p && isspace((unsigned char)*p)) p++; if (!strcmp(p, "-v")) {
if (!strncmp(p, "-v", 2)) {
return 1; return 1;
} else { } else {
return 0; return 0;
@@ -1704,8 +1687,8 @@ process_cmd_sources(char *line)
if (verbose) { if (verbose) {
printf("\n"); printf("\n");
printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n"); printf(" .-- Source mode '^' = server, '=' = peer, '#' = local clock.\n");
printf(" / .- Source state '*' = current synced, '+' = OK for sync, '?' = unreachable,\n"); printf(" / .- Source state '*' = current synced, '+' = combined , '-' = not combined,\n");
printf("| / 'x' = time may be in error, '~' = time is too variable.\n"); printf("| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable.\n");
printf("|| .- xxxx [ yyyy ] +/- zzzz\n"); printf("|| .- xxxx [ yyyy ] +/- zzzz\n");
printf("|| / xxxx = adjusted offset,\n"); printf("|| / xxxx = adjusted offset,\n");
printf("|| Log2(Polling interval) -. | yyyy = measured offset,\n"); printf("|| Log2(Polling interval) -. | yyyy = measured offset,\n");
@@ -1764,7 +1747,7 @@ process_cmd_sources(char *line)
printf("~"); break; printf("~"); break;
case RPY_SD_ST_CANDIDATE: case RPY_SD_ST_CANDIDATE:
printf("+"); break; printf("+"); break;
case RPY_SD_ST_OUTLYER: case RPY_SD_ST_OUTLIER:
printf("-"); break; printf("-"); break;
default: default:
printf(" "); printf(" ");
@@ -2373,7 +2356,7 @@ process_cmd_settime(char *line)
request.command = htons(REQ_SETTIME); request.command = htons(REQ_SETTIME);
if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) { if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
offset_cs = ntohl(reply.data.manual_timestamp.centiseconds); offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
offset = 0.01 * (double) offset_cs; offset = 0.01 * (double)(int32_t)offset_cs;
dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm); dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm); new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
printf("Clock was %.2f seconds fast. Frequency change = %.2fppm, new frequency = %.2fppm\n", printf("Clock was %.2f seconds fast. Frequency change = %.2fppm, new frequency = %.2fppm\n",
@@ -2505,15 +2488,15 @@ process_cmd_waitsync(char *line)
static int static int
process_cmd_dns(const char *line) process_cmd_dns(const char *line)
{ {
if (!strncmp(line, "-46", 3)) { if (!strcmp(line, "-46")) {
DNS_SetAddressFamily(IPADDR_UNSPEC); DNS_SetAddressFamily(IPADDR_UNSPEC);
} else if (!strncmp(line, "-4", 2)) { } else if (!strcmp(line, "-4")) {
DNS_SetAddressFamily(IPADDR_INET4); DNS_SetAddressFamily(IPADDR_INET4);
} else if (!strncmp(line, "-6", 2)) { } else if (!strcmp(line, "-6")) {
DNS_SetAddressFamily(IPADDR_INET6); DNS_SetAddressFamily(IPADDR_INET6);
} else if (!strncmp(line, "-n", 2)) { } else if (!strcmp(line, "-n")) {
no_dns = 1; no_dns = 1;
} else if (!strncmp(line, "+n", 2)) { } else if (!strcmp(line, "+n")) {
no_dns = 0; no_dns = 0;
} else { } else {
fprintf(stderr, "Unrecognized dns command\n"); fprintf(stderr, "Unrecognized dns command\n");
@@ -2527,12 +2510,13 @@ process_cmd_dns(const char *line)
static int static int
process_cmd_authhash(const char *line) process_cmd_authhash(const char *line)
{ {
char hash_name[50]; const char *hash_name;
int new_hash_id; int new_hash_id;
assert(auth_hash_id >= 0); assert(auth_hash_id >= 0);
hash_name = line;
if (sscanf(line, "%49s", hash_name) != 1) { if (!*hash_name) {
fprintf(stderr, "Could not parse hash name\n"); fprintf(stderr, "Could not parse hash name\n");
return 0; return 0;
} }
@@ -2585,7 +2569,7 @@ process_cmd_retries(const char *line)
static int static int
process_line(char *line, int *quit) process_line(char *line, int *quit)
{ {
char *p; char *command;
int do_normal_submit; int do_normal_submit;
int ret; int ret;
CMD_Request tx_message; CMD_Request tx_message;
@@ -2596,142 +2580,155 @@ process_line(char *line, int *quit)
do_normal_submit = 1; do_normal_submit = 1;
/* Check for line being blank */ CPS_NormalizeLine(line);
p = line;
while (*p && isspace((unsigned char)*p)) p++; if (!*line) {
if (!*p) {
fflush(stderr); fflush(stderr);
fflush(stdout); fflush(stdout);
return 1; return 1;
}; };
if (!strncmp(p, "offline", 7)) { command = line;
do_normal_submit = process_cmd_offline(&tx_message, p+7); line = CPS_SplitWord(line);
} else if (!strncmp(p, "online", 6)) {
do_normal_submit = process_cmd_online(&tx_message, p+6); if (!strcmp(command, "accheck")) {
} else if (!strncmp(p, "burst", 5)) { do_normal_submit = process_cmd_accheck(&tx_message, line);
do_normal_submit = process_cmd_burst(&tx_message, p+5); } else if (!strcmp(command, "activity")) {
} else if (!strncmp(p, "password", 8)) {
do_normal_submit = process_cmd_password(&tx_message, p+8);
} else if (!strncmp(p, "minpoll", 7)) {
do_normal_submit = process_cmd_minpoll(&tx_message, p+7);
} else if (!strncmp(p, "maxpoll", 7)) {
do_normal_submit = process_cmd_maxpoll(&tx_message, p+7);
} else if (!strncmp(p, "dump", 4)) {
process_cmd_dump(&tx_message, p+4);
} else if (!strncmp(p, "maxdelaydevratio", 16)) {
do_normal_submit = process_cmd_maxdelaydevratio(&tx_message, p+16);
} else if (!strncmp(p, "maxdelayratio", 13)) {
do_normal_submit = process_cmd_maxdelayratio(&tx_message, p+13);
} else if (!strncmp(p, "maxdelay", 8)) {
do_normal_submit = process_cmd_maxdelay(&tx_message, p+8);
} else if (!strncmp(p, "maxupdateskew", 13)) {
do_normal_submit = process_cmd_maxupdateskew(&tx_message, p+13);
} else if (!strncmp(p, "minstratum", 10)) {
do_normal_submit = process_cmd_minstratum(&tx_message, p+10);
} else if (!strncmp(p, "polltarget", 10)) {
do_normal_submit = process_cmd_polltarget(&tx_message, p+10);
} else if (!strncmp(p, "settime", 7)) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_settime(p+7); ret = process_cmd_activity(line);
} else if (!strncmp(p, "local", 5)) { } else if (!strcmp(command, "add") && !strncmp(line, "peer", 4)) {
do_normal_submit = process_cmd_local(&tx_message, p+5); do_normal_submit = process_cmd_add_peer(&tx_message, CPS_SplitWord(line));
} else if (!strncmp(p, "manual list", 11)) { } else if (!strcmp(command, "add") && !strncmp(line, "server", 6)) {
do_normal_submit = process_cmd_add_server(&tx_message, CPS_SplitWord(line));
} else if (!strcmp(command, "allow")) {
if (!strncmp(line, "all", 3)) {
do_normal_submit = process_cmd_allowall(&tx_message, CPS_SplitWord(line));
} else {
do_normal_submit = process_cmd_allow(&tx_message, line);
}
} else if (!strcmp(command, "authhash")) {
ret = process_cmd_authhash(line);
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_manual_list(p+11); } else if (!strcmp(command, "burst")) {
} else if (!strncmp(p, "manual delete", 13)) { do_normal_submit = process_cmd_burst(&tx_message, line);
do_normal_submit = process_cmd_manual_delete(&tx_message, p+13); } else if (!strcmp(command, "clients")) {
} else if (!strncmp(p, "manual", 6)) { ret = process_cmd_clients(line);
do_normal_submit = process_cmd_manual(&tx_message, p+6);
} else if (!strncmp(p, "sourcestats", 11)) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_sourcestats(p+11); } else if (!strcmp(command, "cmdaccheck")) {
} else if (!strncmp(p, "sources", 7)) { do_normal_submit = process_cmd_cmdaccheck(&tx_message, line);
} else if (!strcmp(command, "cmdallow")) {
if (!strncmp(line, "all", 3)) {
do_normal_submit = process_cmd_cmdallowall(&tx_message, CPS_SplitWord(line));
} else {
do_normal_submit = process_cmd_cmdallow(&tx_message, line);
}
} else if (!strcmp(command, "cmddeny")) {
if (!strncmp(line, "all", 3)) {
line = CPS_SplitWord(line);
do_normal_submit = process_cmd_cmddenyall(&tx_message, line);
} else {
do_normal_submit = process_cmd_cmddeny(&tx_message, line);
}
} else if (!strcmp(command, "cyclelogs")) {
process_cmd_cyclelogs(&tx_message, line);
} else if (!strcmp(command, "delete")) {
do_normal_submit = process_cmd_delete(&tx_message, line);
} else if (!strcmp(command, "deny")) {
if (!strncmp(line, "all", 3)) {
do_normal_submit = process_cmd_denyall(&tx_message, CPS_SplitWord(line));
} else {
do_normal_submit = process_cmd_deny(&tx_message, line);
}
} else if (!strcmp(command, "dfreq")) {
process_cmd_dfreq(&tx_message, line);
} else if (!strcmp(command, "dns")) {
ret = process_cmd_dns(line);
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_sources(p+7); } else if (!strcmp(command, "doffset")) {
} else if (!strncmp(p, "rekey", 5)) { process_cmd_doffset(&tx_message, line);
process_cmd_rekey(&tx_message, p+5); } else if (!strcmp(command, "dump")) {
} else if (!strncmp(p, "allow all", 9)) { process_cmd_dump(&tx_message, line);
do_normal_submit = process_cmd_allowall(&tx_message, p+9); } else if (!strcmp(command, "exit")) {
} else if (!strncmp(p, "allow", 5)) {
do_normal_submit = process_cmd_allow(&tx_message, p+5);
} else if (!strncmp(p, "deny all", 8)) {
do_normal_submit = process_cmd_denyall(&tx_message, p+8);
} else if (!strncmp(p, "deny", 4)) {
do_normal_submit = process_cmd_deny(&tx_message, p+4);
} else if (!strncmp(p, "cmdallow all", 12)) {
do_normal_submit = process_cmd_cmdallowall(&tx_message, p+12);
} else if (!strncmp(p, "cmdallow", 8)) {
do_normal_submit = process_cmd_cmdallow(&tx_message, p+8);
} else if (!strncmp(p, "cmddeny all", 11)) {
do_normal_submit = process_cmd_cmddenyall(&tx_message, p+11);
} else if (!strncmp(p, "cmddeny", 7)) {
do_normal_submit = process_cmd_cmddeny(&tx_message, p+7);
} else if (!strncmp(p, "accheck", 7)) {
do_normal_submit = process_cmd_accheck(&tx_message, p+7);
} else if (!strncmp(p, "cmdaccheck", 10)) {
do_normal_submit = process_cmd_cmdaccheck(&tx_message, p+10);
} else if (!strncmp(p, "add server", 10)) {
do_normal_submit = process_cmd_add_server(&tx_message, p+10);
} else if (!strncmp(p, "add peer", 8)) {
do_normal_submit = process_cmd_add_peer(&tx_message, p+8);
} else if (!strncmp(p, "delete", 6)) {
do_normal_submit = process_cmd_delete(&tx_message, p+6);
} else if (!strncmp(p, "writertc", 7)) {
process_cmd_writertc(&tx_message, p+7);
} else if (!strncmp(p, "rtcdata", 7)) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_rtcreport(p); *quit = 1;
} else if (!strncmp(p, "trimrtc", 7)) { ret = 1;
process_cmd_trimrtc(&tx_message, p); } else if (!strcmp(command, "help")) {
} else if (!strncmp(p, "cyclelogs", 9)) {
process_cmd_cyclelogs(&tx_message, p);
} else if (!strncmp(p, "dfreq", 5)) {
process_cmd_dfreq(&tx_message, p+5);
} else if (!strncmp(p, "doffset", 7)) {
process_cmd_doffset(&tx_message, p+7);
} else if (!strncmp(p, "tracking", 8)) {
ret = process_cmd_tracking(p+8);
do_normal_submit = 0;
} else if (!strncmp(p, "clients", 7)) {
ret = process_cmd_clients(p+7);
do_normal_submit = 0;
} else if (!strncmp(p, "makestep", 8)) {
process_cmd_makestep(&tx_message, p+8);
} else if (!strncmp(p, "activity", 8)) {
ret = process_cmd_activity(p+8);
do_normal_submit = 0;
} else if (!strncmp(p, "reselectdist", 12)) {
do_normal_submit = process_cmd_reselectdist(&tx_message, p+12);
} else if (!strncmp(p, "reselect", 8)) {
process_cmd_reselect(&tx_message, p+8);
} else if (!strncmp(p, "waitsync", 8)) {
ret = process_cmd_waitsync(p+8);
do_normal_submit = 0;
} else if (!strncmp(p, "authhash", 8)) {
ret = process_cmd_authhash(p+8);
do_normal_submit = 0;
} else if (!strncmp(p, "dns ", 4)) {
ret = process_cmd_dns(p+4);
do_normal_submit = 0;
} else if (!strncmp(p, "timeout", 7)) {
ret = process_cmd_timeout(p+7);
do_normal_submit = 0;
} else if (!strncmp(p, "retries", 7)) {
ret = process_cmd_retries(p+7);
do_normal_submit = 0;
} else if (!strncmp(p, "help", 4)) {
do_normal_submit = 0; do_normal_submit = 0;
give_help(); give_help();
ret = 1; ret = 1;
} else if (!strncmp(p, "quit", 4)) { } else if (!strcmp(command, "local")) {
do_normal_submit = process_cmd_local(&tx_message, line);
} else if (!strcmp(command, "makestep")) {
process_cmd_makestep(&tx_message, line);
} else if (!strcmp(command, "manual")) {
if (!strncmp(line, "list", 4)) {
do_normal_submit = 0;
ret = process_cmd_manual_list(CPS_SplitWord(line));
} else if (!strncmp(line, "delete", 6)) {
do_normal_submit = process_cmd_manual_delete(&tx_message, CPS_SplitWord(line));
} else {
do_normal_submit = process_cmd_manual(&tx_message, line);
}
} else if (!strcmp(command, "maxdelay")) {
do_normal_submit = process_cmd_maxdelay(&tx_message, line);
} else if (!strcmp(command, "maxdelaydevratio")) {
do_normal_submit = process_cmd_maxdelaydevratio(&tx_message, line);
} else if (!strcmp(command, "maxdelayratio")) {
do_normal_submit = process_cmd_maxdelayratio(&tx_message, line);
} else if (!strcmp(command, "maxpoll")) {
do_normal_submit = process_cmd_maxpoll(&tx_message, line);
} else if (!strcmp(command, "maxupdateskew")) {
do_normal_submit = process_cmd_maxupdateskew(&tx_message, line);
} else if (!strcmp(command, "minpoll")) {
do_normal_submit = process_cmd_minpoll(&tx_message, line);
} else if (!strcmp(command, "minstratum")) {
do_normal_submit = process_cmd_minstratum(&tx_message, line);
} else if (!strcmp(command, "offline")) {
do_normal_submit = process_cmd_offline(&tx_message, line);
} else if (!strcmp(command, "online")) {
do_normal_submit = process_cmd_online(&tx_message, line);
} else if (!strcmp(command, "password")) {
do_normal_submit = process_cmd_password(&tx_message, line);
} else if (!strcmp(command, "polltarget")) {
do_normal_submit = process_cmd_polltarget(&tx_message, line);
} else if (!strcmp(command, "quit")) {
do_normal_submit = 0; do_normal_submit = 0;
*quit = 1; *quit = 1;
ret = 1; ret = 1;
} else if (!strncmp(p, "exit", 4)) { } else if (!strcmp(command, "rekey")) {
process_cmd_rekey(&tx_message, line);
} else if (!strcmp(command, "reselect")) {
process_cmd_reselect(&tx_message, line);
} else if (!strcmp(command, "reselectdist")) {
do_normal_submit = process_cmd_reselectdist(&tx_message, line);
} else if (!strcmp(command, "retries")) {
ret = process_cmd_retries(line);
do_normal_submit = 0; do_normal_submit = 0;
*quit = 1; } else if (!strcmp(command, "rtcdata")) {
ret = 1; do_normal_submit = 0;
ret = process_cmd_rtcreport(line);
} else if (!strcmp(command, "settime")) {
do_normal_submit = 0;
ret = process_cmd_settime(line);
} else if (!strcmp(command, "sources")) {
do_normal_submit = 0;
ret = process_cmd_sources(line);
} else if (!strcmp(command, "sourcestats")) {
do_normal_submit = 0;
ret = process_cmd_sourcestats(line);
} else if (!strcmp(command, "timeout")) {
ret = process_cmd_timeout(line);
do_normal_submit = 0;
} else if (!strcmp(command, "tracking")) {
ret = process_cmd_tracking(line);
do_normal_submit = 0;
} else if (!strcmp(command, "trimrtc")) {
process_cmd_trimrtc(&tx_message, line);
} else if (!strcmp(command, "waitsync")) {
ret = process_cmd_waitsync(line);
do_normal_submit = 0;
} else if (!strcmp(command, "writertc")) {
process_cmd_writertc(&tx_message, line);
} else { } else {
fprintf(stderr, "Unrecognized command\n"); fprintf(stderr, "Unrecognized command\n");
do_normal_submit = 0; do_normal_submit = 0;
@@ -2747,6 +2744,77 @@ process_line(char *line, int *quit)
/* ================================================== */ /* ================================================== */
static int
authenticate_from_config(const char *filename)
{
CMD_Request tx_message;
CMD_Reply rx_message;
char line[2048], keyfile[2048], *command, *arg, *password;
const char *hashname;
unsigned long key_id = 0, key_id2 = -1;
int ret;
FILE *in;
in = fopen(filename, "r");
if (!in) {
fprintf(stderr, "Could not open file %s\n", filename);
return 0;
}
*keyfile = '\0';
while (fgets(line, sizeof (line), in)) {
CPS_NormalizeLine(line);
command = line;
arg = CPS_SplitWord(line);
if (!strcasecmp(command, "keyfile")) {
snprintf(keyfile, sizeof (keyfile), "%s", arg);
} else if (!strcasecmp(command, "commandkey")) {
if (sscanf(arg, "%lu", &key_id) != 1)
key_id = -1;
}
}
fclose(in);
if (!*keyfile || key_id == -1) {
fprintf(stderr, "Could not read keyfile or commandkey in file %s\n", filename);
return 0;
}
in = fopen(keyfile, "r");
if (!in) {
fprintf(stderr, "Could not open keyfile %s\n", filename);
return 0;
}
while (fgets(line, sizeof (line), in)) {
CPS_NormalizeLine(line);
if (!*line || !CPS_ParseKey(line, &key_id2, &hashname, &password))
continue;
if (key_id == key_id2)
break;
}
fclose(in);
if (key_id == key_id2) {
if (process_cmd_authhash(hashname) &&
process_cmd_password(&tx_message, password)) {
ret = request_reply(&tx_message, &rx_message, RPY_NULL, 1);
} else {
ret = 0;
}
} else {
fprintf(stderr, "Could not find key %lu in keyfile %s\n", key_id, keyfile);
ret = 0;
}
/* Erase password from stack */
memset(line, 0, sizeof (line));
return ret;
}
/* ================================================== */
static int static int
process_args(int argc, char **argv, int multi) process_args(int argc, char **argv, int multi)
{ {
@@ -2773,7 +2841,7 @@ process_args(int argc, char **argv, int multi)
} }
ret = process_line(line, &quit); ret = process_line(line, &quit);
if (!ret) if (!ret || quit)
break; break;
} }
@@ -2788,7 +2856,7 @@ static void
display_gpl(void) display_gpl(void)
{ {
printf("chrony version %s\n" printf("chrony version %s\n"
"Copyright (C) 1997-2003, 2007, 2009-2012 Richard P. Curnow and others\n" "Copyright (C) 1997-2003, 2007, 2009-2013 Richard P. Curnow and others\n"
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n" "chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
"you are welcome to redistribute it under certain conditions. See the\n" "you are welcome to redistribute it under certain conditions. See the\n"
"GNU General Public License version 2 for details.\n\n", "GNU General Public License version 2 for details.\n\n",
@@ -2803,7 +2871,8 @@ main(int argc, char **argv)
char *line; char *line;
const char *progname = argv[0]; const char *progname = argv[0];
const char *hostname = "localhost"; const char *hostname = "localhost";
int quit = 0, ret = 1, multi = 0; const char *conf_file = DEFAULT_CONF_FILE;
int quit = 0, ret = 1, multi = 0, auto_auth = 0;
int port = DEFAULT_CANDM_PORT; int port = DEFAULT_CANDM_PORT;
/* Parse command line options */ /* Parse command line options */
@@ -2818,6 +2887,13 @@ main(int argc, char **argv)
if (*argv) { if (*argv) {
port = atoi(*argv); port = atoi(*argv);
} }
} else if (!strcmp(*argv, "-f")) {
++argv, --argc;
if (*argv) {
conf_file = *argv;
}
} else if (!strcmp(*argv, "-a")) {
auto_auth = 1;
} else if (!strcmp(*argv, "-m")) { } else if (!strcmp(*argv, "-m")) {
multi = 1; multi = 1;
} else if (!strcmp(*argv, "-n")) { } else if (!strcmp(*argv, "-n")) {
@@ -2832,7 +2908,7 @@ main(int argc, char **argv)
printf("chronyc (chrony) version %s\n", CHRONY_VERSION); printf("chronyc (chrony) version %s\n", CHRONY_VERSION);
exit(0); exit(0);
} else if (!strncmp(*argv, "-", 1)) { } else if (!strncmp(*argv, "-", 1)) {
fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [command]\n", progname); fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [-a] [-f <file>]] [command]\n", progname);
exit(1); exit(1);
} else { } else {
break; /* And process remainder of line as a command */ break; /* And process remainder of line as a command */
@@ -2849,11 +2925,20 @@ main(int argc, char **argv)
/* MD5 is the default authentication hash */ /* MD5 is the default authentication hash */
auth_hash_id = HSH_GetHashId("MD5"); auth_hash_id = HSH_GetHashId("MD5");
assert(auth_hash_id >= 0); if (auth_hash_id < 0) {
fprintf(stderr, "Could not initialize MD5\n");
return 1;
}
open_io(hostname, port); open_io(hostname, port);
if (argc > 0) { if (auto_auth) {
ret = authenticate_from_config(conf_file);
}
if (!ret) {
;
} else if (argc > 0) {
ret = process_args(argc, argv, multi); ret = process_args(argc, argv, multi);
} else { } else {
do { do {

View File

@@ -174,7 +174,6 @@ CLG_Initialise(void)
void void
CLG_Finalise(void) CLG_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -34,7 +34,6 @@
#include "sched.h" #include "sched.h"
#include "util.h" #include "util.h"
#include "logging.h" #include "logging.h"
#include "md5.h"
#include "keys.h" #include "keys.h"
#include "ntp_sources.h" #include "ntp_sources.h"
#include "ntp_core.h" #include "ntp_core.h"
@@ -187,9 +186,6 @@ prepare_socket(int family)
int on_off = 1; int on_off = 1;
port_number = CNF_GetCommandPort(); port_number = CNF_GetCommandPort();
if (port_number < 0) {
port_number = DEFAULT_CANDM_PORT;
}
sock_fd = socket(family, SOCK_DGRAM, 0); sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
@@ -252,8 +248,10 @@ prepare_socket(int family)
} }
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) { if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
LOG_FATAL(LOGF_CmdMon, "Could not bind %s command socket : %s", LOG(LOGS_ERR, LOGF_CmdMon, "Could not bind %s command socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno)); family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
close(sock_fd);
return -1;
} }
/* Register handler for read events on the socket */ /* Register handler for read events on the socket */
@@ -265,7 +263,7 @@ prepare_socket(int family)
/* ================================================== */ /* ================================================== */
void void
CAM_Initialise(void) CAM_Initialise(int family)
{ {
assert(!initialised); assert(!initialised);
initialised = 1; initialised = 1;
@@ -281,9 +279,15 @@ CAM_Initialise(void)
free_replies = NULL; free_replies = NULL;
kept_replies.next = NULL; kept_replies.next = NULL;
if (family == IPADDR_UNSPEC || family == IPADDR_INET4)
sock_fd4 = prepare_socket(AF_INET); sock_fd4 = prepare_socket(AF_INET);
else
sock_fd4 = -1;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (family == IPADDR_UNSPEC || family == IPADDR_INET6)
sock_fd6 = prepare_socket(AF_INET6); sock_fd6 = prepare_socket(AF_INET6);
else
sock_fd6 = -1;
#endif #endif
if (sock_fd4 < 0 if (sock_fd4 < 0
@@ -319,7 +323,6 @@ CAM_Finalise(void)
ADF_DestroyTable(access_auth_table); ADF_DestroyTable(access_auth_table);
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -740,8 +743,6 @@ transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to, int auth_len)
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&ip), port); LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&ip), port);
} }
return;
} }
@@ -951,7 +952,7 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) { if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_TIMESTAMP); tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
tx_message->data.manual_timestamp.centiseconds = htonl(offset_cs); tx_message->data.manual_timestamp.centiseconds = htonl((int32_t)offset_cs);
tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm); tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm); tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
} else { } else {
@@ -1050,6 +1051,9 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
case RPT_CANDIDATE: case RPT_CANDIDATE:
tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE); tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE);
break; break;
case RPT_OUTLIER:
tx_message->data.source_data.state = htons(RPY_SD_ST_OUTLIER);
break;
} }
switch (report.mode) { switch (report.mode) {
case RPT_NTP_CLIENT: case RPT_NTP_CLIENT:
@@ -1447,7 +1451,6 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
} else { } else {
tx_message->status = htons(STT_NORTC); tx_message->status = htons(STT_NORTC);
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1462,7 +1465,6 @@ handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
} else { } else {
tx_message->status = htons(STT_NORTC); tx_message->status = htons(STT_NORTC);
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1473,7 +1475,6 @@ handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
LOG_CycleLogFiles(); LOG_CycleLogFiles();
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1521,8 +1522,6 @@ handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
break; break;
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1681,7 +1680,6 @@ handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
LCL_MakeStep(0.0); LCL_MakeStep(0.0);
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1709,7 +1707,6 @@ handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance); dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
SRC_SetReselectDistance(dist); SRC_SetReselectDistance(dist);
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1719,7 +1716,6 @@ handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
SRC_ReselectSource(); SRC_ReselectSource();
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -2319,9 +2315,6 @@ read_from_cmd_socket(void *anything)
do_it = ((do_it + 1) % 3); do_it = ((do_it + 1) % 3);
#endif #endif
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -29,7 +29,7 @@
#include "addressing.h" #include "addressing.h"
extern void CAM_Initialise(void); extern void CAM_Initialise(int family);
extern void CAM_Finalise(void); extern void CAM_Finalise(void);

View File

@@ -3,6 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2013
* *
* 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
@@ -33,17 +34,15 @@
#include "cmdparse.h" #include "cmdparse.h"
#include "memory.h" #include "memory.h"
#include "nameserv.h" #include "nameserv.h"
#include "util.h"
#define MAXLEN 2047
#define SMAXLEN "2047"
/* ================================================== */ /* ================================================== */
CPS_Status CPS_Status
CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src) CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
{ {
char *hostname, *cmd;
int ok, n, done; int ok, n, done;
char cmd[MAXLEN+1], hostname[MAXLEN+1];
CPS_Status result; CPS_Status result;
src->port = SRC_DEFAULT_PORT; src->port = SRC_DEFAULT_PORT;
@@ -63,26 +62,22 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
result = CPS_Success; result = CPS_Success;
ok = 0; hostname = line;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) { line = CPS_SplitWord(line);
ok = 1;
}
if (!ok) { if (!*hostname) {
result = CPS_BadHost; result = CPS_BadHost;
ok = 0;
} else { } else {
line += n;
/* Parse subfields */ /* Parse subfields */
ok = 1; ok = 1;
done = 0; done = 0;
do { do {
if (sscanf(line, "%" SMAXLEN "s%n", cmd, &n) == 1) { cmd = line;
line = CPS_SplitWord(line);
line += n; if (*cmd) {
if (!strcasecmp(cmd, "port")) {
if (!strncasecmp(cmd, "port", 4)) {
if (sscanf(line, "%hu%n", &src->port, &n) != 1) { if (sscanf(line, "%hu%n", &src->port, &n) != 1) {
result = CPS_BadPort; result = CPS_BadPort;
ok = 0; ok = 0;
@@ -90,7 +85,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "minpoll", 7)) { } else if (!strcasecmp(cmd, "minpoll")) {
if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1) {
result = CPS_BadMinpoll; result = CPS_BadMinpoll;
ok = 0; ok = 0;
@@ -98,7 +93,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "maxpoll", 7)) { } else if (!strcasecmp(cmd, "maxpoll")) {
if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1) {
result = CPS_BadMaxpoll; result = CPS_BadMaxpoll;
ok = 0; ok = 0;
@@ -106,7 +101,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "presend", 7)) { } else if (!strcasecmp(cmd, "presend")) {
if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1) {
result = CPS_BadPresend; result = CPS_BadPresend;
ok = 0; ok = 0;
@@ -114,7 +109,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "maxdelaydevratio", 16)) { } else if (!strcasecmp(cmd, "maxdelaydevratio")) {
if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) { if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) {
result = CPS_BadMaxdelaydevratio; result = CPS_BadMaxdelaydevratio;
ok = 0; ok = 0;
@@ -122,8 +117,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
/* This MUST come before the following one ! */ } else if (!strcasecmp(cmd, "maxdelayratio")) {
} else if (!strncasecmp(cmd, "maxdelayratio", 13)) {
if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) { if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) {
result = CPS_BadMaxdelayratio; result = CPS_BadMaxdelayratio;
ok = 0; ok = 0;
@@ -131,7 +125,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "maxdelay", 8)) { } else if (!strcasecmp(cmd, "maxdelay")) {
if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1) { if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1) {
result = CPS_BadMaxdelay; result = CPS_BadMaxdelay;
ok = 0; ok = 0;
@@ -139,7 +133,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "key", 3)) { } else if (!strcasecmp(cmd, "key")) {
if (sscanf(line, "%lu%n", &src->params.authkey, &n) != 1) { if (sscanf(line, "%lu%n", &src->params.authkey, &n) != 1) {
result = CPS_BadKey; result = CPS_BadKey;
ok = 0; ok = 0;
@@ -147,16 +141,16 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "offline", 7)) { } else if (!strcasecmp(cmd, "offline")) {
src->params.online = 0; src->params.online = 0;
} else if (!strncasecmp(cmd, "auto_offline", 12)) { } else if (!strcasecmp(cmd, "auto_offline")) {
src->params.auto_offline = 1; src->params.auto_offline = 1;
} else if (!strncasecmp(cmd, "iburst", 6)) { } else if (!strcasecmp(cmd, "iburst")) {
src->params.iburst = 1; src->params.iburst = 1;
} else if (!strncasecmp(cmd, "minstratum", 10)) { } else if (!strcasecmp(cmd, "minstratum")) {
if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) { if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) {
result = CPS_BadMinstratum; result = CPS_BadMinstratum;
ok = 0; ok = 0;
@@ -165,7 +159,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "polltarget", 10)) { } else if (!strcasecmp(cmd, "polltarget")) {
if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) { if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
result = CPS_BadPolltarget; result = CPS_BadPolltarget;
ok = 0; ok = 0;
@@ -174,10 +168,10 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
line += n; line += n;
} }
} else if (!strncasecmp(cmd, "noselect", 8)) { } else if (!strcasecmp(cmd, "noselect")) {
src->params.sel_option = SRC_SelectNoselect; src->params.sel_option = SRC_SelectNoselect;
} else if (!strncasecmp(cmd, "prefer", 6)) { } else if (!strcasecmp(cmd, "prefer")) {
src->params.sel_option = SRC_SelectPrefer; src->params.sel_option = SRC_SelectPrefer;
} else { } else {
@@ -192,10 +186,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} }
if (ok) { if (ok) {
n = strlen(hostname); src->name = strdup(hostname);
src->name = MallocArray(char, n + 1);
strncpy(src->name, hostname, n);
src->name[n] = '\0';
} }
return result; return result;
@@ -204,3 +195,87 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
/* ================================================== */ /* ================================================== */
void
CPS_NormalizeLine(char *line)
{
char *p, *q;
int space = 1, first = 1;
/* Remove white-space at beginning and replace white-spaces with space char */
for (p = q = line; *p; p++) {
if (isspace(*p)) {
if (!space)
*q++ = ' ';
space = 1;
continue;
}
/* Discard comment lines */
if (first && strchr("!;#%", *p))
break;
*q++ = *p;
space = first = 0;
}
/* Strip trailing space */
if (q > line && q[-1] == ' ')
q--;
*q = '\0';
}
/* ================================================== */
char *
CPS_SplitWord(char *line)
{
char *p = line, *q = line;
/* Skip white-space before the word */
while (*q && isspace(*q))
q++;
/* Move the word to the beginning */
while (*q && !isspace(*q))
*p++ = *q++;
/* Find the next word */
while (*q && isspace(*q))
q++;
*p = '\0';
/* Return pointer to the next word or NUL */
return q;
}
/* ================================================== */
int
CPS_ParseKey(char *line, unsigned long *id, const char **hash, char **key)
{
char *s1, *s2, *s3, *s4;
s1 = line;
s2 = CPS_SplitWord(s1);
s3 = CPS_SplitWord(s2);
s4 = CPS_SplitWord(s3);
/* Require two or three words */
if (!*s2 || *s4)
return 0;
if (sscanf(s1, "%lu", id) != 1)
return 0;
if (*s3) {
*hash = s2;
*key = s3;
} else {
*hash = "MD5";
*key = s2;
}
return 1;
}

View File

@@ -53,8 +53,15 @@ typedef struct {
} CPS_NTP_Source; } CPS_NTP_Source;
/* Parse a command to add an NTP server or peer */ /* Parse a command to add an NTP server or peer */
extern CPS_Status CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src); extern CPS_Status CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src);
/* Remove extra white-space and comments */
extern void CPS_NormalizeLine(char *line);
/* Terminate first word and return pointer to the next word */
extern char *CPS_SplitWord(char *line);
/* Parse a key from keyfile */
extern int CPS_ParseKey(char *line, unsigned long *id, const char **hash, char **key);
#endif /* GOT_CMDPARSE_H */ #endif /* GOT_CMDPARSE_H */

1011
conf.c

File diff suppressed because it is too large Load Diff

9
conf.h
View File

@@ -29,6 +29,8 @@
#include "addressing.h" #include "addressing.h"
extern void CNF_SetRestarted(int);
extern char *CNF_GetRtcDevice(void); extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename); extern void CNF_ReadFile(const char *filename);
@@ -54,6 +56,7 @@ 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 unsigned long CNF_GetCommandKey(void); extern unsigned long 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);
@@ -80,6 +83,7 @@ extern double CNF_GetCorrectionTimeRatio(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 int CNF_AllowLocalReference(int *stratum); extern int CNF_AllowLocalReference(int *stratum);
@@ -90,4 +94,9 @@ extern int CNF_GetLockMemory(void);
extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2); extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2);
extern char *CNF_GetUser(void);
extern int CNF_GetMaxSamples(void);
extern int CNF_GetMinSamples(void);
#endif /* GOT_CONF_H */ #endif /* GOT_CONF_H */

74
configure vendored
View File

@@ -8,7 +8,7 @@
# #
# ======================================================================= # =======================================================================
rm -f config.h rm -f config.h config.log
# This configure script determines the operating system type and version # This configure script determines the operating system type and version
@@ -43,7 +43,7 @@ test_code () {
ldflags=$4 ldflags=$4
code=$5 code=$5
printf "Checking for $name : " echo -n "Checking for $name : "
( (
for h in $headers; do for h in $headers; do
@@ -54,23 +54,30 @@ test_code () {
echo "return 0; }" echo "return 0; }"
) > docheck.c ) > docheck.c
$MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags $MYLDFLAGS >/dev/null 2>&1 echo "docheck.c:" >> config.log
cat docheck.c >> config.log
echo $MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
$MYLDFLAGS >> config.log
$MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
$MYLDFLAGS >> config.log 2>&1
if [ $? -eq 0 ] if [ $? -eq 0 ]
then then
printf "Yes\n" echo "Yes"
result=0 result=0
else else
printf "No\n" echo "No"
result=1 result=1
fi fi
rm -f docheck.c docheck rm -f docheck.c docheck
echo >> config.log
return $result return $result
} }
#}}} #}}}
#{{{ usage #{{{ usage
usage () { usage () {
cat <<EOF cat <<EOF
\`configure' configures tdl to adapt to many kinds of systems. \`configure' configures this package to adapt to many kinds of systems.
Usage: ./configure [OPTION]... Usage: ./configure [OPTION]...
@@ -106,6 +113,7 @@ For better control, use the options below.
--disable-linuxcaps Disable Linux capabilities support --disable-linuxcaps Disable Linux capabilities support
--disable-forcednsretry Don't retry on permanent DNS error --disable-forcednsretry Don't retry on permanent DNS error
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail] --with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
--enable-trace Enable tracing
Fine tuning of the installation directories: Fine tuning of the installation directories:
--sysconfdir=DIR chrony.conf location [/etc] --sysconfdir=DIR chrony.conf location [/etc]
@@ -115,6 +123,8 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info] --infodir=DIR info documentation [DATAROOTDIR/info]
--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]
--chronyvardir=DIR location for chrony data [LOCALSTATEDIR/lib/chrony]
Overriding system detection when cross-compiling: Overriding system detection when cross-compiling:
--host-system=OS Specify system name (uname -s) --host-system=OS Specify system name (uname -s)
@@ -183,7 +193,7 @@ mail_program="/usr/lib/sendmail"
for option for option
do do
case "$option" in case "$option" in
--trace ) --enable-trace )
add_def TRACEON add_def TRACEON
;; ;;
--disable-readline ) --disable-readline )
@@ -231,6 +241,12 @@ do
--docdir=* ) --docdir=* )
SETDOCDIR=`echo $option | sed -e 's/^.*=//;'` SETDOCDIR=`echo $option | sed -e 's/^.*=//;'`
;; ;;
--localstatedir=* )
SETLOCALSTATEDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--chronyvardir=* )
SETCHRONYVARDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--disable-rtc) --disable-rtc)
feat_rtc=0 feat_rtc=0
;; ;;
@@ -290,10 +306,6 @@ case $SYSTEM in
EXTRA_CLI_LIBS="-lsocket -lnsl" EXTRA_CLI_LIBS="-lsocket -lnsl"
add_def SOLARIS add_def SOLARIS
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")" echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
if [ $VERSION = "5.3" ]; then
add_def HAS_NO_BZERO
echo "Using memset() instead of bzero()"
fi
;; ;;
esac esac
;; ;;
@@ -354,7 +366,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
printf "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out\n" echo "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out"
exit 1 exit 1
fi fi
fi fi
@@ -475,6 +487,18 @@ if [ $feat_readline = "1" ]; then
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
if test_code readline 'stdio.h readline/readline.h readline/history.h' \ if test_code readline 'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib $ncurses_lib -lreadline" \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
READLINE_COMPILE="$readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline"
fi
fi
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
if test_code 'readline with -lncurses' \
'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \ "$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
'add_history(readline("prompt"));' 'add_history(readline("prompt"));'
then then
@@ -499,6 +523,7 @@ if [ $try_nss = "1" ]; then
HASH_OBJ="hash_nss.o" HASH_OBJ="hash_nss.o"
HASH_COMPILE="$test_cflags" HASH_COMPILE="$test_cflags"
HASH_LINK="$test_link" HASH_LINK="$test_link"
add_def GENERATE_SHA1_KEY
fi fi
fi fi
@@ -509,6 +534,7 @@ if [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]; then
HASH_OBJ="hash_tomcrypt.o" HASH_OBJ="hash_tomcrypt.o"
HASH_COMPILE="-I/usr/include/tomcrypt" HASH_COMPILE="-I/usr/include/tomcrypt"
HASH_LINK="-ltomcrypt" HASH_LINK="-ltomcrypt"
add_def GENERATE_SHA1_KEY
fi fi
fi fi
@@ -557,7 +583,17 @@ if [ "x$SETDOCDIR" != "x" ]; then
DOCDIR=$SETDOCDIR DOCDIR=$SETDOCDIR
fi fi
add_def DEFAULT_CONF_DIR "\"$SYSCONFDIR\"" LOCALSTATEDIR=/var
if [ "x$SETLOCALSTATEDIR" != "x" ]; then
LOCALSTATEDIR=$SETLOCALSTATEDIR
fi
CHRONYVARDIR=${LOCALSTATEDIR}/lib/chrony
if [ "x$SETCHRONYVARDIR" != "x" ]; then
CHRONYVARDIR=$SETCHRONYVARDIR
fi
add_def DEFAULT_CONF_FILE "\"$SYSCONFDIR/chrony.conf\""
add_def MAIL_PROGRAM "\"$mail_program\"" add_def MAIL_PROGRAM "\"$mail_program\""
if [ -f version.txt ]; then if [ -f version.txt ]; then
@@ -566,7 +602,10 @@ else
add_def CHRONY_VERSION "\"DEVELOPMENT\"" add_def CHRONY_VERSION "\"DEVELOPMENT\""
fi fi
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\ for f in Makefile chrony.conf.5 chrony.texi chronyc.1 chronyd.8
do
echo Creating $f
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@CC@%${MYCC}%;\ s%@CC@%${MYCC}%;\
s%@CFLAGS@%${MYCFLAGS}%;\ s%@CFLAGS@%${MYCFLAGS}%;\
s%@CPPFLAGS@%${CPPFLAGS}%;\ s%@CPPFLAGS@%${CPPFLAGS}%;\
@@ -584,8 +623,11 @@ sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@SBINDIR@%${SBINDIR}%;\ s%@SBINDIR@%${SBINDIR}%;\
s%@DOCDIR@%${DOCDIR}%;\ s%@DOCDIR@%${DOCDIR}%;\
s%@MANDIR@%${MANDIR}%;\ s%@MANDIR@%${MANDIR}%;\
s%@INFODIR@%${INFODIR}%;"\ s%@INFODIR@%${INFODIR}%;\
< Makefile.in > Makefile s%@LOCALSTATEDIR@%${LOCALSTATEDIR}%;\
s%@CHRONYVARDIR@%${CHRONYVARDIR}%;"\
< ${f}.in > $f
done
# ======================================================================= # =======================================================================
# vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s # vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s

View File

@@ -40,21 +40,21 @@
# more 'NTP servers'. You will probably find that your Internet Service # more 'NTP servers'. You will probably find that your Internet Service
# Provider or company have one or more NTP servers that you can specify. # Provider or company have one or more NTP servers that you can specify.
# Failing that, there are a lot of public NTP servers. There is a list # Failing that, there are a lot of public NTP servers. There is a list
# you can access at # you can access at http://support.ntp.org/bin/view/Servers/WebHome or
# http://www.eecis.udel.edu/~mills/ntp/servers.htm. # you can use servers from the pool.ntp.org project.
! server ntp0.your-isp.com ! server 0.pool.ntp.org iburst
! server ntp1.your-isp.com ! server 1.pool.ntp.org iburst
! server ntp.public-server.org ! server 2.pool.ntp.org iburst
# However, for dial-up use you probably want these instead. The word # However, for dial-up use you probably want these instead. The word
# 'offline' means that the server is not visible at boot time. Use # 'offline' means that the server is not visible at boot time. Use
# chronyc's 'online' command to tell chronyd that these servers have # chronyc's 'online' command to tell chronyd that these servers have
# become visible after you go on-line. # become visible after you go on-line.
! server ntp0.your-isp.com offline ! server 0.pool.ntp.org offline
! server ntp1.your-isp.com offline ! server 1.pool.ntp.org offline
! server ntp.public-server.org offline ! server 2.pool.ntp.org offline
# You may want to specify NTP 'peers' instead. If you run a network # You may want to specify NTP 'peers' instead. If you run a network
# with a lot of computers and want several computers running chrony to # with a lot of computers and want several computers running chrony to
@@ -89,7 +89,7 @@
# immediately so that it doesn't gain or lose any more time. You # immediately so that it doesn't gain or lose any more time. You
# generally want this, so it is uncommented. # generally want this, so it is uncommented.
driftfile /etc/chrony.drift driftfile /var/lib/chrony/drift
# If you want to use the program called chronyc to configure aspects of # If you want to use the program called chronyc to configure aspects of
# chronyd's operation once it is running (e.g. tell it the Internet link # chronyd's operation once it is running (e.g. tell it the Internet link
@@ -122,7 +122,7 @@ commandkey 1
# Enable these two options to use this. # Enable these two options to use this.
! dumponexit ! dumponexit
! dumpdir /var/log/chrony ! dumpdir /var/lib/chrony
# chronyd writes its process ID to a file. If you try to start a second # chronyd writes its process ID to a file. If you try to start a second
# copy of chronyd, it will detect that the process named in the file is # copy of chronyd, it will detect that the process named in the file is
@@ -133,17 +133,16 @@ commandkey 1
####################################################################### #######################################################################
### INITIAL CLOCK CORRECTION ### INITIAL CLOCK CORRECTION
# This option is only useful if your NTP servers are visible at boot # This option is useful to quickly correct the clock on start if it's
# time. This probably means you are on a LAN. If so, the following # off by a large amount. The value '10' means that if the error is less
# option will choose the best-looking of the servers and correct the
# system time to that. The value '10' means that if the error is less
# than 10 seconds, it will be gradually removed by speeding up or # than 10 seconds, it will be gradually removed by speeding up or
# slowing down your computer's clock until it is correct. If the error # slowing down your computer's clock until it is correct. If the error
# is above 10 seconds, an immediate time jump will be applied to correct # is above 10 seconds, an immediate time jump will be applied to correct
# it. Some software can get upset if the system clock jumps (especially # it. The value '1' means the step is allowed only on the first update
# backwards), so be careful! # of the clock. Some software can get upset if the system clock jumps
# (especially backwards), so be careful!
! initstepslew 10 ntp0.your-company.com ntp1.your-company.com ntp2.your-company.com ! makestep 10 1
####################################################################### #######################################################################
### LOGGING ### LOGGING
@@ -255,13 +254,6 @@ commandkey 1
# put into chronyc to allow you to modify chronyd's parameters. By # put into chronyc to allow you to modify chronyd's parameters. By
# default all you can do is view information about chronyd's operation. # default all you can do is view information about chronyd's operation.
# Some people have reported that the need the following line to allow
# chronyc to work even on the same machine. This should not be
# necessary, and the problem is being investigated. You can leave this
# line enabled, as it's benign otherwise.
cmdallow 127.0.0.1
####################################################################### #######################################################################
### 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
@@ -273,7 +265,7 @@ cmdallow 127.0.0.1
# You need to have 'enhanced RTC support' compiled into your Linux # You need to have 'enhanced RTC support' compiled into your Linux
# kernel. (Note, these options apply only to Linux.) # kernel. (Note, these options apply only to Linux.)
! rtcfile /etc/chrony.rtc ! rtcfile /var/lib/chrony/rtc
# Your RTC can be set to keep Universal Coordinated Time (UTC) or local # Your RTC can be set to keep Universal Coordinated Time (UTC) or local
# time. (Local time means UTC +/- the effect of your timezone.) If you # time. (Local time means UTC +/- the effect of your timezone.) If you

View File

@@ -18,9 +18,13 @@ rtcsync
# if the adjustment is larger than 100 seconds. # if the adjustment is larger than 100 seconds.
makestep 100 3 makestep 100 3
# Allow client access from local network. # Allow NTP client access from local network.
#allow 192.168/16 #allow 192.168/16
# Listen for commands only on localhost.
bindcmdaddress 127.0.0.1
bindcmdaddress ::1
# 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
@@ -29,6 +33,9 @@ keyfile /etc/chrony.keys
# Specify the key used as password for chronyc. # Specify the key used as password for chronyc.
commandkey 1 commandkey 1
# Generate command key if missing.
generatecommandkey
# Disable logging of client accesses. # Disable logging of client accesses.
noclientlog noclientlog

View File

@@ -1,26 +1,29 @@
####################################################################### #######################################################################
# #
# This is an example chrony keys file. You should copy it to /etc/chrony.keys # This is an example chrony keys file. You should copy it to /etc/chrony.keys
# after editing it to set up the key(s) you want to use. In most situations, # after editing it to set up the key(s) you want to use. It should be readable
# you will require a single key (the 'commandkey') so that you can supply a # only by root or the user chronyd drops the root privileges to. In most
# password to chronyc to enable you to modify chronyd's operation whilst it is # situations, you will require a single key (the 'commandkey') so that you can
# running. # supply a password to chronyc to enable you to modify chronyd's operation
# whilst it is running.
# #
# Copyright 2002 Richard P. Curnow # Copyright 2002 Richard P. Curnow
# #
####################################################################### ######################################################################
# A valid key line looks like this
1 a_key # Examples of valid keys:
# It must consist of an integer, followed by whitespace, followed by a block of #1 ALongAndRandomPassword
# text with no spaces in it. (You cannot put a space in a key). If you wanted #2 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC
# to use the above line as your commandkey (i.e. chronyc password), you would #3 SHA1 HEX:1DC764E0791B11FA67EFC7ECBC4B0D73F68A070C
# put the following line into chrony.conf (remove the # from the start):
# commandkey 1 # 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 MD5 authentication facility # You might want to define more keys if you use the authentication facility
# in the network time protocol to authenticate request/response packets between # in the network time protocol to authenticate request/response packets between
# trusted clients and servers. # trusted clients and servers.

67
faq.txt
View File

@@ -96,56 +96,6 @@ at all, I found xntpd gave me no help with managing the local clock's
gain/loss rate on the NTP master node (which I set from my watch). I gain/loss rate on the NTP master node (which I set from my watch). I
added some automated support in chrony to deal with this. added some automated support in chrony to deal with this.
S: Compilation issues
Q:How do I apply source patches?
Sometimes we release source patches rather than a full version when we need to
provide a fix for small problems. Supposing you have chrony-1.X.tar.gz and a
source patch chrony-1.X-1.X.1.gz. The steps required are:
tar xzvf ../chrony-1.X.tar.gz
cd chrony-1.X
gunzip < ../../chrony-1.X-1.X.1.gz | patch -p1
./configure
make
make install
Q:Can I compile chrony with an ANSI-C compiler that is not GCC v2.x?
I have had reports that chrony can be compiled with GCC v1.42, by using the
following trick when running make
make CC='gcc -D__FUNCTION__=\"function_not_available\"'
(this gets around the lack of a __FUNCTION__ macro in GCC v1.)
The same trick may be enough to allow other compilers to be used.
Q: I get errors like 'client.c:44: readline/readline.h: file not found'
Read the section about 'readline' in the INSTALL file or in chrony.txt. You
may need to disable readline support (e.g. if you haven't got readline
installed at all, or just don't want it), or specify the location of the
readline files (e.g. if you've installed them in a non-standard place).
Q: I have RedHat 7.3 and can't compile rtc_linux.c (error in spinlock.h)
The following solution has been found for this. Enter the following 3 commands
(as root):
cd /usr/include/
mv linux linux.rh
ln -s /usr/src/linux/include/linux ./linux
The problem seems to be that RedHat provide their own kernel header files in
/usr/include/linux. Besides differing from those used by your current kernel,
if you compiled it yourself, they also seem to have been changed in a way that
causes a problem compiling chrony. Chrony compiles fine with standard kernel
header files.
There have also been reports that just replacing the file
/usr/src/linux/spinlock.h by the equivalent file from a vanilla kernel source
tree is sufficient to fix the problem.
Note : from version 1.21 onwards, this problem no longer exists. The kernel
header files are no longer included.
S: Selection of NTP servers S: Selection of NTP servers
Q: I have several computers on a LAN. Should I make one the master, or make them all clients of an external server? Q: I have several computers on a LAN. Should I make one the master, or make them all clients of an external server?
I think the best configuration is to make one computer the master, with the I think the best configuration is to make one computer the master, with the
@@ -201,15 +151,6 @@ Do you have a 'local stratum X' directive in the chrony.conf file? If X is
lower than the stratum of the server you're trying to use, this situation will lower than the stratum of the server you're trying to use, this situation will
arise. You should always make X quite high (e.g. 10) in this directive. arise. You should always make X quite high (e.g. 10) in this directive.
S: Issues with chronyd
Q: chronyd crashes after a syslog message "adjtimex failed for set frequency"
The usual cause is that the kernel is running with a different value of 'HZ'
(the timer interrupt rate) than the value that was found in the kernel header
files when chrony was compiled. The chrony.conf file can include options to
modify the HZ value (see the discussion of linux_hz and linux_freq_scale in the
documentation), however the problem is to find the value of HZ being used.
S: Issues with chronyc S: Issues with chronyc
Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'. Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'.
@@ -268,14 +209,6 @@ For the real time clock support to work, you need the following three things:
* enhanced RTC support compiled into the kernel * enhanced RTC support compiled into the kernel
* an 'rtcfile' directive in your chrony.conf file. * an 'rtcfile' directive in your chrony.conf file.
S: Problems with isolated networks.
Q: When I use the 'settime' command, chronyd crashes.
If you enter times that are too far away from the real time, chronyd will
think the system clock runs fast or slow by an excessive amount. The required
compensation factor will be outside the bounds for the adjtimex() system call.
chronyd will crash when it tries to apply such an excessive adjustment.
S: Microsoft Windows S: Microsoft Windows
Q: Does chrony support Windows? Q: Does chrony support Windows?

144
keys.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012 * Copyright (C) Miroslav Lichvar 2012-2013
* *
* 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
@@ -28,11 +28,10 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include "sysincl.h"
#include <stdlib.h>
#include <string.h>
#include "keys.h" #include "keys.h"
#include "cmdparse.h"
#include "conf.h" #include "conf.h"
#include "memory.h" #include "memory.h"
#include "util.h" #include "util.h"
@@ -61,6 +60,64 @@ static int cache_key_pos;
/* ================================================== */ /* ================================================== */
static int
generate_key(unsigned long key_id)
{
#ifdef GENERATE_SHA1_KEY
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%lu %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 %lu", key_id);
return 1;
}
/* ================================================== */
void void
KEY_Initialise(void) KEY_Initialise(void)
{ {
@@ -68,7 +125,11 @@ KEY_Initialise(void)
command_key_valid = 0; command_key_valid = 0;
cache_valid = 0; cache_valid = 0;
KEY_Reload(); KEY_Reload();
return;
if (CNF_GetGenerateCommandKey() && !KEY_KeyKnown(KEY_GetCommandKey())) {
if (generate_key(KEY_GetCommandKey()))
KEY_Reload();
}
} }
/* ================================================== */ /* ================================================== */
@@ -76,8 +137,6 @@ KEY_Initialise(void)
void void
KEY_Finalise(void) KEY_Finalise(void)
{ {
/* Nothing to do */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -104,7 +163,7 @@ determine_hash_delay(int key_id)
} }
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Keys, "authentication delay for key %d: %d useconds", key_id, min_usecs); LOG(LOGS_INFO, LOGF_Keys, "authentication delay for key %lu: %d useconds", key_id, min_usecs);
#endif #endif
/* Add on a bit extra to allow for copying, conversions etc */ /* Add on a bit extra to allow for copying, conversions etc */
@@ -133,56 +192,55 @@ compare_keys_by_id(const void *a, const void *b)
/* ================================================== */ /* ================================================== */
#define KEYLEN 2047
#define SKEYLEN "2047"
void void
KEY_Reload(void) KEY_Reload(void)
{ {
int i, len1, fields; int i, line_number;
char *key_file;
FILE *in; FILE *in;
unsigned long key_id; unsigned long key_id;
char line[KEYLEN+1], buf1[KEYLEN+1], buf2[KEYLEN+1]; char line[2048], *keyval, *key_file;
char *keyval, *hashname; const char *hashname;
for (i=0; i<n_keys; i++) { for (i=0; i<n_keys; i++) {
Free(keys[i].val); Free(keys[i].val);
} }
n_keys = 0; n_keys = 0;
command_key_valid = 0;
cache_valid = 0;
key_file = CNF_GetKeysFile(); key_file = CNF_GetKeysFile();
line_number = 0;
if (!key_file)
return;
if (key_file) {
in = fopen(key_file, "r"); in = fopen(key_file, "r");
if (in) { if (!in) {
while (fgets(line, sizeof(line), in)) { LOG(LOGS_WARN, LOGF_Keys, "Could not open keyfile %s", key_file);
len1 = strlen(line) - 1; return;
}
/* Guard against removing last character of the line while (fgets(line, sizeof (line), in)) {
* if the last line of the file is missing an end-of-line */ line_number++;
if (line[len1] == '\n') {
line[len1] = '\0'; CPS_NormalizeLine(line);
} if (!*line)
fields = sscanf(line, "%lu%" SKEYLEN "s%" SKEYLEN "s", &key_id, buf1, buf2); continue;
if (fields >= 2 && fields <= 3) {
if (fields == 3) { if (!CPS_ParseKey(line, &key_id, &hashname, &keyval)) {
hashname = buf1; LOG(LOGS_WARN, LOGF_Keys, "Could not parse key at line %d in file %s", line_number, key_file);
keyval = buf2; continue;
} else {
hashname = "MD5";
keyval = buf1;
} }
keys[n_keys].hash_id = HSH_GetHashId(hashname); keys[n_keys].hash_id = HSH_GetHashId(hashname);
if (keys[n_keys].hash_id < 0) { if (keys[n_keys].hash_id < 0) {
LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %d", key_id); LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %lu", key_id);
continue; continue;
} }
keys[n_keys].len = UTI_DecodePasswordFromText(keyval); keys[n_keys].len = UTI_DecodePasswordFromText(keyval);
if (!keys[n_keys].len) { if (!keys[n_keys].len) {
LOG(LOGS_WARN, LOGF_Keys, "Could not decode password in key %d", key_id); LOG(LOGS_WARN, LOGF_Keys, "Could not decode password in key %lu", key_id);
continue; continue;
} }
@@ -191,7 +249,7 @@ KEY_Reload(void)
memcpy(keys[n_keys].val, keyval, keys[n_keys].len); memcpy(keys[n_keys].val, keyval, keys[n_keys].len);
n_keys++; n_keys++;
} }
}
fclose(in); fclose(in);
/* Sort keys into order. Note, if there's a duplicate, it is /* Sort keys into order. Note, if there's a duplicate, it is
@@ -199,21 +257,19 @@ KEY_Reload(void)
more careful! */ more careful! */
qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id); qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id);
/* Erase the passwords from stack */ /* Check for duplicates */
memset(line, 0, sizeof (line)); for (i = 1; i < n_keys; i++) {
memset(buf1, 0, sizeof (buf1)); if (keys[i - 1].id == keys[i].id) {
memset(buf2, 0, sizeof (buf2)); LOG(LOGS_WARN, LOGF_Keys, "Detected duplicate key %lu", key_id);
} }
} }
command_key_valid = 0; /* Erase any passwords from stack */
cache_valid = 0; memset(line, 0, sizeof (line));
for (i=0; i<n_keys; i++) { for (i=0; i<n_keys; i++) {
keys[i].auth_delay = determine_hash_delay(keys[i].id); keys[i].auth_delay = determine_hash_delay(keys[i].id);
} }
return;
} }
/* ================================================== */ /* ================================================== */

19
local.c
View File

@@ -30,8 +30,7 @@
#include "config.h" #include "config.h"
#include <assert.h> #include "sysincl.h"
#include <stddef.h>
#include "conf.h" #include "conf.h"
#include "local.h" #include "local.h"
@@ -132,8 +131,6 @@ calculate_sys_precision(void)
precision_log--; precision_log--;
best_dusec *= 2; best_dusec *= 2;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -167,7 +164,6 @@ LCL_Initialise(void)
void void
LCL_Finalise(void) LCL_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -220,14 +216,11 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
new_entry->prev = change_list.prev; new_entry->prev = change_list.prev;
change_list.prev->next = new_entry; change_list.prev->next = new_entry;
change_list.prev = new_entry; change_list.prev = new_entry;
return;
} }
/* ================================================== */ /* ================================================== */
/* Remove a handler */ /* Remove a handler */
extern
void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything) void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
{ {
@@ -251,8 +244,6 @@ void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *
ptr->prev->next = ptr->next; ptr->prev->next = ptr->next;
free(ptr); free(ptr);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -279,8 +270,6 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
new_entry->prev = dispersion_notify_list.prev; new_entry->prev = dispersion_notify_list.prev;
dispersion_notify_list.prev->next = new_entry; dispersion_notify_list.prev->next = new_entry;
dispersion_notify_list.prev = new_entry; dispersion_notify_list.prev = new_entry;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -310,8 +299,6 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
ptr->prev->next = ptr->next; ptr->prev->next = ptr->next;
free(ptr); free(ptr);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -577,8 +564,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Local, "Local freq=%.3fppm", current_freq_ppm); LOG(LOGS_INFO, LOGF_Local, "Local freq=%.3fppm", current_freq_ppm);
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -614,8 +599,6 @@ LCL_SetLeap(int leap)
if (drv_set_leap) { if (drv_set_leap) {
(drv_set_leap)(leap); (drv_set_leap)(leap);
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -29,7 +29,6 @@
#include "sysincl.h" #include "sysincl.h"
#include "main.h"
#include "conf.h" #include "conf.h"
#include "logging.h" #include "logging.h"
#include "mkdirpp.h" #include "mkdirpp.h"
@@ -74,8 +73,6 @@ LOG_Initialise(void)
#ifdef WINNT #ifdef WINNT
logfile = fopen("./chronyd.err", "a"); logfile = fopen("./chronyd.err", "a");
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -97,7 +94,6 @@ LOG_Finalise(void)
LOG_CycleLogFiles(); LOG_CycleLogFiles();
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -132,7 +128,6 @@ LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *form
fprintf(stderr, "%s\n", buf); fprintf(stderr, "%s\n", buf);
} }
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -162,9 +157,7 @@ LOG_Fatal_Function(LOG_Facility facility, const char *format, ...)
} }
#endif #endif
MAI_CleanupAndExit(); exit(1);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -185,7 +178,6 @@ LOG_Position(const char *filename, int line_number, const char *function_name)
fprintf(stderr, "%s:%d:(%s)[%s] ", filename, line_number, function_name, buf); fprintf(stderr, "%s:%d:(%s)[%s] ", filename, line_number, function_name, buf);
} }
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */

26
main.c
View File

@@ -88,13 +88,13 @@ MAI_CleanupAndExit(void)
TMC_Finalise(); TMC_Finalise();
MNL_Finalise(); MNL_Finalise();
ACQ_Finalise(); ACQ_Finalise();
KEY_Finalise();
CLG_Finalise(); CLG_Finalise();
NSR_Finalise(); NSR_Finalise();
NCR_Finalise(); NCR_Finalise();
BRD_Finalise(); BRD_Finalise();
SST_Finalise(); SST_Finalise();
REF_Finalise(); REF_Finalise();
KEY_Finalise();
RCL_Finalise(); RCL_Finalise();
SRC_Finalise(); SRC_Finalise();
RTC_Finalise(); RTC_Finalise();
@@ -284,10 +284,10 @@ go_daemon(void)
int main int main
(int argc, char **argv) (int argc, char **argv)
{ {
char *conf_file = NULL; const char *conf_file = DEFAULT_CONF_FILE;
char *user = NULL; char *user = NULL;
int debug = 0, nofork = 0; int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
int do_init_rtc = 0; int do_init_rtc = 0, restarted = 0;
int other_pid; int other_pid;
int lock_memory = 0, sched_priority = 0; int lock_memory = 0, sched_priority = 0;
@@ -308,6 +308,8 @@ int main
lock_memory = 1; lock_memory = 1;
} else if (!strcmp("-r", *argv)) { } else if (!strcmp("-r", *argv)) {
reload = 1; reload = 1;
} else if (!strcmp("-R", *argv)) {
restarted = 1;
} else if (!strcmp("-u", *argv)) { } else if (!strcmp("-u", *argv)) {
++argv, --argc; ++argv, --argc;
if (argc == 0) { if (argc == 0) {
@@ -327,9 +329,9 @@ int main
debug = 1; debug = 1;
nofork = 1; nofork = 1;
} else if (!strcmp("-4", *argv)) { } else if (!strcmp("-4", *argv)) {
DNS_SetAddressFamily(IPADDR_INET4); address_family = IPADDR_INET4;
} else if (!strcmp("-6", *argv)) { } else if (!strcmp("-6", *argv)) {
DNS_SetAddressFamily(IPADDR_INET6); address_family = IPADDR_INET6;
} else { } else {
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv); LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
} }
@@ -352,6 +354,9 @@ int main
LOG(LOGS_INFO, LOGF_Main, "chronyd version %s starting", CHRONY_VERSION); LOG(LOGS_INFO, LOGF_Main, "chronyd version %s starting", CHRONY_VERSION);
DNS_SetAddressFamily(address_family);
CNF_SetRestarted(restarted);
CNF_ReadFile(conf_file); CNF_ReadFile(conf_file);
/* Check whether another chronyd may already be running. Do this after /* Check whether another chronyd may already be running. Do this after
@@ -373,11 +378,12 @@ int main
LCL_Initialise(); LCL_Initialise();
SCH_Initialise(); SCH_Initialise();
SYS_Initialise(); SYS_Initialise();
NIO_Initialise(); NIO_Initialise(address_family);
CAM_Initialise(); CAM_Initialise(address_family);
RTC_Initialise(); RTC_Initialise();
SRC_Initialise(); SRC_Initialise();
RCL_Initialise(); RCL_Initialise();
KEY_Initialise();
/* Command-line switch must have priority */ /* Command-line switch must have priority */
if (!sched_priority) { if (!sched_priority) {
@@ -391,6 +397,9 @@ int main
SYS_LockMemory(); SYS_LockMemory();
} }
if (!user) {
user = CNF_GetUser();
}
if (user) { if (user) {
SYS_DropRoot(user); SYS_DropRoot(user);
} }
@@ -403,7 +412,6 @@ int main
NCR_Initialise(); NCR_Initialise();
NSR_Initialise(); NSR_Initialise();
CLG_Initialise(); CLG_Initialise();
KEY_Initialise();
ACQ_Initialise(); ACQ_Initialise();
MNL_Initialise(); MNL_Initialise();
TMC_Initialise(); TMC_Initialise();

View File

@@ -34,15 +34,18 @@ echo $version > version.txt
sed -e "s%@@VERSION@@%${version}%" < chrony.spec.sample > chrony.spec sed -e "s%@@VERSION@@%${version}%" < chrony.spec.sample > chrony.spec
for m in chrony.1 chronyc.1 chrony.conf.5 chronyd.8; do for m in chrony.1.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
makeinfo --no-headers --number-sections -o chrony.txt chrony.texi ./configure && make chrony.txt || exit 1
mv chrony.txt chrony.txt_
make distclean
mv chrony.txt_ chrony.txt
rm -f make_release chrony.spec.sample .gitignore rm -f faqgen.pl make_release chrony.spec.sample .gitignore
cd .. cd ..
tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz

View File

@@ -32,7 +32,7 @@
#include "config.h" #include "config.h"
#include <stddef.h> #include "sysincl.h"
#include "manual.h" #include "manual.h"
#include "logging.h" #include "logging.h"
@@ -93,8 +93,6 @@ MNL_Initialise(void)
error = ERROR_MARGIN; error = ERROR_MARGIN;
LCL_AddParameterChangeHandler(slew_samples, NULL); LCL_AddParameterChangeHandler(slew_samples, NULL);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -102,7 +100,6 @@ MNL_Initialise(void)
void void
MNL_Finalise(void) MNL_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -157,7 +154,7 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
if (found_freq) { if (found_freq) {
LOG(LOGS_INFO, LOGF_Manual, LOG(LOGS_INFO, LOGF_Manual,
"Making a frequency change of %.3fppm and a slew of %.6f\n", "Making a frequency change of %.3f ppm and a slew of %.6f",
1.0e6 * freq, slew_by); 1.0e6 * freq, slew_by);
REF_SetManualReference(now, REF_SetManualReference(now,
@@ -239,7 +236,6 @@ slew_samples(struct timeval *raw,
dfreq, doffset); dfreq, doffset);
samples[i].offset += delta_time; samples[i].offset += delta_time;
} }
return;
} }
/* ================================================== */ /* ================================================== */

6
md5.h
View File

@@ -32,11 +32,7 @@
*********************************************************************** ***********************************************************************
*/ */
#ifdef HAS_STDINT_H #include "sysincl.h"
#include <stdint.h>
#elif defined(HAS_INTTYPES_H)
#include <inttypes.h>
#endif
/* typedef a 32-bit type */ /* typedef a 32-bit type */
typedef uint32_t UINT4; typedef uint32_t UINT4;

View File

@@ -27,8 +27,6 @@
#ifndef GOT_MEMORY_H #ifndef GOT_MEMORY_H
#define GOT_MEMORY_H #define GOT_MEMORY_H
#include <stdlib.h>
#define Malloc(x) malloc(x) #define Malloc(x) malloc(x)
#define MallocNew(T) ((T *) malloc(sizeof(T))) #define MallocNew(T) ((T *) malloc(sizeof(T)))
#define MallocArray(T, n) ((T *) malloc((n) * sizeof(T))) #define MallocArray(T, n) ((T *) malloc((n) * sizeof(T)))

View File

@@ -32,7 +32,6 @@
#include "nameserv.h" #include "nameserv.h"
#include "util.h" #include "util.h"
#include <resolv.h>
/* ================================================== */ /* ================================================== */

24
ntp.h
View File

@@ -27,11 +27,7 @@
#ifndef GOT_NTP_H #ifndef GOT_NTP_H
#define GOT_NTP_H #define GOT_NTP_H
#ifdef HAS_STDINT_H #include "sysincl.h"
#include <stdint.h>
#elif defined(HAS_INTTYPES_H)
#include <inttypes.h>
#endif
#include "hash.h" #include "hash.h"
@@ -93,22 +89,4 @@ typedef union {
#define NTP_NORMAL_PACKET_SIZE offsetof(NTP_Packet, auth_keyid) #define NTP_NORMAL_PACKET_SIZE offsetof(NTP_Packet, auth_keyid)
/* ================================================== */
inline static double
int32_to_double(NTP_int32 x)
{
return (double) ntohl(x) / 65536.0;
}
/* ================================================== */
inline static NTP_int32
double_to_int32(double x)
{
return htonl((NTP_int32)(0.5 + 65536.0 * x));
}
/* ================================================== */
#endif /* GOT_NTP_H */ #endif /* GOT_NTP_H */

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2012 * Copyright (C) Miroslav Lichvar 2009-2013
* *
* 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
@@ -84,6 +84,8 @@ struct NCR_Instance_Record {
int local_poll; /* Log2 of polling interval at our end */ int local_poll; /* Log2 of polling interval at our end */
int remote_poll; /* Log2 of server/peer's polling interval (recovered int remote_poll; /* Log2 of server/peer's polling interval (recovered
from received packets) */ from received packets) */
int remote_stratum; /* Stratum of the server/peer (recovered from
received packets) */
int presend_minpoll; /* If the current polling interval is int presend_minpoll; /* If the current polling interval is
at least this, an echo datagram at least this, an echo datagram
@@ -178,6 +180,9 @@ struct NCR_Instance_Record {
/* Randomness added to spacing between samples for one server/peer */ /* Randomness added to spacing between samples for one server/peer */
#define SAMPLING_RANDOMNESS 0.02 #define SAMPLING_RANDOMNESS 0.02
/* Adjustment of the peer polling interval */
#define PEER_SAMPLING_ADJ 1.1
/* Spacing between samples in burst mode for one server/peer */ /* Spacing between samples in burst mode for one server/peer */
#define BURST_INTERVAL 2.0 #define BURST_INTERVAL 2.0
@@ -193,7 +198,7 @@ struct NCR_Instance_Record {
/* Compatible NTP protocol versions */ /* Compatible NTP protocol versions */
#define NTP_MAX_COMPAT_VERSION 4 #define NTP_MAX_COMPAT_VERSION 4
#define NTP_MIN_COMPAT_VERSION 2 #define NTP_MIN_COMPAT_VERSION 1
/* Maximum allowed dispersion - as defined in RFC1305 (16 seconds) */ /* Maximum allowed dispersion - as defined in RFC1305 (16 seconds) */
#define NTP_MAX_DISPERSION 16.0 #define NTP_MAX_DISPERSION 16.0
@@ -249,8 +254,21 @@ start_initial_timeout(NCR_Instance inst)
SCH_NtpSamplingClass, SCH_NtpSamplingClass,
transmit_timeout, (void *)inst); transmit_timeout, (void *)inst);
inst->timer_running = 1; inst->timer_running = 1;
}
return; /* ================================================== */
static void
take_offline(NCR_Instance inst)
{
inst->opmode = MD_OFFLINE;
if (inst->timer_running) {
SCH_RemoveTimeout(inst->timeout_id);
inst->timer_running = 0;
}
/* Mark source unreachable */
SRC_ResetReachability(inst->source);
} }
/* ================================================== */ /* ================================================== */
@@ -317,6 +335,8 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
result->auto_offline = params->auto_offline; result->auto_offline = params->auto_offline;
result->local_poll = params->minpoll; result->local_poll = params->minpoll;
result->remote_poll = 0;
result->remote_stratum = 0;
/* Create a source instance for this NTP source */ /* Create a source instance for this NTP source */
result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, params->sel_option, &result->remote_addr.ip_addr); result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, params->sel_option, &result->remote_addr.ip_addr);
@@ -351,7 +371,6 @@ NCR_DestroyInstance(NCR_Instance instance)
/* Free the data structure */ /* Free the data structure */
Free(instance); Free(instance);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -392,9 +411,133 @@ adjust_poll(NCR_Instance inst, double adj)
/* ================================================== */ /* ================================================== */
static double
get_poll_adj(NCR_Instance inst, double error_in_estimate, double peer_distance)
{
double poll_adj;
if (error_in_estimate > peer_distance) {
int shift = 0;
unsigned long temp = (int)(error_in_estimate / peer_distance);
do {
shift++;
temp>>=1;
} while (temp);
poll_adj = -shift - inst->poll_score + 0.5;
} else {
int samples = SRC_Samples(inst->source);
/* Adjust polling interval so that the number of sourcestats samples
remains close to the target value */
poll_adj = ((double)samples / inst->poll_target - 1.0) / inst->poll_target;
/* Make interval shortening quicker */
if (samples < inst->poll_target) {
poll_adj *= 2.0;
}
}
return poll_adj;
}
/* ================================================== */
static double
get_transmit_delay(NCR_Instance inst, int on_tx, double last_tx)
{
int poll_to_use, stratum_diff;
double delay_time;
/* If we're in burst mode, queue for immediate dispatch.
If we're operating in client/server mode, queue the timeout for
the poll interval hence. The fact that a timeout has been queued
in the transmit handler is immaterial - that is only done so that
we at least send something, if no reply is heard.
If we're in symmetric mode, we have to take account of the peer's
wishes, otherwise his sampling regime will fall to pieces. If
we're in client/server mode, we don't care what poll interval the
server responded with last time. */
switch (inst->opmode) {
case MD_OFFLINE:
assert(0);
break;
case MD_ONLINE:
/* Normal processing, depending on whether we're in
client/server or symmetric mode */
switch(inst->mode) {
case MODE_CLIENT:
/* Client/server association - aim at some randomised time
approx the poll interval away */
poll_to_use = inst->local_poll;
delay_time = (double) (1UL<<poll_to_use);
break;
case MODE_ACTIVE:
/* Symmetric active association - aim at some randomised time approx
the poll interval away since the last transmit */
/* Use shorter of the local and remote poll interval, but not shorter
than the allowed minimum */
poll_to_use = inst->local_poll;
if (poll_to_use > inst->remote_poll)
poll_to_use = inst->remote_poll;
if (poll_to_use < inst->minpoll)
poll_to_use = inst->minpoll;
delay_time = (double) (1UL<<poll_to_use);
/* If the remote stratum is higher than ours, try to lock on the
peer's polling to minimize our response time by slightly extending
our delay or waiting for the peer to catch up with us as the
random part in the actual interval is reduced. If the remote
stratum is equal to ours, try to interleave evenly with the peer. */
stratum_diff = inst->remote_stratum - REF_GetOurStratum();
if ((stratum_diff > 0 && last_tx * PEER_SAMPLING_ADJ < delay_time) ||
(!on_tx && !stratum_diff &&
last_tx / delay_time > PEER_SAMPLING_ADJ - 0.5))
delay_time *= PEER_SAMPLING_ADJ;
/* Substract the already spend time */
if (last_tx > 0.0)
delay_time -= last_tx;
if (delay_time < 0.0)
delay_time = 0.0;
break;
default:
assert(0);
break;
}
break;
case MD_BURST_WAS_ONLINE:
case MD_BURST_WAS_OFFLINE:
/* With burst, the timeout for new transmit after valid reply is shorter
than the timeout without reply */
delay_time = on_tx ? BURST_TIMEOUT : BURST_INTERVAL;
break;
default:
assert(0);
break;
}
return delay_time;
}
/* ================================================== */
static void static void
transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
int my_poll, /* The log2 of the local poll interval */ int my_poll, /* The log2 of the local poll interval */
int version, /* The NTP version to be set in the packet */
int do_auth, /* Boolean indicating whether to authenticate the packet or not */ int do_auth, /* Boolean indicating whether to authenticate the packet or not */
unsigned long key_id, /* The authentication key ID */ unsigned long key_id, /* The authentication key ID */
NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */ NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */
@@ -412,20 +555,25 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
) )
{ {
NTP_Packet message; NTP_Packet message;
int version;
int leap; int leap;
struct timeval local_transmit; struct timeval local_transmit;
/* Parameters read from reference module */ /* Parameters read from reference module */
int are_we_synchronised, our_stratum; int are_we_synchronised, our_stratum;
NTP_Leap leap_status; NTP_Leap leap_status;
uint32_t our_ref_id; 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;
/* Don't reply with version higher than ours */
if (version > NTP_VERSION) {
version = NTP_VERSION; version = NTP_VERSION;
}
/* This is accurate enough and cheaper than calling LCL_ReadCookedTime.
A more accurate time stamp will be taken later in this function. */
SCH_GetLastEventTime(&local_transmit, NULL, NULL);
LCL_ReadCookedTime(&local_transmit, NULL);
REF_GetReferenceParams(&local_transmit, REF_GetReferenceParams(&local_transmit,
&are_we_synchronised, &leap_status, &are_we_synchronised, &leap_status,
&our_stratum, &our_stratum,
@@ -452,13 +600,13 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
/* If we're sending a client mode packet and we aren't synchronized yet, /* If we're sending a client mode packet and we aren't synchronized yet,
we might have to set up artificial values for some of these parameters */ we might have to set up artificial values for some of these parameters */
message.root_delay = double_to_int32(our_root_delay); message.root_delay = UTI_DoubleToInt32(our_root_delay);
message.root_dispersion = double_to_int32(our_root_dispersion); message.root_dispersion = UTI_DoubleToInt32(our_root_dispersion);
message.reference_id = htonl((NTP_int32) our_ref_id); message.reference_id = htonl((NTP_int32) our_ref_id);
/* Now fill in timestamps */ /* Now fill in timestamps */
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts); 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 */
message.originate_ts = *orig_ts; message.originate_ts = *orig_ts;
@@ -467,7 +615,10 @@ 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); UTI_TimevalToInt64(local_rx, &message.receive_ts, 0);
/* Prepare random bits which will be added to the transmit timestamp. */
ts_fuzz = UTI_GetNTPTsFuzz(message.precision);
/* Transmit - this our local time right now! Also, we might need to /* Transmit - this our local time right now! Also, we might need to
store this for our own use later, next time we receive a message store this for our own use later, next time we receive a message
@@ -481,7 +632,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
take to generate the authentication data. */ take to generate the authentication data. */
local_transmit.tv_usec += KEY_GetAuthDelay(key_id); local_transmit.tv_usec += KEY_GetAuthDelay(key_id);
UTI_NormaliseTimeval(&local_transmit); UTI_NormaliseTimeval(&local_transmit);
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts); UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz);
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message, auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
offsetof(NTP_Packet, auth_keyid), offsetof(NTP_Packet, auth_keyid),
@@ -492,7 +643,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
sizeof (message.auth_keyid) + auth_len); sizeof (message.auth_keyid) + auth_len);
} }
} else { } else {
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts); UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz);
NIO_SendNormalPacket(&message, where_to); NIO_SendNormalPacket(&message, where_to);
} }
@@ -513,10 +664,28 @@ static void
transmit_timeout(void *arg) transmit_timeout(void *arg)
{ {
NCR_Instance inst = (NCR_Instance) arg; NCR_Instance inst = (NCR_Instance) arg;
double timeout_delay=0.0; double timeout_delay;
int do_timer = 0;
int do_auth; int do_auth;
inst->timer_running = 0;
switch (inst->opmode) {
case MD_BURST_WAS_ONLINE:
/* With online burst switch to online before last packet */
if (inst->burst_total_samples_to_go <= 1)
inst->opmode = MD_ONLINE;
case MD_BURST_WAS_OFFLINE:
if (inst->burst_total_samples_to_go <= 0)
take_offline(inst);
break;
default:
break;
}
if (inst->opmode == MD_OFFLINE) {
return;
}
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]", LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]",
UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port); UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port);
@@ -572,63 +741,29 @@ transmit_timeout(void *arg)
do_auth = 0; do_auth = 0;
} }
if (inst->opmode != MD_OFFLINE) {
transmit_packet(inst->mode, inst->local_poll, transmit_packet(inst->mode, inst->local_poll,
NTP_VERSION,
do_auth, inst->auth_key_id, do_auth, inst->auth_key_id,
&inst->remote_orig, &inst->remote_orig,
&inst->local_rx, &inst->local_tx, &inst->local_ntp_tx, &inst->local_rx, &inst->local_tx, &inst->local_ntp_tx,
&inst->remote_addr); &inst->remote_addr);
}
switch (inst->opmode) { switch (inst->opmode) {
case MD_BURST_WAS_ONLINE:
case MD_BURST_WAS_OFFLINE: case MD_BURST_WAS_OFFLINE:
--inst->burst_total_samples_to_go; --inst->burst_total_samples_to_go;
if (inst->burst_total_samples_to_go <= 0) {
inst->opmode = MD_OFFLINE;
}
break;
case MD_BURST_WAS_ONLINE:
--inst->burst_total_samples_to_go;
if (inst->burst_total_samples_to_go <= 0) {
inst->opmode = MD_ONLINE;
}
break; break;
default: default:
break; break;
} }
/* Restart timer for this message */ /* Restart timer for this message */
switch (inst->opmode) { timeout_delay = get_transmit_delay(inst, 1, 0.0);
case MD_ONLINE:
timeout_delay = (double)(1 << inst->local_poll);
do_timer = 1;
break;
case MD_OFFLINE:
do_timer = 0;
/* Mark source unreachable */
SRC_ResetReachability(inst->source);
break;
case MD_BURST_WAS_ONLINE:
case MD_BURST_WAS_OFFLINE:
timeout_delay = BURST_TIMEOUT;
do_timer = 1;
break;
}
if (do_timer) {
inst->timer_running = 1; inst->timer_running = 1;
inst->timeout_id = SCH_AddTimeoutInClass(timeout_delay, SAMPLING_SEPARATION, inst->timeout_id = SCH_AddTimeoutInClass(timeout_delay, SAMPLING_SEPARATION,
SAMPLING_RANDOMNESS, SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass, SCH_NtpSamplingClass,
transmit_timeout, (void *)inst); transmit_timeout, (void *)inst);
} else {
inst->timer_running = 0;
}
/* And we're done */
return;
} }
@@ -712,10 +847,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
/* The absolute difference between the offset estimate and /* The absolute difference between the offset estimate and
measurement in seconds */ measurement in seconds */
double error_in_estimate; double error_in_estimate;
int poll_to_use;
double delay_time = 0; double delay_time = 0;
int requeue_transmit = 0; int requeue_transmit = 0;
double poll_adj;
/* ==================== */ /* ==================== */
@@ -729,8 +862,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
source_is_synchronized = 1; source_is_synchronized = 1;
} }
pkt_root_delay = int32_to_double(message->root_delay); pkt_root_delay = UTI_Int32ToDouble(message->root_delay);
pkt_root_dispersion = int32_to_double(message->root_dispersion); pkt_root_dispersion = UTI_Int32ToDouble(message->root_dispersion);
/* Perform packet validity tests */ /* Perform packet validity tests */
@@ -754,13 +887,12 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
} }
/* Regardless of any validity checks we apply, we are required to /* Regardless of any validity checks we apply, we are required to
save these two fields from the packet into the ntp source save this field from the packet into the ntp source
instance record. See RFC1305 section 3.4.4, peer.org <- pkt.xmt instance record. See RFC1305 section 3.4.4, peer.org <- pkt.xmt
& peer.peerpoll <- pkt.poll. Note we can't do this assignment & peer.peerpoll <- pkt.poll. Note we can't do this assignment
before test1 has been carried out!! */ before test1 has been carried out!! */
inst->remote_orig = message->transmit_ts; inst->remote_orig = message->transmit_ts;
inst->remote_poll = message->poll;
/* Test 3 requires that pkt.org != 0 and pkt.rec != 0. If /* Test 3 requires that pkt.org != 0 and pkt.rec != 0. If
either of these are true it means the association is not properly either of these are true it means the association is not properly
@@ -790,13 +922,12 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
assuming worst case frequency error between us and the other assuming worst case frequency error between us and the other
source */ source */
delta = local_interval - remote_interval / (1.0 - source_freq_lo); delta = local_interval - remote_interval * (1.0 + source_freq_lo);
/* Calculate theta. Following the NTP definition, this is negative /* Calculate theta. Following the NTP definition, this is negative
if we are fast of the remote source. */ if we are fast of the remote source. */
theta = (double) (remote_average.tv_sec - local_average.tv_sec) + UTI_DiffTimevalsToDouble(&theta, &remote_average, &local_average);
(double) (remote_average.tv_usec - local_average.tv_usec) * 1.0e-6;
/* We treat the time of the sample as being midway through the local /* We treat the time of the sample as being midway through the local
measurement period. An analysis assuming constant relative measurement period. An analysis assuming constant relative
@@ -809,14 +940,14 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
skew = (source_freq_hi - source_freq_lo) / 2.0; skew = (source_freq_hi - source_freq_lo) / 2.0;
/* and then calculate peer dispersion */ /* and then calculate peer dispersion */
epsilon = LCL_GetSysPrecisionAsQuantum() + now_err + skew * local_interval; epsilon = LCL_GetSysPrecisionAsQuantum() + now_err + skew * fabs(local_interval);
} else { } else {
/* If test3 failed, we probably can't calculate these quantities /* If test3 failed, we probably can't calculate these quantities
properly (e.g. for the first sample received in a peering properly (e.g. for the first sample received in a peering
connection). */ connection). */
theta = delta = epsilon = 0.0; theta = delta = epsilon = 0.0;
sample_time = *now;
} }
peer_distance = epsilon + 0.5 * fabs(delta); peer_distance = epsilon + 0.5 * fabs(delta);
@@ -856,8 +987,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
the standard deviation of the offsets in the register is less than an the standard deviation of the offsets in the register is less than an
administrator-defined value or the difference between measured offset administrator-defined value or the difference between measured offset
and predicted offset is larger than the increase in delay */ and predicted offset is larger than the increase in delay */
if (!SRC_IsGoodSample(inst->source, -theta, delta, inst->max_delay_dev_ratio, if (!SRC_IsGoodSample(inst->source, -theta, fabs(delta),
LCL_GetMaxClockError(), &sample_time)) { inst->max_delay_dev_ratio, LCL_GetMaxClockError(), &sample_time)) {
test4c = 0; /* Failed */ test4c = 0; /* Failed */
} else { } else {
test4c = 1; /* Success */ test4c = 1; /* Success */
@@ -926,7 +1057,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
/* Test 8 checks that the root delay and dispersion quoted in /* Test 8 checks that the root delay and dispersion quoted in
the packet are appropriate */ the packet are appropriate */
if ((fabs(pkt_root_delay) >= NTP_MAX_DISPERSION) || if ((pkt_root_delay >= NTP_MAX_DISPERSION) ||
(pkt_root_dispersion >= NTP_MAX_DISPERSION)) { (pkt_root_dispersion >= NTP_MAX_DISPERSION)) {
test8 = 0; /* Failed */ test8 = 0; /* Failed */
} else { } else {
@@ -934,7 +1065,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
} }
/* Check for Kiss-of-Death */ /* Check for Kiss-of-Death */
if (message->stratum > NTP_MAX_STRATUM && !source_is_synchronized) { if (!test7i && !source_is_synchronized) {
if (!memcmp(&message->reference_id, "RATE", 4)) if (!memcmp(&message->reference_id, "RATE", 4))
kod_rate = 1; kod_rate = 1;
} }
@@ -946,7 +1077,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
valid_header = test5 && test6 && test7i && test8; valid_header = test5 && test6 && test7i && test8;
good_header = valid_header && test7ii; good_header = valid_header && test7ii;
root_delay = pkt_root_delay + delta; root_delay = pkt_root_delay + fabs(delta);
root_dispersion = pkt_root_dispersion + epsilon; root_dispersion = pkt_root_dispersion + epsilon;
#ifdef TRACEON #ifdef TRACEON
@@ -981,7 +1112,31 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
LOG(LOGS_INFO, LOGF_NtpCore, "kod_rate=%d valid_kod=%d", kod_rate, valid_kod); LOG(LOGS_INFO, LOGF_NtpCore, "kod_rate=%d valid_kod=%d", kod_rate, valid_kod);
#endif #endif
/* Reduce polling rate if KoD RATE was received */
if (kod_rate && valid_kod) {
if (message->poll > inst->minpoll) {
inst->minpoll = message->poll;
if (inst->minpoll > inst->maxpoll)
inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll;
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d",
UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
/* Stop ongoing burst */
if (inst->opmode == MD_BURST_WAS_OFFLINE || inst->opmode == MD_BURST_WAS_ONLINE) {
inst->burst_good_samples_to_go = 0;
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s, burst sampling stopped",
UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
requeue_transmit = 1;
}
if (valid_header && valid_data) { if (valid_header && valid_data) {
inst->remote_poll = message->poll;
inst->remote_stratum = message->stratum;
inst->tx_count = 0; inst->tx_count = 0;
SRC_UpdateReachability(inst->source, 1); SRC_UpdateReachability(inst->source, 1);
@@ -995,15 +1150,14 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
} else { } else {
SRC_UnsetSelectable(inst->source); SRC_UnsetSelectable(inst->source);
} }
}
if (good_data) {
/* Do this before we accumulate a new sample into the stats registers, obviously */ /* Do this before we accumulate a new sample into the stats registers, obviously */
estimated_offset = SRC_PredictOffset(inst->source, &sample_time); estimated_offset = SRC_PredictOffset(inst->source, &sample_time);
if (valid_header && good_data) {
SRC_AccumulateSample(inst->source, SRC_AccumulateSample(inst->source,
&sample_time, &sample_time,
theta, delta, epsilon, theta, fabs(delta), epsilon,
root_delay, root_dispersion, root_delay, root_dispersion,
message->stratum, (NTP_Leap) pkt_leap); message->stratum, (NTP_Leap) pkt_leap);
@@ -1012,167 +1166,45 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
not tracking the peer at all well, so we back off the sampling not tracking the peer at all well, so we back off the sampling
rate depending on just how bad the situation is. */ rate depending on just how bad the situation is. */
error_in_estimate = fabs(-theta - estimated_offset); error_in_estimate = fabs(-theta - estimated_offset);
/* Now update the polling interval */ /* Now update the polling interval */
adjust_poll(inst, get_poll_adj(inst, error_in_estimate, peer_distance));
if (error_in_estimate > peer_distance) { /* If we're in burst mode, check whether the burst is completed and
int shift = 0; revert to the previous mode */
unsigned long temp = (int)(error_in_estimate / peer_distance); switch (inst->opmode) {
do { case MD_BURST_WAS_ONLINE:
shift++; case MD_BURST_WAS_OFFLINE:
temp>>=1; --inst->burst_good_samples_to_go;
} while (temp); if (inst->burst_good_samples_to_go <= 0) {
if (inst->opmode == MD_BURST_WAS_ONLINE)
poll_adj = -shift - inst->poll_score + 0.5; inst->opmode = MD_ONLINE;
else
take_offline(inst);
}
break;
default:
break;
}
} else { } else {
int samples = SRC_Samples(inst->source);
/* Adjust polling interval so that the number of sourcestats samples
remains close to the target value */
poll_adj = ((double)samples / inst->poll_target - 1.0) / inst->poll_target;
/* Use higher gain when decreasing the interval */
if (samples < inst->poll_target) {
poll_adj *= 2.0;
}
}
adjust_poll(inst, poll_adj);
} else if (valid_header && valid_data) {
/* Slowly increase the polling interval if we can't get good_data */ /* Slowly increase the polling interval if we can't get good_data */
adjust_poll(inst, 0.1); adjust_poll(inst, 0.1);
} }
/* Reduce polling rate if KoD RATE was received */
if (kod_rate && valid_kod) {
if (inst->remote_poll > inst->minpoll) {
inst->minpoll = inst->remote_poll;
if (inst->minpoll > inst->maxpoll)
inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll;
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
/* Stop ongoing burst */
if (inst->opmode == MD_BURST_WAS_OFFLINE || inst->opmode == MD_BURST_WAS_ONLINE) {
inst->burst_good_samples_to_go = 0;
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s, burst sampling stopped", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
}
/* If we're in burst mode, check whether the burst is completed and
revert to the previous mode */
switch (inst->opmode) {
case MD_BURST_WAS_ONLINE:
if (valid_data) {
--inst->burst_good_samples_to_go;
}
if (inst->burst_good_samples_to_go <= 0) {
inst->opmode = MD_ONLINE;
}
break;
case MD_BURST_WAS_OFFLINE:
if (valid_data) {
--inst->burst_good_samples_to_go;
}
if (inst->burst_good_samples_to_go <= 0) {
inst->opmode = MD_OFFLINE;
if (inst->timer_running) {
SCH_RemoveTimeout(inst->timeout_id);
}
inst->timer_running = 0;
}
break;
default:
break;
}
/* And now, requeue the timer.
If we're in burst mode, queue for immediate dispatch.
If we're operating in client/server mode, queue the timeout for
the poll interval hence. The fact that a timeout has been queued
in the transmit handler is immaterial - that is only done so that
we at least send something, if no reply is heard.
If we're in symmetric mode, we have to take account of the peer's
wishes, otherwise his sampling regime will fall to pieces. If
we're in client/server mode, we don't care what poll interval the
server responded with last time. */
switch (inst->opmode) {
case MD_OFFLINE:
requeue_transmit = 0;
/* Mark source unreachable */
SRC_ResetReachability(inst->source);
break; /* Even if we've received something, we don't want to
transmit back. This might be a symmetric active peer
that is trying to talk to us. */
case MD_ONLINE:
/* Normal processing, depending on whether we're in
client/server or symmetric mode */
requeue_transmit = 1; requeue_transmit = 1;
switch(inst->mode) {
case MODE_CLIENT:
/* Client/server association - aim at some randomised time
approx the poll interval away */
poll_to_use = inst->local_poll;
delay_time = (double) (1UL<<poll_to_use);
break;
case MODE_ACTIVE:
/* Symmetric active association - aim at some randomised time approx
half the poll interval away, to interleave 50-50 with the peer */
poll_to_use = (inst->local_poll < inst->remote_poll) ? inst->local_poll : inst->remote_poll;
/* Limit by min and max poll */
if (poll_to_use < inst->minpoll) poll_to_use = inst->minpoll;
if (poll_to_use > inst->maxpoll) poll_to_use = inst->maxpoll;
delay_time = (double) (1UL<<(poll_to_use - 1));
break;
default:
assert(0);
break;
} }
break; /* And now, requeue the timer. */
if (requeue_transmit && inst->opmode != MD_OFFLINE) {
delay_time = get_transmit_delay(inst, 0, local_interval);
case MD_BURST_WAS_ONLINE: if (kod_rate) {
case MD_BURST_WAS_OFFLINE:
requeue_transmit = 1;
delay_time = BURST_INTERVAL;
break;
default:
assert(0);
break;
}
if (kod_rate && valid_kod) {
/* Back off for a while */ /* Back off for a while */
delay_time += (double) (4 * (1UL << inst->minpoll)); delay_time += (double) (4 * (1UL << inst->minpoll));
} }
if (requeue_transmit) {
/* Get rid of old timeout and start a new one */ /* Get rid of old timeout and start a new one */
assert(inst->timer_running);
SCH_RemoveTimeout(inst->timeout_id); SCH_RemoveTimeout(inst->timeout_id);
inst->timeout_id = SCH_AddTimeoutInClass(delay_time, SAMPLING_SEPARATION, inst->timeout_id = SCH_AddTimeoutInClass(delay_time, SAMPLING_SEPARATION,
SAMPLING_RANDOMNESS, SAMPLING_RANDOMNESS,
@@ -1195,14 +1227,6 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
theta, delta, epsilon, theta, delta, epsilon,
pkt_root_delay, pkt_root_dispersion); pkt_root_delay, pkt_root_dispersion);
} }
/* At this point we will have to do something about trimming the
poll interval for the source and requeueing the polling timeout.
Left until the source statistics management has been written */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1245,6 +1269,11 @@ NCR_ProcessKnown
unsigned long auth_key_id; unsigned long auth_key_id;
unsigned long reply_auth_key_id; unsigned long reply_auth_key_id;
/* Ignore packets from offline sources */
if (inst->opmode == MD_OFFLINE) {
return;
}
/* Check version */ /* Check version */
version = (message->lvm >> 3) & 0x7; version = (message->lvm >> 3) & 0x7;
if (version < NTP_MIN_COMPAT_VERSION || version > NTP_MAX_COMPAT_VERSION) { if (version < NTP_MIN_COMPAT_VERSION || version > NTP_MAX_COMPAT_VERSION) {
@@ -1306,6 +1335,7 @@ NCR_ProcessKnown
} }
transmit_packet(MODE_SERVER, inst->local_poll, transmit_packet(MODE_SERVER, inst->local_poll,
version,
authenticate_reply, reply_auth_key_id, authenticate_reply, reply_auth_key_id,
&message->transmit_ts, &message->transmit_ts,
now, now,
@@ -1489,6 +1519,7 @@ NCR_ProcessUnknown
my_poll = message->poll; /* What should this be set to? Does the client actually care? */ my_poll = message->poll; /* What should this be set to? Does the client actually care? */
transmit_packet(my_mode, my_poll, transmit_packet(my_mode, my_poll,
version,
do_auth, do_auth ? key_id : 0, do_auth, do_auth ? key_id : 0,
&message->transmit_ts, /* Originate (for us) is the transmit time for the client */ &message->transmit_ts, /* Originate (for us) is the transmit time for the client */
now, /* Time we received the packet */ now, /* Time we received the packet */
@@ -1502,7 +1533,6 @@ NCR_ProcessUnknown
UTI_IPToString(&remote_addr->ip_addr), UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port); remote_addr->port);
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1513,12 +1543,14 @@ NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doff
struct timeval prev; struct timeval prev;
double delta; double delta;
prev = inst->local_rx; prev = inst->local_rx;
if (inst->local_rx.tv_sec || inst->local_rx.tv_usec)
UTI_AdjustTimeval(&inst->local_rx, when, &inst->local_rx, &delta, dfreq, doffset); UTI_AdjustTimeval(&inst->local_rx, when, &inst->local_rx, &delta, dfreq, doffset);
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "rx prev=[%s] new=[%s]", LOG(LOGS_INFO, LOGF_NtpCore, "rx prev=[%s] new=[%s]",
UTI_TimevalToString(&prev), UTI_TimevalToString(&inst->local_rx)); UTI_TimevalToString(&prev), UTI_TimevalToString(&inst->local_rx));
#endif #endif
prev = inst->local_tx; prev = inst->local_tx;
if (inst->local_tx.tv_sec || inst->local_tx.tv_usec)
UTI_AdjustTimeval(&inst->local_tx, when, &inst->local_tx, &delta, dfreq, doffset); UTI_AdjustTimeval(&inst->local_tx, when, &inst->local_tx, &delta, dfreq, doffset);
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "tx prev=[%s] new=[%s]", LOG(LOGS_INFO, LOGF_NtpCore, "tx prev=[%s] new=[%s]",
@@ -1553,6 +1585,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
break; break;
case MD_BURST_WAS_OFFLINE: case MD_BURST_WAS_OFFLINE:
inst->opmode = MD_BURST_WAS_ONLINE; inst->opmode = MD_BURST_WAS_ONLINE;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
break; break;
} }
} }
@@ -1566,17 +1599,14 @@ NCR_TakeSourceOffline(NCR_Instance inst)
case MD_ONLINE: case MD_ONLINE:
if (inst->timer_running) { if (inst->timer_running) {
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr)); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
SCH_RemoveTimeout(inst->timeout_id); take_offline(inst);
inst->timer_running = 0;
inst->opmode = MD_OFFLINE;
/* Mark source unreachable */
SRC_ResetReachability(inst->source);
} }
break; break;
case MD_OFFLINE: case MD_OFFLINE:
break; break;
case MD_BURST_WAS_ONLINE: case MD_BURST_WAS_ONLINE:
inst->opmode = MD_BURST_WAS_OFFLINE; inst->opmode = MD_BURST_WAS_OFFLINE;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
break; break;
case MD_BURST_WAS_OFFLINE: case MD_BURST_WAS_OFFLINE:
break; break;
@@ -1714,8 +1744,6 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *no
default: default:
assert(0); assert(0);
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -39,8 +39,6 @@
#include "conf.h" #include "conf.h"
#include "util.h" #include "util.h"
#include <fcntl.h>
union sockaddr_in46 { union sockaddr_in46 {
struct sockaddr_in in4; struct sockaddr_in in4;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@@ -212,8 +210,10 @@ prepare_socket(int family)
#endif #endif
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) { if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
LOG_FATAL(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)); family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
close(sock_fd);
return -1;
} }
/* Register handler for read events on the socket */ /* Register handler for read events on the socket */
@@ -231,17 +231,25 @@ prepare_socket(int family)
return sock_fd; return sock_fd;
} }
/* ================================================== */
void void
NIO_Initialise(void) NIO_Initialise(int family)
{ {
assert(!initialised); assert(!initialised);
initialised = 1; initialised = 1;
do_size_checks(); do_size_checks();
if (family == IPADDR_UNSPEC || family == IPADDR_INET4)
sock_fd4 = prepare_socket(AF_INET); sock_fd4 = prepare_socket(AF_INET);
else
sock_fd4 = -1;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (family == IPADDR_UNSPEC || family == IPADDR_INET6)
sock_fd6 = prepare_socket(AF_INET6); sock_fd6 = prepare_socket(AF_INET6);
else
sock_fd6 = -1;
#endif #endif
if (sock_fd4 < 0 if (sock_fd4 < 0
@@ -251,8 +259,6 @@ NIO_Initialise(void)
) { ) {
LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket"); LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -273,7 +279,6 @@ NIO_Finalise(void)
sock_fd6 = -1; sock_fd6 = -1;
#endif #endif
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -291,7 +296,7 @@ read_from_socket(void *anything)
ReceiveBuffer message; ReceiveBuffer message;
union sockaddr_in46 where_from; union sockaddr_in46 where_from;
unsigned int flags = 0; unsigned int flags = 0;
struct timeval now; struct timeval now, now_raw;
double now_err; double now_err;
NTP_Remote_Address remote_addr; NTP_Remote_Address remote_addr;
char cmsgbuf[256]; char cmsgbuf[256];
@@ -301,7 +306,7 @@ read_from_socket(void *anything)
assert(initialised); assert(initialised);
SCH_GetFileReadyTime(&now, &now_err); SCH_GetLastEventTime(&now, &now_err, &now_raw);
iov.iov_base = message.arbitrary; iov.iov_base = message.arbitrary;
iov.iov_len = sizeof(message); iov.iov_len = sizeof(message);
@@ -371,7 +376,9 @@ read_from_socket(void *anything)
struct timeval tv; struct timeval tv;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv)); memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
LCL_CookTime(&tv, &now, &now_err);
/* This should be more accurate than LCL_CookTime(&now_raw,...) */
UTI_AddDiffToTimeval(&now, &now_raw, &tv, &now);
} }
#endif #endif
} }
@@ -386,8 +393,6 @@ read_from_socket(void *anything)
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -502,8 +507,6 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s", LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno)); UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -32,7 +32,7 @@
#include "addressing.h" #include "addressing.h"
/* Function to initialise the module. */ /* Function to initialise the module. */
extern void NIO_Initialise(void); extern void NIO_Initialise(int family);
/* Function to finalise the module */ /* Function to finalise the module */
extern void NIO_Finalise(void); extern void NIO_Finalise(void);

View File

@@ -103,8 +103,6 @@ NSR_Initialise(void)
initialised = 1; initialised = 1;
LCL_AddParameterChangeHandler(slew_sources, NULL); LCL_AddParameterChangeHandler(slew_sources, NULL);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -113,7 +111,6 @@ void
NSR_Finalise(void) NSR_Finalise(void)
{ {
initialised = 0; initialised = 0;
return; /* Nothing to do yet */
} }
/* ================================================== */ /* ================================================== */
@@ -179,8 +176,6 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
*found = 0; *found = 0;
*slot = hash; *slot = hash;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -670,8 +665,6 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
for (us = unresolved_sources; us; us = us->next) { for (us = unresolved_sources; us; us = us->next) {
report->unresolved++; report->unresolved++;
} }
return;
} }

View File

@@ -452,7 +452,7 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
filter_add_sample(&instance->filter, &cooked_time, offset, dispersion); filter_add_sample(&instance->filter, &cooked_time, offset, dispersion);
instance->leap_status = LEAP_Normal; instance->leap_status = LEAP_Normal;
log_sample(instance, &cooked_time, 0, 1, second, offset, dispersion); log_sample(instance, &cooked_time, 0, 1, offset + correction - instance->offset, offset, dispersion);
/* for logging purposes */ /* for logging purposes */
if (!instance->driver->poll) if (!instance->driver->poll)

View File

@@ -27,13 +27,12 @@
#include "config.h" #include "config.h"
#include "sysincl.h"
#include "refclock.h" #include "refclock.h"
#include "logging.h" #include "logging.h"
#include "util.h" #include "util.h"
#include <sys/types.h>
#include <sys/shm.h>
#define SHMKEY 0x4e545030 #define SHMKEY 0x4e545030
struct shmTime { struct shmTime {
@@ -45,7 +44,7 @@ struct shmTime {
* use values * use values
* clear valid * clear valid
*/ */
int count; volatile int count;
time_t clockTimeStampSec; time_t clockTimeStampSec;
int clockTimeStampUSec; int clockTimeStampUSec;
time_t receiveTimeStampSec; time_t receiveTimeStampSec;
@@ -53,8 +52,10 @@ struct shmTime {
int leap; int leap;
int precision; int precision;
int nsamples; int nsamples;
int valid; volatile int valid;
int dummy[10]; int clockTimeStampNSec;
int receiveTimeStampNSec;
int dummy[8];
}; };
static int shm_initialise(RCL_Instance instance) { static int shm_initialise(RCL_Instance instance) {
@@ -89,7 +90,7 @@ static void shm_finalise(RCL_Instance instance)
static int shm_poll(RCL_Instance instance) static int shm_poll(RCL_Instance instance)
{ {
struct timeval tv1, tv2; struct timeval tv;
struct shmTime t, *shm; struct shmTime t, *shm;
double offset; double offset;
@@ -107,13 +108,17 @@ static int shm_poll(RCL_Instance instance)
shm->valid = 0; shm->valid = 0;
tv1.tv_sec = t.receiveTimeStampSec; tv.tv_sec = t.receiveTimeStampSec;
tv1.tv_usec = t.receiveTimeStampUSec; tv.tv_usec = t.receiveTimeStampUSec;
tv2.tv_sec = t.clockTimeStampSec;
tv2.tv_usec = t.clockTimeStampUSec;
UTI_DiffTimevalsToDouble(&offset, &tv2, &tv1); offset = t.clockTimeStampSec - t.receiveTimeStampSec;
return RCL_AddSample(instance, &tv1, offset, t.leap); if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec &&
t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec)
offset += (t.clockTimeStampNSec - t.receiveTimeStampNSec) * 1e-9;
else
offset += (t.clockTimeStampUSec - t.receiveTimeStampUSec) * 1e-6;
return RCL_AddSample(instance, &tv, offset, t.leap);
} }
RefclockDriver RCL_SHM_driver = { RefclockDriver RCL_SHM_driver = {

View File

@@ -27,16 +27,13 @@
#include "config.h" #include "config.h"
#include "sysincl.h"
#include "refclock.h" #include "refclock.h"
#include "logging.h" #include "logging.h"
#include "util.h" #include "util.h"
#include "sched.h" #include "sched.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCK_MAGIC 0x534f434b #define SOCK_MAGIC 0x534f434b
struct sock_sample { struct sock_sample {

View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2012 * Copyright (C) Miroslav Lichvar 2009-2013
* *
* 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
@@ -39,6 +39,9 @@
/* ================================================== */ /* ================================================== */
/* The minimum allowed skew */
#define MIN_SKEW 1.0e-12
static int are_we_synchronised; static int are_we_synchronised;
static int enable_local_stratum; static int enable_local_stratum;
static int local_stratum; static int local_stratum;
@@ -149,7 +152,6 @@ void
REF_Initialise(void) REF_Initialise(void)
{ {
FILE *in; FILE *in;
char line[1024];
double file_freq_ppm, file_skew_ppm; double file_freq_ppm, file_skew_ppm;
double our_frequency_ppm; double our_frequency_ppm;
@@ -169,17 +171,15 @@ REF_Initialise(void)
if (drift_file) { if (drift_file) {
in = fopen(drift_file, "r"); in = fopen(drift_file, "r");
if (in) { if (in) {
if (fgets(line, sizeof(line), in)) { if (fscanf(in, "%lf%lf", &file_freq_ppm, &file_skew_ppm) == 2) {
if (sscanf(line, "%lf%lf", &file_freq_ppm, &file_skew_ppm) == 2) {
/* We have read valid data */ /* We have read valid data */
our_frequency_ppm = file_freq_ppm; our_frequency_ppm = file_freq_ppm;
our_skew = 1.0e-6 * file_skew_ppm; our_skew = 1.0e-6 * file_skew_ppm;
LOG(LOGS_INFO, LOGF_Reference, "Frequency %.3f +/- %.3f ppm read from %s", file_freq_ppm, file_skew_ppm, drift_file); if (our_skew < MIN_SKEW)
our_skew = MIN_SKEW;
LOG(LOGS_INFO, LOGF_Reference, "Frequency %.3f +/- %.3f ppm read from %s",
file_freq_ppm, file_skew_ppm, drift_file);
LCL_SetAbsoluteFrequency(our_frequency_ppm); LCL_SetAbsoluteFrequency(our_frequency_ppm);
} else {
LOG(LOGS_WARN, LOGF_Reference, "Could not parse valid frequency and skew from driftfile %s",
drift_file);
}
} else { } else {
LOG(LOGS_WARN, LOGF_Reference, "Could not read valid frequency and skew from driftfile %s", LOG(LOGS_WARN, LOGF_Reference, "Could not read valid frequency and skew from driftfile %s",
drift_file); drift_file);
@@ -196,7 +196,7 @@ REF_Initialise(void)
} }
logfileid = CNF_GetLogTracking() ? LOG_FileOpen("tracking", logfileid = CNF_GetLogTracking() ? LOG_FileOpen("tracking",
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset L") " Date (UTC) Time IP Address St Freq ppm Skew ppm Offset L Co Offset sd Rem. corr.")
: -1; : -1;
max_update_skew = fabs(CNF_GetMaxUpdateSkew()) * 1.0e-6; max_update_skew = fabs(CNF_GetMaxUpdateSkew()) * 1.0e-6;
@@ -244,8 +244,6 @@ REF_Initialise(void)
/* Make first entry in tracking log */ /* Make first entry in tracking log */
REF_SetUnsynchronised(); REF_SetUnsynchronised();
return;
} }
/* ================================================== */ /* ================================================== */
@@ -264,7 +262,6 @@ REF_Finalise(void)
Free(fb_drifts); Free(fb_drifts);
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -314,9 +311,13 @@ update_drift_file(double freq_ppm, double skew)
} }
/* Write the frequency and skew parameters in ppm */ /* Write the frequency and skew parameters in ppm */
fprintf(out, "%20.4f %20.4f\n", freq_ppm, 1.0e6 * skew); if ((fprintf(out, "%20.6f %20.6f\n", freq_ppm, 1.0e6 * skew) < 0) |
fclose(out)) {
fclose(out); Free(temp_drift_file);
LOG(LOGS_WARN, LOGF_Reference, "Could not write to temporary driftfile %s.tmp",
drift_file);
return;
}
/* Clone the file attributes from the existing file if there is one. */ /* Clone the file attributes from the existing file if there is one. */
@@ -332,7 +333,7 @@ update_drift_file(double freq_ppm, double skew)
if (rename(temp_drift_file,drift_file)) { if (rename(temp_drift_file,drift_file)) {
unlink(temp_drift_file); unlink(temp_drift_file);
Free(temp_drift_file); Free(temp_drift_file);
LOG(LOGS_WARN, LOGF_Reference, "Could not replace old driftfile %s with new one %s.tmp (%d)", LOG(LOGS_WARN, LOGF_Reference, "Could not replace old driftfile %s with new one %s.tmp",
drift_file,drift_file); drift_file,drift_file);
return; return;
} }
@@ -457,12 +458,11 @@ schedule_fb_drift(struct timeval *now)
#define S_MAX_USER_LEN "128" #define S_MAX_USER_LEN "128"
static void static void
maybe_log_offset(double offset) maybe_log_offset(double offset, time_t now)
{ {
double abs_offset; double abs_offset;
FILE *p; FILE *p;
char buffer[BUFLEN], host[BUFLEN]; char buffer[BUFLEN], host[BUFLEN];
time_t now;
struct tm stm; struct tm stm;
abs_offset = fabs(offset); abs_offset = fabs(offset);
@@ -484,7 +484,6 @@ maybe_log_offset(double offset)
} }
fprintf(p, "Subject: chronyd reports change to system clock on node [%s]\n", host); fprintf(p, "Subject: chronyd reports change to system clock on node [%s]\n", host);
fputs("\n", p); fputs("\n", p);
now = time(NULL);
stm = *localtime(&now); stm = *localtime(&now);
strftime(buffer, sizeof(buffer), "On %A, %d %B %Y\n with the system clock reading %H:%M:%S (%Z)", &stm); strftime(buffer, sizeof(buffer), "On %A, %d %B %Y\n with the system clock reading %H:%M:%S (%Z)", &stm);
fputs(buffer, p); fputs(buffer, p);
@@ -648,12 +647,16 @@ update_leap_status(NTP_Leap leap, time_t now)
/* ================================================== */ /* ================================================== */
static void static void
write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap, double freq, double skew, double offset) write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap,
double freq, double skew, double offset, int combined_sources,
double offset_sd, double uncorrected_offset)
{ {
const char leap_codes[4] = {'N', '+', '-', '?'}; const char leap_codes[4] = {'N', '+', '-', '?'};
if (logfileid != -1) { if (logfileid != -1) {
LOG_FileWrite(logfileid, "%s %-15s %2d %10.3f %10.3f %10.3e %1c", LOG_FileWrite(logfileid, "%s %-15s %2d %10.3f %10.3f %10.3e %1c %2d %10.3e %10.3e",
UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew, offset, leap_codes[leap]); UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew,
offset, leap_codes[leap], combined_sources, offset_sd,
uncorrected_offset);
} }
} }
@@ -662,6 +665,7 @@ write_log(struct timeval *ref_time, char *ref, int stratum, NTP_Leap leap, doubl
void void
REF_SetReference(int stratum, REF_SetReference(int stratum,
NTP_Leap leap, NTP_Leap leap,
int combined_sources,
uint32_t ref_id, uint32_t ref_id,
IPAddr *ref_ip, IPAddr *ref_ip,
struct timeval *ref_time, struct timeval *ref_time,
@@ -684,15 +688,14 @@ REF_SetReference(int stratum,
double update_interval; double update_interval;
double elapsed; double elapsed;
double correction_rate; double correction_rate;
struct timeval now, raw_now; double uncorrected_offset;
struct timeval now, raw_now, ev_now, ev_raw_now;
assert(initialised); assert(initialised);
/* Avoid getting NaNs */ /* Guard against dividing by zero */
if (skew < 1e-12) if (skew < MIN_SKEW)
skew = 1e-12; skew = MIN_SKEW;
if (our_skew < 1e-12)
our_skew = 1e-12;
/* If we get a serious rounding error in the source stats regression /* If we get a serious rounding error in the source stats regression
processing, there is a remote chance that the skew argument is a processing, there is a remote chance that the skew argument is a
@@ -713,15 +716,19 @@ REF_SetReference(int stratum,
} }
LCL_ReadRawTime(&raw_now); LCL_ReadRawTime(&raw_now);
LCL_CookTime(&raw_now, &now, NULL);
/* This is cheaper than calling LCL_CookTime */
SCH_GetLastEventTime(&ev_now, NULL, &ev_raw_now);
UTI_DiffTimevalsToDouble(&uncorrected_offset, &ev_now, &ev_raw_now);
UTI_AddDoubleToTimeval(&raw_now, uncorrected_offset, &now);
UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time); UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time);
our_offset = offset + elapsed * frequency; our_offset = offset + elapsed * frequency;
if (!is_offset_ok(offset)) if (!is_offset_ok(our_offset))
return; return;
are_we_synchronised = 1; are_we_synchronised = leap != LEAP_Unsynchronised ? 1 : 0;
our_stratum = stratum + 1; our_stratum = stratum + 1;
our_ref_id = ref_id; our_ref_id = ref_id;
if (ref_ip) if (ref_ip)
@@ -732,8 +739,6 @@ REF_SetReference(int stratum,
our_root_delay = root_delay; our_root_delay = root_delay;
our_root_dispersion = root_dispersion; our_root_dispersion = root_dispersion;
update_leap_status(leap, raw_now.tv_sec);
if (last_ref_update.tv_sec) { if (last_ref_update.tv_sec) {
UTI_DiffTimevalsToDouble(&update_interval, &now, &last_ref_update); UTI_DiffTimevalsToDouble(&update_interval, &now, &last_ref_update);
if (update_interval < 0.0) if (update_interval < 0.0)
@@ -759,9 +764,9 @@ REF_SetReference(int stratum,
correction_rate = correction_time_ratio * 0.5 * offset_sd * update_interval; correction_rate = correction_time_ratio * 0.5 * offset_sd * update_interval;
/* Eliminate updates that are based on totally unreliable frequency /* Eliminate updates that are based on totally unreliable frequency
information */ information. Ignore this limit with manual reference. */
if (fabs(skew) < max_update_skew) { if (fabs(skew) < max_update_skew || leap == LEAP_Unsynchronised) {
previous_skew = our_skew; previous_skew = our_skew;
new_skew = skew; new_skew = skew;
@@ -773,9 +778,10 @@ REF_SetReference(int stratum,
the local module. */ the local module. */
new_freq = frequency; new_freq = frequency;
/* Set new frequency based on weighted average of old and new skew. */ /* Set new frequency based on weighted average of old and new skew. With
manual reference the old frequency has no weight. */
old_weight = 1.0 / Sqr(previous_skew); old_weight = leap != LEAP_Unsynchronised ? 1.0 / Sqr(previous_skew) : 0.0;
new_weight = 3.0 / Sqr(new_skew); new_weight = 3.0 / Sqr(new_skew);
sum_weight = old_weight + new_weight; sum_weight = old_weight + new_weight;
@@ -791,7 +797,6 @@ REF_SetReference(int stratum,
our_residual_freq = new_freq - our_frequency; our_residual_freq = new_freq - our_frequency;
maybe_log_offset(our_offset);
LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset, correction_rate); LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset, correction_rate);
} else { } else {
@@ -799,12 +804,13 @@ REF_SetReference(int stratum,
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Reference, "Skew %f too large to track, offset=%f", skew, our_offset); LOG(LOGS_INFO, LOGF_Reference, "Skew %f too large to track, offset=%f", skew, our_offset);
#endif #endif
maybe_log_offset(our_offset);
LCL_AccumulateOffset(our_offset, correction_rate); LCL_AccumulateOffset(our_offset, correction_rate);
our_residual_freq = frequency; our_residual_freq = frequency;
} }
update_leap_status(leap, raw_now.tv_sec);
maybe_log_offset(our_offset, raw_now.tv_sec);
maybe_make_step(); maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency(); abs_freq_ppm = LCL_ReadAbsoluteFrequency();
@@ -815,7 +821,10 @@ REF_SetReference(int stratum,
our_leap_status, our_leap_status,
abs_freq_ppm, abs_freq_ppm,
1.0e6*our_skew, 1.0e6*our_skew,
our_offset); our_offset,
combined_sources,
offset_sd,
uncorrected_offset);
if (drift_file) { if (drift_file) {
/* Update drift file at most once per hour */ /* Update drift file at most once per hour */
@@ -842,12 +851,6 @@ REF_SetReference(int stratum,
avg2_moving = 1; avg2_moving = 1;
avg2_offset = our_offset * our_offset; avg2_offset = our_offset * our_offset;
} }
/* And now set the freq and offset to zero */
our_frequency = 0.0;
our_offset = 0.0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -861,33 +864,13 @@ REF_SetManualReference
double skew double skew
) )
{ {
double abs_freq_ppm; 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
... */ ... */
are_we_synchronised = 0; REF_SetReference(0, LEAP_Unsynchronised, 1, manual_refid, NULL,
ref_time, offset, 0.0, frequency, skew, 0.0, 0.0);
our_skew = skew;
our_residual_freq = 0.0;
maybe_log_offset(offset);
LCL_AccumulateFrequencyAndOffset(frequency, offset, 0.0);
maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
write_log(ref_time,
"127.127.1.1",
our_stratum,
our_leap_status,
abs_freq_ppm,
1.0e6*our_skew,
offset);
if (drift_file) {
update_drift_file(abs_freq_ppm, our_skew);
}
} }
/* ================================================== */ /* ================================================== */
@@ -896,11 +879,14 @@ void
REF_SetUnsynchronised(void) REF_SetUnsynchronised(void)
{ {
/* Variables required for logging to statistics log */ /* Variables required for logging to statistics log */
struct timeval now; struct timeval now, now_raw;
double uncorrected_offset;
assert(initialised); assert(initialised);
LCL_ReadCookedTime(&now, NULL); /* This is cheaper than calling LCL_CookTime */
SCH_GetLastEventTime(&now, NULL, &now_raw);
UTI_DiffTimevalsToDouble(&uncorrected_offset, &now, &now_raw);
if (fb_drifts) { if (fb_drifts) {
schedule_fb_drift(&now); schedule_fb_drift(&now);
@@ -915,7 +901,10 @@ REF_SetUnsynchronised(void)
our_leap_status, our_leap_status,
LCL_ReadAbsoluteFrequency(), LCL_ReadAbsoluteFrequency(),
1.0e6*our_skew, 1.0e6*our_skew,
0.0); 0.0,
0,
0.0,
uncorrected_offset);
} }
/* ================================================== */ /* ================================================== */

View File

@@ -105,6 +105,7 @@ extern void REF_SetReference
( (
int stratum, int stratum,
NTP_Leap leap, NTP_Leap leap,
int combined_sources,
uint32_t ref_id, uint32_t ref_id,
IPAddr *ref_ip, IPAddr *ref_ip,
struct timeval *ref_time, struct timeval *ref_time,

View File

@@ -28,11 +28,7 @@
#include "config.h" #include "config.h"
#include <assert.h> #include "sysincl.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "regress.h" #include "regress.h"
#include "logging.h" #include "logging.h"
@@ -103,8 +99,6 @@ RGR_WeightedRegression
*sb0 = sqrt(*s2 / W + aa * aa); *sb0 = sqrt(*s2 / W + aa * aa);
*s2 *= (n / W); /* Giving weighted average of variances */ *s2 *= (n / W); /* Giving weighted average of variances */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -228,6 +222,9 @@ RGR_FindBestRegression
int m, /* number of extra samples in x and y arrays int m, /* number of extra samples in x and y arrays
(negative index) which can be used to (negative index) which can be used to
extend runs test */ extend runs test */
int min_samples, /* minimum number of samples to be kept after
changing the starting index to pass the runs
test */
/* And now the results */ /* And now the results */
@@ -299,7 +296,9 @@ RGR_FindBestRegression
/* Count number of runs */ /* Count number of runs */
nruns = n_runs_from_residuals(resid, n - resid_start); nruns = n_runs_from_residuals(resid, n - resid_start);
if (nruns > critical_runs[n - resid_start] || n - start <= MIN_SAMPLES_FOR_REGRESS) { if (nruns > critical_runs[n - resid_start] ||
n - start <= MIN_SAMPLES_FOR_REGRESS ||
n - start <= min_samples) {
if (start != resid_start) { if (start != resid_start) {
/* Ignore extra samples in returned nruns */ /* Ignore extra samples in returned nruns */
nruns = n_runs_from_residuals(resid - resid_start + start, n - start); nruns = n_runs_from_residuals(resid - resid_start + start, n - start);
@@ -422,7 +421,7 @@ find_ordered_entry(double *x, int n, int index)
{ {
int flags[MAX_POINTS]; int flags[MAX_POINTS];
bzero(flags, n * sizeof(int)); memset(flags, 0, n * sizeof(int));
return find_ordered_entry_with_flags(x, n, index, flags); return find_ordered_entry_with_flags(x, n, index, flags);
} }
#endif #endif
@@ -588,7 +587,7 @@ RGR_FindBestRobustRegression
Estimate standard deviation of b and expand range about b based Estimate standard deviation of b and expand range about b based
on that. */ on that. */
sb = sqrt(s2 * W/V); sb = sqrt(s2 * W/V);
if (sb > 0.0) { if (sb > tol) {
incr = 3.0 * sb; incr = 3.0 * sb;
} else { } else {
incr = 3.0 * tol; incr = 3.0 * tol;
@@ -598,6 +597,11 @@ RGR_FindBestRobustRegression
bhi = b; bhi = b;
do { do {
/* Make sure incr is significant to blo and bhi */
while (bhi + incr == bhi || blo - incr == blo) {
incr *= 2;
}
blo -= incr; blo -= incr;
bhi += incr; bhi += incr;
@@ -605,8 +609,8 @@ RGR_FindBestRobustRegression
eval_robust_residual(x + start, y + start, n_points, blo, &a, &rlo); eval_robust_residual(x + start, y + start, n_points, blo, &a, &rlo);
eval_robust_residual(x + start, y + start, n_points, bhi, &a, &rhi); eval_robust_residual(x + start, y + start, n_points, bhi, &a, &rhi);
} while (rlo * rhi > 0.0); /* fn vals have same sign, i.e. root not } while (rlo * rhi >= 0.0); /* fn vals have same sign or one is zero,
in interval. */ i.e. root not in interval (rlo, rhi). */
/* OK, so the root for b lies in (blo, bhi). Start bisecting */ /* OK, so the root for b lies in (blo, bhi). Start bisecting */
do { do {
@@ -623,7 +627,7 @@ RGR_FindBestRobustRegression
} else { } else {
assert(0); assert(0);
} }
} while ((bhi - blo) > tol); } while ((bhi - blo) > tol && (bmid - blo) * (bhi - bmid) > 0.0);
*b0 = a; *b0 = a;
*b1 = bmid; *b1 = bmid;

View File

@@ -80,6 +80,9 @@ RGR_FindBestRegression
int m, /* number of extra samples in x and y arrays int m, /* number of extra samples in x and y arrays
(negative index) which can be used to (negative index) which can be used to
extend runs test */ extend runs test */
int min_samples, /* minimum number of samples to be kept after
changing the starting index to pass the runs
test */
/* And now the results */ /* And now the results */

View File

@@ -37,7 +37,7 @@ typedef struct {
int stratum; int stratum;
int poll; int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE} state; enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE, RPT_OUTLIER} state;
enum {RPT_NORMAL, RPT_PREFER, RPT_NOSELECT} sel_option; enum {RPT_NORMAL, RPT_PREFER, RPT_NOSELECT} sel_option;
int reachability; int reachability;

3
rtc.c
View File

@@ -108,9 +108,6 @@ RTC_Initialise(void)
} else { } else {
driver_initialised = 0; driver_initialised = 0;
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -29,25 +29,8 @@
#include "config.h" #include "config.h"
#if defined LINUX #include "sysincl.h"
#ifdef sparc
#define __KERNEL__
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include "logging.h" #include "logging.h"
@@ -189,7 +172,6 @@ discard_samples(int new_first)
memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timeval)); memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timeval));
n_samples = n_to_save; n_samples = n_to_save;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -217,8 +199,6 @@ accumulate_sample(time_t rtc, struct timeval *sys)
++n_samples_since_regression; ++n_samples_since_regression;
} }
++n_samples; ++n_samples;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -470,10 +450,14 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
} }
/* Gain rate is written out in ppm */ /* Gain rate is written out in ppm */
fprintf(out, "%1d %ld %.6f %.3f\n", if ((fprintf(out, "%1d %ld %.6f %.3f\n",
valid,ref_time, offset, 1.0e6 * rate); valid,ref_time, offset, 1.0e6 * rate) < 0) |
fclose(out)) {
fclose(out); Free(temp_coefs_file_name);
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not write to temporary RTC file %s.tmp",
coefs_file_name);
return RTC_ST_BADFILE;
}
/* Clone the file attributes from the existing file if there is one. */ /* Clone the file attributes from the existing file if there is one. */
@@ -675,8 +659,6 @@ handle_initial_trim(void)
(after_init_hook)(after_init_hook_arg); (after_init_hook)(after_init_hook_arg);
operating_mode = OM_NORMAL; operating_mode = OM_NORMAL;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -791,7 +773,7 @@ read_from_device(void *any)
/* Read RTC time, sandwiched between two polls of the system clock /* Read RTC time, sandwiched between two polls of the system clock
so we can bound any error. */ so we can bound any error. */
SCH_GetFileReadyTime(&sys_time, NULL); SCH_GetLastEventTime(&sys_time, NULL, NULL);
status = ioctl(fd, RTC_RD_TIME, &rtc_raw); status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status < 0) { if (status < 0) {
@@ -1069,7 +1051,3 @@ RTC_Linux_Trim(void)
return 1; return 1;
} }
/* ================================================== */
#endif /* defined LINUX */

View File

@@ -28,8 +28,6 @@
#include "reports.h" #include "reports.h"
#if defined LINUX
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 void RTC_Linux_TimePreInit(void); extern void RTC_Linux_TimePreInit(void);
@@ -44,6 +42,4 @@ extern int RTC_Linux_Trim(void);
extern void RTC_Linux_CycleLogFile(void); extern void RTC_Linux_CycleLogFile(void);
#endif /* defined LINUX */
#endif /* _GOT_RTC_LINUX_H */ #endif /* _GOT_RTC_LINUX_H */

50
sched.c
View File

@@ -131,8 +131,6 @@ handle_slew(struct timeval *raw,
void void
SCH_Initialise(void) SCH_Initialise(void)
{ {
struct timeval tv;
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
n_read_fds = 0; n_read_fds = 0;
@@ -146,12 +144,12 @@ SCH_Initialise(void)
LCL_AddParameterChangeHandler(handle_slew, NULL); LCL_AddParameterChangeHandler(handle_slew, NULL);
LCL_ReadRawTime(&tv); LCL_ReadRawTime(&last_select_ts_raw);
srandom(tv.tv_sec * tv.tv_usec); last_select_ts = last_select_ts_raw;
srandom(last_select_ts.tv_sec << 16 ^ last_select_ts.tv_usec);
initialised = 1; initialised = 1;
return;
} }
@@ -160,7 +158,6 @@ SCH_Initialise(void)
void void
SCH_Finalise(void) { SCH_Finalise(void) {
initialised = 0; initialised = 0;
return; /* Nothing to do for now */
} }
/* ================================================== */ /* ================================================== */
@@ -187,8 +184,6 @@ SCH_AddInputFileHandler
if ((fd + 1) > one_highest_fd) { if ((fd + 1) > one_highest_fd) {
one_highest_fd = fd + 1; one_highest_fd = fd + 1;
} }
return;
} }
@@ -219,19 +214,20 @@ SCH_RemoveInputFileHandler(int fd)
} }
one_highest_fd = fd_to_check; one_highest_fd = fd_to_check;
return;
} }
/* ================================================== */ /* ================================================== */
void void
SCH_GetFileReadyTime(struct timeval *tv, double *err) SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw)
{ {
*tv = last_select_ts; if (cooked) {
*cooked = last_select_ts;
if (err) if (err)
*err = last_select_ts_err; *err = last_select_ts_err;
}
if (raw)
*raw = last_select_ts_raw;
} }
/* ================================================== */ /* ================================================== */
@@ -265,7 +261,6 @@ release_tqe(TimerQueueEntry *node)
{ {
node->next = tqe_free_list; node->next = tqe_free_list;
tqe_free_list = node; tqe_free_list = node;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -512,12 +507,11 @@ handle_slew(struct timeval *raw,
void *anything) void *anything)
{ {
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
double delta;
int i; int i;
if (is_step_change) { if (is_step_change) {
/* We're not interested in anything else - it won't affect the /* If a step change occurs, just shift all raw time stamps by the offset */
functionality of timer event dispatching. If a step change
occurs, just shift all the timeouts by the offset */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) { for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &ptr->tv); UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &ptr->tv);
@@ -528,8 +522,9 @@ handle_slew(struct timeval *raw,
} }
UTI_AddDoubleToTimeval(&last_select_ts_raw, -doffset, &last_select_ts_raw); UTI_AddDoubleToTimeval(&last_select_ts_raw, -doffset, &last_select_ts_raw);
UTI_AddDoubleToTimeval(&last_select_ts, -doffset, &last_select_ts);
} }
UTI_AdjustTimeval(&last_select_ts, cooked, &last_select_ts, &delta, dfreq, doffset);
} }
/* ================================================== */ /* ================================================== */
@@ -566,7 +561,7 @@ void
SCH_MainLoop(void) SCH_MainLoop(void)
{ {
fd_set rd; fd_set rd;
int status; int status, errsv;
struct timeval tv, *ptv; struct timeval tv, *ptv;
struct timeval now, cooked; struct timeval now, cooked;
double err; double err;
@@ -594,12 +589,10 @@ SCH_MainLoop(void)
/* if there are no file descriptors being waited on and no /* if there are no file descriptors being waited on and no
timeout set, this is clearly ridiculous, so stop the run */ timeout set, this is clearly ridiculous, so stop the run */
assert(ptv || n_read_fds);
if (!ptv && (n_read_fds == 0)) {
LOG_FATAL(LOGF_Scheduler, "No descriptors or timeout to wait for");
}
status = select(one_highest_fd, &rd, NULL, NULL, ptv); status = select(one_highest_fd, &rd, NULL, NULL, ptv);
errsv = errno;
LCL_ReadRawTime(&now); LCL_ReadRawTime(&now);
LCL_CookTime(&now, &cooked, &err); LCL_CookTime(&now, &cooked, &err);
@@ -614,15 +607,15 @@ SCH_MainLoop(void)
last_select_ts_err = err; last_select_ts_err = err;
if (status < 0) { if (status < 0) {
assert(need_to_exit); if (!need_to_exit && errsv != EINTR) {
LOG_FATAL(LOGF_Scheduler, "select() failed : %s", strerror(errsv));
}
} else if (status > 0) { } else if (status > 0) {
/* A file descriptor is ready to read */ /* A file descriptor is ready to read */
dispatch_filehandlers(status, &rd); dispatch_filehandlers(status, &rd);
} else { } else {
assert(status == 0);
/* No descriptors readable, timeout must have elapsed. /* No descriptors readable, timeout must have elapsed.
Therefore, tv must be non-null */ Therefore, tv must be non-null */
assert(ptv); assert(ptv);
@@ -633,9 +626,6 @@ SCH_MainLoop(void)
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -58,9 +58,8 @@ extern void SCH_AddInputFileHandler
); );
extern void SCH_RemoveInputFileHandler(int fd); extern void SCH_RemoveInputFileHandler(int fd);
/* Get the time (cooked) when file descriptor became ready, intended for use /* Get the time stamp taken after a file descriptor became ready or a timeout expired */
in file handlers */ extern void SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw);
extern void SCH_GetFileReadyTime(struct timeval *tv, double *err);
/* This queues a timeout to elapse at a given (raw) local time */ /* This queues a timeout to elapse at a given (raw) local time */
extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument); extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);

142
sources.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012 * Copyright (C) Miroslav Lichvar 2011-2013
* *
* 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
@@ -44,6 +44,7 @@
#include "reports.h" #include "reports.h"
#include "nameserv.h" #include "nameserv.h"
#include "mkdirpp.h" #include "mkdirpp.h"
#include "sched.h"
/* ================================================== */ /* ================================================== */
/* Flag indicating that we are initialised */ /* Flag indicating that we are initialised */
@@ -55,10 +56,7 @@ struct SelectInfo {
int stratum; int stratum;
int select_ok; int select_ok;
double variance; double variance;
double root_delay;
double root_dispersion;
double root_distance; double root_distance;
double best_offset;
double lo_limit; double lo_limit;
double hi_limit; double hi_limit;
}; };
@@ -95,6 +93,12 @@ struct SRC_Instance_Record {
/* Reachability register */ /* Reachability register */
int reachability; int reachability;
/* Flag indicating that only few samples were accumulated so far */
int beginning;
/* Updates left before allowing combining */
int outlier;
/* Flag indicating the status of the source */ /* Flag indicating the status of the source */
SRC_Status status; SRC_Status status;
@@ -137,8 +141,12 @@ static int selected_source_index; /* Which source index is currently
/* Score needed to replace the currently selected source */ /* Score needed to replace the currently selected source */
#define SCORE_LIMIT 10.0 #define SCORE_LIMIT 10.0
/* Number of updates needed to reset the outlier status */
#define OUTLIER_PENALTY 32
static double reselect_distance; static double reselect_distance;
static double stratum_weight; static double stratum_weight;
static double combine_limit;
/* ================================================== */ /* ================================================== */
/* Forward prototype */ /* Forward prototype */
@@ -161,12 +169,11 @@ void SRC_Initialise(void) {
selected_source_index = INVALID_SOURCE; selected_source_index = INVALID_SOURCE;
reselect_distance = CNF_GetReselectDistance(); reselect_distance = CNF_GetReselectDistance();
stratum_weight = CNF_GetStratumWeight(); stratum_weight = CNF_GetStratumWeight();
combine_limit = CNF_GetCombineLimit();
initialised = 1; initialised = 1;
LCL_AddParameterChangeHandler(slew_sources, NULL); LCL_AddParameterChangeHandler(slew_sources, NULL);
LCL_AddDispersionNotifyHandler(add_dispersion, NULL); LCL_AddDispersionNotifyHandler(add_dispersion, NULL);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -176,7 +183,6 @@ void SRC_Finalise(void)
LCL_RemoveParameterChangeHandler(slew_sources, NULL); LCL_RemoveParameterChangeHandler(slew_sources, NULL);
LCL_RemoveDispersionNotifyHandler(add_dispersion, NULL); LCL_RemoveDispersionNotifyHandler(add_dispersion, NULL);
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -213,6 +219,8 @@ SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOpt
result->ip_addr = addr; result->ip_addr = addr;
result->selectable = 0; result->selectable = 0;
result->reachability = 0; result->reachability = 0;
result->beginning = 1;
result->outlier = 0;
result->status = SRC_BAD_STATS; result->status = SRC_BAD_STATS;
result->type = type; result->type = type;
result->sel_score = 1.0; result->sel_score = 1.0;
@@ -268,7 +276,6 @@ void SRC_GetFrequencyRange(SRC_Instance instance, double *lo, double *hi)
assert(initialised); assert(initialised);
SST_GetFrequencyRange(instance->stats, lo, hi); SST_GetFrequencyRange(instance->stats, lo, hi);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -311,8 +318,6 @@ void SRC_AccumulateSample
SST_DoNewRegression(inst->stats); SST_DoNewRegression(inst->stats);
/* And redo clock selection */ /* And redo clock selection */
SRC_SelectSource(inst->ref_id); SRC_SelectSource(inst->ref_id);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -359,6 +364,10 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
inst->reachability |= !!reachable; inst->reachability |= !!reachable;
inst->reachability &= ~(-1 << REACH_BITS); inst->reachability &= ~(-1 << REACH_BITS);
/* The beginning is over when the first sample is at the end of the register */
if (inst->reachability & (1 << (REACH_BITS - 1)))
inst->beginning = 0;
if (!reachable && inst->index == selected_source_index) { if (!reachable && inst->index == selected_source_index) {
/* Try to select a better source */ /* Try to select a better source */
SRC_SelectSource(0); SRC_SelectSource(0);
@@ -415,6 +424,85 @@ source_to_string(SRC_Instance inst)
return NULL; return NULL;
} }
/* ================================================== */
static int
combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
double *offset_sd, double *frequency, double *skew)
{
struct timeval src_ref_time;
double src_offset, src_offset_sd, src_frequency, src_skew;
double src_root_delay, src_root_dispersion, elapsed;
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
double frequency_weight, sum_frequency_weight, sum_frequency, inv_sum2_skew;
int i, index, combined;
if (n_sel_sources == 1)
return 1;
sum_offset_weight = sum_offset = sum2_offset_sd = 0.0;
sum_frequency_weight = sum_frequency = inv_sum2_skew = 0.0;
for (i = combined = 0; i < n_sel_sources; i++) {
index = sel_sources[i];
SST_GetTrackingData(sources[index]->stats, &src_ref_time,
&src_offset, &src_offset_sd,
&src_frequency, &src_skew,
&src_root_delay, &src_root_dispersion);
/* Don't include this source if its distance is longer than the distance of
the selected source multiplied by the limit, their estimated frequencies
are not close, or it was recently marked as outlier */
if (index != selected_source_index &&
(sources[index]->sel_info.root_distance > combine_limit *
(reselect_distance + sources[selected_source_index]->sel_info.root_distance) ||
fabs(*frequency - src_frequency) >
combine_limit * (*skew + src_skew + LCL_GetMaxClockError()))) {
sources[index]->outlier = !sources[index]->beginning ? OUTLIER_PENALTY : 1;
} else if (sources[index]->outlier) {
sources[index]->outlier--;
}
if (sources[index]->outlier)
continue;
UTI_DiffTimevalsToDouble(&elapsed, ref_time, &src_ref_time);
src_offset += elapsed * src_frequency;
offset_weight = 1.0 / sources[index]->sel_info.root_distance;
frequency_weight = 1.0 / src_skew;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "combining index=%d oweight=%e offset=%e sd=%e fweight=%e freq=%e skew=%e",
index, offset_weight, src_offset, src_offset_sd, frequency_weight, src_frequency, src_skew);
#endif
sum_offset_weight += offset_weight;
sum_offset += offset_weight * src_offset;
sum2_offset_sd += offset_weight * (src_offset_sd * src_offset_sd +
(src_offset - *offset) * (src_offset - *offset));
sum_frequency_weight += frequency_weight;
sum_frequency += frequency_weight * src_frequency;
inv_sum2_skew += 1.0 / (src_skew * src_skew);
combined++;
}
assert(combined);
*offset = sum_offset / sum_offset_weight;
*offset_sd = sqrt(sum2_offset_sd / sum_offset_weight);
*frequency = sum_frequency / sum_frequency_weight;
*skew = 1.0 / sqrt(inv_sum2_skew);
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "combined result offset=%e sd=%e freq=%e skew=%e",
*offset, *offset_sd, *frequency, *skew);
#endif
return combined;
}
/* ================================================== */ /* ================================================== */
/* This function selects the current reference from amongst the pool /* This function selects the current reference from amongst the pool
of sources we are holding. of sources we are holding.
@@ -432,7 +520,7 @@ SRC_SelectSource(uint32_t match_refid)
int n_endpoints, j1, j2; int n_endpoints, j1, j2;
double best_lo, best_hi; double best_lo, best_hi;
int depth, best_depth; int depth, best_depth;
int n_sel_sources; int n_sel_sources, combined;
double distance, sel_src_distance; double distance, sel_src_distance;
int stratum, min_stratum; int stratum, min_stratum;
struct SelectInfo *si; struct SelectInfo *si;
@@ -454,7 +542,8 @@ SRC_SelectSource(uint32_t match_refid)
return; return;
} }
LCL_ReadCookedTime(&now, NULL); /* This is accurate enough and cheaper than calling LCL_ReadCookedTime */
SCH_GetLastEventTime(&now, NULL, NULL);
/* Step 1 - build intervals about each source */ /* Step 1 - build intervals about each source */
n_endpoints = 0; n_endpoints = 0;
@@ -469,20 +558,16 @@ SRC_SelectSource(uint32_t match_refid)
si = &(sources[i]->sel_info); si = &(sources[i]->sel_info);
SST_GetSelectionData(sources[i]->stats, &now, SST_GetSelectionData(sources[i]->stats, &now,
&(si->stratum), &(si->stratum),
&(si->best_offset), &(si->lo_limit),
&(si->root_delay), &(si->hi_limit),
&(si->root_dispersion), &(si->root_distance),
&(si->variance), &(si->variance),
&(si->select_ok)); &(si->select_ok));
si->root_distance = si->root_dispersion + 0.5 * fabs(si->root_delay);
si->lo_limit = si->best_offset - si->root_distance;
si->hi_limit = si->best_offset + si->root_distance;
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f", LOG(LOGS_INFO, LOGF_Sources, "%s dist=%f lo=%f hi=%f",
source_to_string(sources[i]), source_to_string(sources[i]),
si->best_offset, si->root_distance, si->root_distance,
si->lo_limit, si->hi_limit); si->lo_limit, si->hi_limit);
#endif #endif
@@ -771,6 +856,7 @@ SRC_SelectSource(uint32_t match_refid)
/* Reset score for non-selectable sources */ /* Reset score for non-selectable sources */
if (sources[i]->status != SRC_SELECTABLE) { if (sources[i]->status != SRC_SELECTABLE) {
sources[i]->sel_score = 1.0; sources[i]->sel_score = 1.0;
sources[i]->outlier = OUTLIER_PENALTY;
continue; continue;
} }
@@ -834,6 +920,7 @@ SRC_SelectSource(uint32_t match_refid)
/* New source has been selected, reset all scores */ /* New source has been selected, reset all scores */
for (i=0; i < n_sources; i++) { for (i=0; i < n_sources; i++) {
sources[i]->sel_score = 1.0; sources[i]->sel_score = 1.0;
sources[i]->outlier = 0;
} }
} }
@@ -844,15 +931,20 @@ SRC_SelectSource(uint32_t match_refid)
if (selected_source_index != old_selected_index || if (selected_source_index != old_selected_index ||
match_refid == sources[selected_source_index]->ref_id) { match_refid == sources[selected_source_index]->ref_id) {
/* Now just use the statistics of the selected source for /* Now just use the statistics of the selected source combined with
trimming the local clock */ the other selectable sources for trimming the local clock */
SST_GetTrackingData(sources[selected_source_index]->stats, &ref_time, SST_GetTrackingData(sources[selected_source_index]->stats, &ref_time,
&src_offset, &src_offset_sd, &src_offset, &src_offset_sd,
&src_frequency, &src_skew, &src_frequency, &src_skew,
&src_root_delay, &src_root_dispersion); &src_root_delay, &src_root_dispersion);
REF_SetReference(min_stratum, leap_status, combined = combine_sources(n_sel_sources, &ref_time, &src_offset,
&src_offset_sd, &src_frequency, &src_skew);
REF_SetReference(sources[selected_source_index]->sel_info.stratum,
leap_status,
combined,
sources[selected_source_index]->ref_id, sources[selected_source_index]->ref_id,
sources[selected_source_index]->ip_addr, sources[selected_source_index]->ip_addr,
&ref_time, &ref_time,
@@ -1104,7 +1196,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
report->state = RPT_FALSETICKER; report->state = RPT_FALSETICKER;
break; break;
case SRC_SELECTABLE: case SRC_SELECTABLE:
report->state = RPT_CANDIDATE; report->state = src->outlier ? RPT_OUTLIER : RPT_CANDIDATE;
break; break;
default: default:
assert(0); assert(0);

View File

@@ -43,10 +43,17 @@
to store per source */ to store per source */
#define MAX_SAMPLES 64 #define MAX_SAMPLES 64
/* User defined maximum and minimum number of samples */
int max_samples;
int min_samples;
/* This is the assumed worst case bound on an unknown frequency, /* This is the assumed worst case bound on an unknown frequency,
2000ppm, which would be pretty bad */ 2000ppm, which would be pretty bad */
#define WORST_CASE_FREQ_BOUND (2000.0/1.0e6) #define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
/* The minimum allowed skew */
#define MIN_SKEW 1.0e-12
/* ================================================== */ /* ================================================== */
static LOG_FileID logfileid; static LOG_FileID logfileid;
@@ -160,6 +167,8 @@ SST_Initialise(void)
logfileid = CNF_GetLogStatistics() ? LOG_FileOpen("statistics", logfileid = CNF_GetLogStatistics() ? LOG_FileOpen("statistics",
" Date (UTC) Time IP Address Std dev'n Est offset Offset sd Diff freq Est skew Stress Ns Bs Nr") " Date (UTC) Time IP Address Std dev'n Est offset Offset sd Diff freq Est skew Stress Ns Bs Nr")
: -1; : -1;
max_samples = CNF_GetMaxSamples();
min_samples = CNF_GetMinSamples();
} }
/* ================================================== */ /* ================================================== */
@@ -204,7 +213,6 @@ void
SST_DeleteInstance(SST_Stats inst) SST_DeleteInstance(SST_Stats inst)
{ {
Free(inst); Free(inst);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -240,7 +248,8 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
int n, m; int n, m;
/* Make room for the new sample */ /* Make room for the new sample */
if (inst->n_samples == MAX_SAMPLES) { if (inst->n_samples > 0 &&
(inst->n_samples == MAX_SAMPLES || inst->n_samples == max_samples)) {
prune_register(inst, 1); prune_register(inst, 1);
} }
@@ -259,7 +268,7 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
inst->sample_times[n] = *sample_time; inst->sample_times[n] = *sample_time;
inst->offsets[n] = offset; inst->offsets[n] = offset;
inst->orig_offsets[m] = offset; inst->orig_offsets[m] = offset;
inst->peer_delays[m] = fabs(peer_delay); inst->peer_delays[m] = peer_delay;
inst->peer_dispersions[m] = peer_dispersion; inst->peer_dispersions[m] = peer_dispersion;
inst->root_delays[m] = root_delay; inst->root_delays[m] = root_delay;
inst->root_dispersions[m] = root_dispersion; inst->root_dispersions[m] = root_dispersion;
@@ -335,7 +344,7 @@ find_best_sample_index(SST_Stats inst, double *times_back)
elapsed = -times_back[i]; elapsed = -times_back[i];
assert(elapsed >= 0.0); assert(elapsed >= 0.0);
root_distance = inst->root_dispersions[j] + elapsed * inst->skew + 0.5 * fabs(inst->root_delays[j]); root_distance = inst->root_dispersions[j] + elapsed * inst->skew + 0.5 * inst->root_delays[j];
if (root_distance < best_root_distance) { if (root_distance < best_root_distance) {
best_root_distance = root_distance; best_root_distance = root_distance;
best_index = i; best_index = i;
@@ -348,8 +357,6 @@ find_best_sample_index(SST_Stats inst, double *times_back)
#if 0 #if 0
LOG(LOGS_INFO, LOGF_SourceStats, "n=%d best_index=%d", n, best_index); LOG(LOGS_INFO, LOGF_SourceStats, "n=%d best_index=%d", n, best_index);
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -431,6 +438,7 @@ SST_DoNewRegression(SST_Stats inst)
inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples, inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
offsets + inst->runs_samples, weights, offsets + inst->runs_samples, weights,
inst->n_samples, inst->runs_samples, inst->n_samples, inst->runs_samples,
min_samples,
&est_intercept, &est_slope, &est_var, &est_intercept, &est_slope, &est_var,
&est_intercept_sd, &est_slope_sd, &est_intercept_sd, &est_slope_sd,
&best_start, &nruns, &degrees_of_freedom); &best_start, &nruns, &degrees_of_freedom);
@@ -448,6 +456,9 @@ SST_DoNewRegression(SST_Stats inst)
inst->variance = est_var; inst->variance = est_var;
inst->nruns = nruns; inst->nruns = nruns;
if (inst->skew < MIN_SKEW)
inst->skew = MIN_SKEW;
stress = fabs(old_freq - inst->estimated_frequency) / old_skew; stress = fabs(old_freq - inst->estimated_frequency) / old_skew;
if (best_start > 0) { if (best_start > 0) {
@@ -491,38 +502,6 @@ SST_DoNewRegression(SST_Stats inst)
} }
/* ================================================== */
void
SST_GetReferenceData(SST_Stats inst, struct timeval *now,
int *stratum, double *offset,
double *root_delay, double *root_dispersion,
double *frequency, double *skew)
{
double elapsed;
int i, j;
*frequency = inst->estimated_frequency;
*skew = inst->skew;
i = get_runsbuf_index(inst, inst->best_single_sample);
j = get_buf_index(inst, inst->best_single_sample);
UTI_DiffTimevalsToDouble(&elapsed, now, &inst->sample_times[i]);
*root_delay = inst->root_delays[j];
*root_dispersion = inst->root_dispersions[j] + elapsed * inst->skew;
*offset = inst->offsets[i] + elapsed * inst->estimated_frequency;
*stratum = inst->strata[j];
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_SourceStats, "n=%d freq=%f skew=%f del=%f disp=%f ofs=%f str=%d",
inst->n_samples, *frequency, *skew, *root_delay, *root_dispersion, *offset, *stratum);
#endif
return;
}
/* ================================================== */ /* ================================================== */
/* Return the assumed worst case range of values that this source's /* Return the assumed worst case range of values that this source's
frequency lies within. Frequency is defined as the amount of time frequency lies within. Frequency is defined as the amount of time
@@ -549,55 +528,51 @@ SST_GetFrequencyRange(SST_Stats inst,
/* ================================================== */ /* ================================================== */
/* ================================================== */
void void
SST_GetSelectionData(SST_Stats inst, struct timeval *now, SST_GetSelectionData(SST_Stats inst, struct timeval *now,
int *stratum, int *stratum,
double *best_offset, double *best_root_delay, double *offset_lo_limit,
double *best_root_dispersion, double *offset_hi_limit,
double *root_distance,
double *variance, int *select_ok) double *variance, int *select_ok)
{ {
double average_offset; double offset, sample_elapsed;
double sample_elapsed;
double elapsed;
int i, j; int i, j;
int average_ok;
double peer_distance;
i = get_runsbuf_index(inst, inst->best_single_sample); i = get_runsbuf_index(inst, inst->best_single_sample);
j = get_buf_index(inst, inst->best_single_sample); j = get_buf_index(inst, inst->best_single_sample);
*stratum = inst->strata[j]; *stratum = inst->strata[get_buf_index(inst, inst->n_samples - 1)];
*variance = inst->variance; *variance = inst->variance;
peer_distance = inst->peer_dispersions[j] + 0.5 * inst->peer_delays[j];
UTI_DiffTimevalsToDouble(&elapsed, now, &(inst->offset_time));
UTI_DiffTimevalsToDouble(&sample_elapsed, now, &inst->sample_times[i]); UTI_DiffTimevalsToDouble(&sample_elapsed, now, &inst->sample_times[i]);
*best_offset = inst->offsets[i] + sample_elapsed * inst->estimated_frequency; offset = inst->offsets[i] + sample_elapsed * inst->estimated_frequency;
*best_root_delay = inst->root_delays[j]; *root_distance = 0.5 * inst->root_delays[j] +
*best_root_dispersion = inst->root_dispersions[j] + sample_elapsed * inst->skew; inst->root_dispersions[j] + sample_elapsed * inst->skew;
*offset_lo_limit = offset - *root_distance;
*offset_hi_limit = offset + *root_distance;
#if 0
double average_offset, elapsed;
int average_ok;
/* average_ok ignored for now */ /* average_ok ignored for now */
UTI_DiffTimevalsToDouble(&elapsed, now, &(inst->offset_time));
average_offset = inst->estimated_offset + inst->estimated_frequency * elapsed; average_offset = inst->estimated_offset + inst->estimated_frequency * elapsed;
if (fabs(average_offset - *best_offset) <= peer_distance) { if (fabs(average_offset - offset) <=
inst->peer_dispersions[j] + 0.5 * inst->peer_delays[j]) {
average_ok = 1; average_ok = 1;
} else { } else {
average_ok = 0; average_ok = 0;
} }
#endif
*select_ok = inst->regression_ok; *select_ok = inst->regression_ok;
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_SourceStats, "n=%d off=%f del=%f dis=%f var=%f pdist=%f avoff=%f avok=%d selok=%d", LOG(LOGS_INFO, LOGF_SourceStats, "n=%d off=%f dist=%f var=%f selok=%d",
inst->n_samples, *best_offset, *best_root_delay, *best_root_dispersion, *variance, inst->n_samples, offset, *root_distance, *variance, *select_ok);
peer_distance, average_offset, average_ok, *select_ok);
#else
(void)average_ok;
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -677,8 +652,6 @@ SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffs
#else #else
(void)prev; (void)prev_freq; (void)prev; (void)prev_freq;
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -82,10 +82,10 @@ extern void SST_GetFrequencyRange(SST_Stats inst, double *lo, double *hi);
extern void extern void
SST_GetSelectionData(SST_Stats inst, struct timeval *now, SST_GetSelectionData(SST_Stats inst, struct timeval *now,
int *stratum, int *stratum,
double *best_offset, double *best_root_delay, double *offset_lo_limit,
double *best_root_dispersion, double *offset_hi_limit,
double *variance, double *root_distance,
int *select_ok); double *variance, int *select_ok);
/* Get data needed when setting up tracking on this source */ /* Get data needed when setting up tracking on this source */
extern void extern void
@@ -94,15 +94,6 @@ SST_GetTrackingData(SST_Stats inst, struct timeval *ref_time,
double *frequency, double *skew, double *frequency, double *skew,
double *root_delay, double *root_dispersion); double *root_delay, double *root_dispersion);
/* Get parameters for using this source as the reference */
extern void
SST_GetReferenceData(SST_Stats inst, struct timeval *now,
int *stratum, double *offset,
double *root_delay, double *root_dispersion,
double *frequency, double *skew);
/* This routine is called when the local machine clock parameters are /* This routine is called when the local machine clock parameters are
changed. It adjusts all existing samples that we are holding for changed. It adjusts all existing samples that we are holding for
each peer so that it looks like they were made under the new clock each peer so that it looks like they were made under the new clock

8
sys.c
View File

@@ -91,8 +91,6 @@ SYS_Finalise(void)
#if defined(__NetBSD__) #if defined(__NetBSD__)
SYS_NetBSD_Finalise(); SYS_NetBSD_Finalise();
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -104,8 +102,6 @@ void SYS_DropRoot(char *user)
#else #else
LOG_FATAL(LOGF_Sys, "dropping root privileges not supported"); LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -117,8 +113,6 @@ void SYS_SetScheduler(int SchedPriority)
#else #else
LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported"); LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported");
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -130,8 +124,6 @@ void SYS_LockMemory(void)
#else #else
LOG_FATAL(LOGF_Sys, "memory locking not supported"); LOG_FATAL(LOGF_Sys, "memory locking not supported");
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -29,14 +29,8 @@
#include "config.h" #include "config.h"
#ifdef LINUX #include "sysincl.h"
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include <assert.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#if defined(HAVE_SCHED_SETSCHEDULER) #if defined(HAVE_SCHED_SETSCHEDULER)
@@ -598,8 +592,6 @@ initiate_slew(void)
offset_register = 0.0; offset_register = 0.0;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -856,8 +848,6 @@ get_offset_correction(struct timeval *raw,
update_nano_slew_error(noffset, 0); update_nano_slew_error(noffset, 0);
*err = get_slow_slew_error(raw) + get_fast_slew_error(raw) + get_nano_slew_error();; *err = get_slow_slew_error(raw) + get_fast_slew_error(raw) + get_nano_slew_error();;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -871,8 +861,6 @@ set_leap(int leap)
LOG(LOGS_INFO, LOGF_SysLinux, "System clock status set to %s leap second", LOG(LOGS_INFO, LOGF_SysLinux, "System clock status set to %s leap second",
leap ? (leap > 0 ? "insert" : "delete") : "not insert/delete"); leap ? (leap > 0 ? "insert" : "delete") : "not insert/delete");
return;
} }
/* ================================================== */ /* ================================================== */
@@ -910,7 +898,6 @@ guess_hz_and_shift_hz(int tick, int *hz, int *shift_hz)
/* oh dear. doomed. */ /* oh dear. doomed. */
*hz = 0; *hz = 0;
*shift_hz = 0; *shift_hz = 0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -1257,9 +1244,3 @@ void SYS_Linux_MemLockAll(int LockAll)
} }
} }
#endif /* HAVE_MLOCKALL */ #endif /* HAVE_MLOCKALL */
#endif /* LINUX */
/* vim:ts=8
* */

View File

@@ -110,8 +110,6 @@ clock_initialise(void)
if (adjtime(&newadj, &oldadj) < 0) { if (adjtime(&newadj, &oldadj) < 0) {
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed"); LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -120,9 +118,6 @@ static void
clock_finalise(void) clock_finalise(void)
{ {
/* Nothing to do yet */ /* Nothing to do yet */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -217,7 +212,6 @@ accrue_offset(double offset, double corr_rate)
stop_adjust(); stop_adjust();
offset_register += offset; offset_register += offset;
start_adjust(); start_adjust();
return;
} }
/* ================================================== */ /* ================================================== */
@@ -296,7 +290,6 @@ get_offset_correction(struct timeval *raw,
start_adjust(); start_adjust();
if (err) if (err)
*err = 0.0; *err = 0.0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -304,7 +297,6 @@ get_offset_correction(struct timeval *raw,
static void static void
immediate_step(void) immediate_step(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -468,8 +460,6 @@ SYS_Solaris_Finalise(void)
if (need_dosynctodr) { if (need_dosynctodr) {
set_dosynctodr(1); set_dosynctodr(1);
} }
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -101,8 +101,6 @@ clock_initialise(void)
if (adjtime(&newadj, &oldadj) < 0) { if (adjtime(&newadj, &oldadj) < 0) {
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed"); LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -111,9 +109,6 @@ static void
clock_finalise(void) clock_finalise(void)
{ {
/* Nothing to do yet */ /* Nothing to do yet */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -221,7 +216,6 @@ accrue_offset(double offset, double corr_rate)
stop_adjust(); stop_adjust();
offset_register += offset; offset_register += offset;
start_adjust(); start_adjust();
return;
} }
/* ================================================== */ /* ================================================== */
@@ -283,7 +277,6 @@ get_offset_correction(struct timeval *raw,
start_adjust(); start_adjust();
if (err) if (err)
*err = 0.0; *err = 0.0;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -291,7 +284,6 @@ get_offset_correction(struct timeval *raw,
static void static void
immediate_step(void) immediate_step(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -420,8 +412,6 @@ SYS_SunOS_Finalise(void)
/* When exiting, we want to return the machine to its 'autonomous' /* When exiting, we want to return the machine to its 'autonomous'
tracking mode */ tracking mode */
setup_kernel(1); setup_kernel(1);
return;
} }
/* ================================================== */ /* ================================================== */

View File

@@ -45,6 +45,7 @@
#include <math.h> #include <math.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <resolv.h>
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
@@ -56,6 +57,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/un.h>
#include <sys/shm.h>
#include <syslog.h> #include <syslog.h>
#include <time.h> #include <time.h>
@@ -86,10 +89,6 @@
#include <nlist.h> #include <nlist.h>
#endif #endif
#if defined (HAS_NO_BZERO)
#define bzero(ptr,n) memset(ptr,0,n)
#endif /* HAS_NO_BZERO */
#if defined (WINNT) #if defined (WINNT)
/* Designed to work with the GCC from the GNAT-3.10 for Win32 /* Designed to work with the GCC from the GNAT-3.10 for Win32

80
util.c
View File

@@ -3,7 +3,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009, 2012 * Copyright (C) Miroslav Lichvar 2009, 2012-2013
* *
* 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
@@ -107,8 +107,6 @@ UTI_DiffTimevals(struct timeval *result,
(0,1000000) */ (0,1000000) */
UTI_NormaliseTimeval(result); /* JGH */ UTI_NormaliseTimeval(result); /* JGH */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -137,7 +135,8 @@ UTI_AddDoubleToTimeval(struct timeval *start,
is too marginal here. */ is too marginal here. */
int_part = (long) increment; int_part = (long) increment;
frac_part = (long) (0.5 + 1.0e6 * (increment - (double)int_part)); increment = (increment - int_part) * 1.0e6;
frac_part = (long) (increment > 0.0 ? increment + 0.5 : increment - 0.5);
end->tv_sec = int_part + start->tv_sec; end->tv_sec = int_part + start->tv_sec;
end->tv_usec = frac_part + start->tv_usec; end->tv_usec = frac_part + start->tv_usec;
@@ -189,6 +188,18 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
/* ================================================== */ /* ================================================== */
void
UTI_AddDiffToTimeval(struct timeval *a, struct timeval *b,
struct timeval *c, struct timeval *result)
{
double diff;
UTI_DiffTimevalsToDouble(&diff, a, b);
UTI_AddDoubleToTimeval(c, diff, result);
}
/* ================================================== */
#define POOL_ENTRIES 16 #define POOL_ENTRIES 16
#define BUFFER_LENGTH 64 #define BUFFER_LENGTH 64
static char buffer_pool[POOL_ENTRIES][BUFFER_LENGTH]; static char buffer_pool[POOL_ENTRIES][BUFFER_LENGTH];
@@ -212,19 +223,6 @@ UTI_TimevalToString(struct timeval *tv)
return result; return result;
} }
/* ================================================== */
#define JAN_1970 0x83aa7e80UL
inline static void
int64_to_timeval(NTP_int64 *src,
struct timeval *dest)
{
dest->tv_sec = ntohl(src->hi) - JAN_1970;
/* Until I invent a slick way to do this, just do it the obvious way */
dest->tv_usec = (int)(0.5 + (double)(ntohl(src->lo)) / 4294.967296);
}
/* ================================================== */ /* ================================================== */
/* Convert an NTP timestamp into a temporary string, largely /* Convert an NTP timestamp into a temporary string, largely
for diagnostic display */ for diagnostic display */
@@ -233,7 +231,7 @@ char *
UTI_TimestampToString(NTP_int64 *ts) UTI_TimestampToString(NTP_int64 *ts)
{ {
struct timeval tv; struct timeval tv;
int64_to_timeval(ts, &tv); UTI_Int64ToTimeval(ts, &tv);
return UTI_TimevalToString(&tv); return UTI_TimevalToString(&tv);
} }
@@ -459,16 +457,53 @@ UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *
/* ================================================== */ /* ================================================== */
uint32_t
UTI_GetNTPTsFuzz(int precision)
{
uint32_t fuzz;
int fuzz_bits;
fuzz_bits = 32 - 1 + precision;
fuzz = random() % (1 << fuzz_bits);
return fuzz;
}
/* ================================================== */
double
UTI_Int32ToDouble(NTP_int32 x)
{
return (double) ntohl(x) / 65536.0;
}
/* ================================================== */
#define MAX_NTP_INT32 (4294967295.0 / 65536.0)
NTP_int32
UTI_DoubleToInt32(double x)
{
if (x > MAX_NTP_INT32)
x = MAX_NTP_INT32;
else if (x < 0)
x = 0.0;
return htonl((NTP_int32)(0.5 + 65536.0 * x));
}
/* ================================================== */
/* Seconds part of RFC1305 timestamp correponding to the origin of the /* Seconds part of RFC1305 timestamp correponding to the origin of the
struct timeval format. */ struct timeval format. */
#define JAN_1970 0x83aa7e80UL #define JAN_1970 0x83aa7e80UL
void void
UTI_TimevalToInt64(struct timeval *src, UTI_TimevalToInt64(struct timeval *src,
NTP_int64 *dest) NTP_int64 *dest, uint32_t fuzz)
{ {
unsigned long usec = src->tv_usec; unsigned long usec = src->tv_usec;
unsigned long sec = src->tv_sec; unsigned long sec = src->tv_sec;
uint32_t lo;
/* Recognize zero as a special case - it always signifies /* Recognize zero as a special case - it always signifies
an 'unknown' value */ an 'unknown' value */
@@ -478,7 +513,12 @@ UTI_TimevalToInt64(struct timeval *src,
dest->hi = htonl(src->tv_sec + JAN_1970); dest->hi = htonl(src->tv_sec + JAN_1970);
/* This formula gives an error of about 0.1us worst case */ /* This formula gives an error of about 0.1us worst case */
dest->lo = htonl(4295 * usec - (usec>>5) - (usec>>9)); lo = 4295 * usec - (usec>>5) - (usec>>9);
/* Add the fuzz */
lo ^= fuzz;
dest->lo = htonl(lo);
} }
} }

10
util.h
View File

@@ -63,6 +63,9 @@ extern void UTI_AddDoubleToTimeval(struct timeval *start, double increment, stru
/* Calculate the average and difference (as a double) of two timevals */ /* Calculate the average and difference (as a double) of two timevals */
extern void UTI_AverageDiffTimevals(struct timeval *earlier, struct timeval *later, struct timeval *average, double *diff); extern void UTI_AverageDiffTimevals(struct timeval *earlier, struct timeval *later, struct timeval *average, double *diff);
/* Calculate result = a - b + c */
extern void UTI_AddDiffToTimeval(struct timeval *a, struct timeval *b, struct timeval *c, struct timeval *result);
/* Convert a timeval into a temporary string, largely for diagnostic /* Convert a timeval into a temporary string, largely for diagnostic
display */ display */
extern char *UTI_TimevalToString(struct timeval *tv); extern char *UTI_TimevalToString(struct timeval *tv);
@@ -88,8 +91,13 @@ extern char *UTI_TimeToLogForm(time_t t);
/* Adjust time following a frequency/offset change */ /* Adjust time following a frequency/offset change */
extern void UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta, double dfreq, double doffset); extern void UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta, double dfreq, double doffset);
/* Get a random value to fuzz an NTP timestamp in the given precision */
extern uint32_t UTI_GetNTPTsFuzz(int precision);
extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest); extern double UTI_Int32ToDouble(NTP_int32 x);
extern NTP_int32 UTI_DoubleToInt32(double x);
extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fuzz);
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest); extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);

View File

@@ -31,10 +31,6 @@
#include "config.h" #include "config.h"
#ifdef LINUX
#define _LOOSE_KERNEL_NAMES
#include "chrony_timex.h" #include "chrony_timex.h"
#include "wrap_adjtimex.h" #include "wrap_adjtimex.h"
@@ -276,6 +272,3 @@ TMX_ApplyStepOffset(double offset)
return adjtimex(&txc); return adjtimex(&txc);
} }
#endif