Compare commits

..

247 Commits
1.24 ... 1.27

Author SHA1 Message Date
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
Miroslav Lichvar
711cda6aed Update NEWS 2012-02-28 13:11:56 +01:00
Miroslav Lichvar
0c738d84af Update copyright years 2012-02-28 13:11:56 +01:00
Miroslav Lichvar
be1e1dc441 Fix password handling in chronyc 2012-02-28 13:11:56 +01:00
Miroslav Lichvar
2a305d8e16 Fix compiler warnings 2012-02-27 16:08:21 +01:00
Miroslav Lichvar
15b6ab77ea Update configure help text 2012-02-27 15:45:27 +01:00
Miroslav Lichvar
6199822783 Test leap second timezone on start 2012-02-27 13:28:14 +01:00
Miroslav Lichvar
0b72b2940a Update documentation 2012-02-27 13:28:14 +01:00
Miroslav Lichvar
d4ce3f19c3 Reschedule fast slew timeout on offset change 2012-02-24 16:26:53 +01:00
Miroslav Lichvar
824e86a82f Add leap status to tracking log and report 2012-02-24 11:06:20 +01:00
Miroslav Lichvar
2a5c045c3d Add support for reading leap second data from tz database
leapsectz directive is used to set the name of the timezone in the
system tz database which chronyd can use to find out when will the next
leap second occur.  It will periodically check if dates Jun 30 23:59:60
and Dec 31 23:59:60 are valid in that timezone. This is mainly useful
with reference clocks which don't provide the leap second information.
It is not necessary to restart chronyd if the tz database is updated
with a new leap second at least 12 hours before the event.
2012-02-24 11:06:20 +01:00
Miroslav Lichvar
f7c65a4b88 Add maxchange directive
This directive sets the maximum allowed offset corrected on a clock
update.  The check is performed only after the specified number of
updates to allow a large initial adjustment of the system clock.  When
an offset larger than the specified maximum occurs, it will be ignored
for the specified number of times and then chronyd will give up
and exit (a negative value can be used to never exit).  In both cases
a message is sent to syslog.
2012-02-21 14:34:09 +01:00
Miroslav Lichvar
a8956f2f56 Move refclock slew and dispersion handler init 2012-02-14 18:13:15 +01:00
Miroslav Lichvar
91c9f84a01 Step system time in RTC preinit only with offsets over 1 second 2012-02-14 17:49:55 +01:00
Miroslav Lichvar
2be89bc6f2 Fix last commit 2012-02-14 14:47:57 +01:00
Miroslav Lichvar
d6c447a445 Better estimate RTC offset right after trim 2012-02-13 16:54:18 +01:00
Miroslav Lichvar
a60586eaad Return success on empty command 2012-02-10 18:30:11 +01:00
Miroslav Lichvar
d77356837a Support passwords encoded in HEX 2012-02-09 16:56:17 +01:00
Miroslav Lichvar
d6842301dd Update reported RMS offset quickly on start 2012-02-08 14:30:35 +01:00
Miroslav Lichvar
19b3c5be26 Extend tracking, sources and activity reports 2012-02-03 17:22:53 +01:00
Miroslav Lichvar
5fb5a89f02 Use +/- when logging skew on start 2012-02-03 17:22:52 +01:00
Miroslav Lichvar
9367e7b9af Fix logged offset in manual reference 2012-02-03 15:23:25 +01:00
Miroslav Lichvar
6673cadfa2 Check if struct in6_pktinfo is usable 2012-01-05 15:11:54 +01:00
Miroslav Lichvar
b485051b65 Fix reported number of runs to correspond to reported number of samples 2011-11-28 11:19:48 +01:00
Miroslav Lichvar
9a01ccc07f Add corrtimeratio directive
The corrtimeratio directive controls the ratio between the
duration in which the clock is slewed for an average correction
according to the source history and the interval in which the
corrections are done (usually the NTP polling interval).  Corrections
larger than the average take less time and smaller corrections take
more time, the amount of the correction and the correction time are
inversely proportional.

Increasing corrtimeratio makes the overall frequency error of
the system clock smaller, but increases the overall time error as
the corrections will take longer.

By default, the ratio is 1, which means the duration of an average
correction will be close to the update interval.
2011-11-15 18:25:49 +01:00
Miroslav Lichvar
1b8deaf354 Control offset correction rate in Linux driver
The kernel currently doesn't support a linear adjustment with
programmable rate, extend the use of the kernel PLL with locked
frequency instead.

Set the PLL time constant according to the correction time corresponding
to the correction rate and corrected offset.

On kernels with nano PLL adjtime() is no longer used.
2011-11-15 12:30:59 +01:00
Miroslav Lichvar
c7d0232bb1 Introduce offset correction rate
We want to correct the offset quickly, but we also want to keep the
frequency error caused by the correction itself low.

Define correction rate as the area of the region bounded by the graph of
offset corrected in time. Set the rate so that the time needed to correct
an offset equal to the current sourcestats stddev will be equal to the
update interval (assuming linear adjustment). The offset and the
time needed to make the correction are inversely proportional.

This is only a suggestion and it's up to the system driver how the
adjustment will be executed.
2011-11-15 12:27:44 +01:00
Miroslav Lichvar
79e5f2be13 Include clock steps in calculated reference update interval 2011-11-14 15:55:19 +01:00
Miroslav Lichvar
9ab181eb9c Document extended keyfile format and authhash command 2011-11-02 13:53:00 +01:00
Miroslav Lichvar
3cc6021e03 Add support for libtomcrypt 2011-11-02 13:53:00 +01:00
Miroslav Lichvar
375389fa1e Add support for NSS library
This adds support for the NSSLOWHASH API provided by the freebl3
library.
2011-11-02 13:53:00 +01:00
Miroslav Lichvar
777303f130 Add support for different authentication hashes
Allow different hash functions to be used in the NTP and cmdmon
protocols. This breaks the cmdmon protocol compatibility. Extended key
file format is used to specify the hash functions for chronyd and new
authhash command is added to chronyc. MD5 is the default and the only
function included in the chrony source code, other functions will be
available from libraries.
2011-11-02 13:53:00 +01:00
Miroslav Lichvar
6015f99d98 Fix writing rtc data when called soon after trimrtc 2011-09-14 18:03:01 +02:00
Miroslav Lichvar
78fc17c661 Use ADJ_OFFSET_SS_READ mode only with kernels 2.6.28 and later 2011-09-13 16:39:08 +02:00
Miroslav Lichvar
d42addf746 Add macro for maximum fastslew timeout 2011-09-01 18:08:45 +02:00
Miroslav Lichvar
f570eb76b3 Check for timepps.h also in sys directory 2011-09-01 17:06:54 +02:00
Miroslav Lichvar
cc3f5962b8 Merge NCR_Process functions 2011-09-01 16:25:13 +02:00
Miroslav Lichvar
6ab3d1daa3 Add support for ADJ_SETOFFSET mode
This adjtimex mode allows precise stepping of the system clock.
2011-09-01 15:31:11 +02:00
Miroslav Lichvar
b088b70f82 Check sample ordering on accumulation
If the newly accumulated sample is not newer than than the last one,
discard the source history and start from scratch. This can happen after
loading an invalid dump or when the system clock was stepped.
2011-08-31 18:36:10 +02:00
Miroslav Lichvar
fbbb6bbc00 Update gpsd SOCK example in documentation 2011-08-26 18:34:00 +02:00
Miroslav Lichvar
5c36342958 Use initial delay also for burst samples 2011-08-26 18:34:00 +02:00
Miroslav Lichvar
f1a0cacc5a Make scheduling loop detector less sensitive
It could be triggered by delayed name resolving as it adds multiple new
timeouts which can be called in the same dispatching if the DNS responses
are slower than initial delay and sampling separation.

Compare number of dispatched events also with current number of
timeouts.
2011-08-26 18:34:00 +02:00
Miroslav Lichvar
1d2a0856b4 Wait in foreground process until daemon is fully initialized
Exit when all sockets are ready and initstepslew command and rtc step
are completed. Also, in case of a fatal error, print the error message
and exit with a non-zero status.
2011-08-26 18:31:26 +02:00
Miroslav Lichvar
7fb50d9a3e Always use delayed name resolving for server and peer directives
This significantly reduces initialization time.
2011-08-26 14:22:10 +02:00
Miroslav Lichvar
919b5b5a7d Change working directory to / 2011-08-25 18:49:34 +02:00
Miroslav Lichvar
1e35b26826 Read config after opening syslog 2011-08-25 14:46:16 +02:00
Miroslav Lichvar
27b0b5824a Disable maxdelayratio test by default
Change default maxdelayratio from 16384.0 to 0.0. A value larger
than 1.0 is required to enable the test.
2011-08-12 15:38:05 +02:00
Miroslav Lichvar
1d72d22bc5 Match skew in ntp_core to sourcestats skew 2011-08-12 15:38:05 +02:00
Miroslav Lichvar
e0c9ed44f9 Limit skew used in NTP test4
With iburst and very jittery sources the source skew can reach very high
values which makes the NTP test4 fail even with relatively small delays.
Limit the skew to 2000 ppm to avoid getting state where a source is unable
to accept more than first three iburst samples.
2011-08-12 15:37:58 +02:00
Miroslav Lichvar
411f4da340 Fix creating logdir 2011-08-11 14:15:15 +02:00
Miroslav Lichvar
4fac84098e Update NEWS 2011-07-13 14:55:28 +02:00
Miroslav Lichvar
21b2063a6f Retry on permanent DNS error by default 2011-07-13 14:49:22 +02:00
Miroslav Lichvar
917c191650 Update NEWS 2011-06-24 13:45:16 +02:00
Miroslav Lichvar
2bfce03d29 Add configure option for sendmail path 2011-06-24 13:27:30 +02:00
Miroslav Lichvar
1cb8167be0 Generate version and date in man pages 2011-06-24 12:30:48 +02:00
Miroslav Lichvar
40d33cc64d Convert make_release to shell script 2011-06-24 12:27:54 +02:00
Miroslav Lichvar
95433e9639 Remove chrony.lsm 2011-06-23 17:49:18 +02:00
Miroslav Lichvar
bbe1a09e7e Step also cooked select timestamp in scheduler slew handler 2011-06-23 15:23:16 +02:00
Miroslav Lichvar
dce2366b3a Detect infinite loop in scheduler
If more timeouts were handled than there were in the timer queue on
start, assume some code is scheduling timeouts with negative delays and
abort. Make the actual limit higher in case the machine is temporarily
overloaded and dispatching the handlers takes more time than was delay
of a scheduled timeout.
2011-06-23 15:14:08 +02:00
Miroslav Lichvar
bab7ba22cf Add asserts for timeout delays 2011-06-23 13:42:04 +02:00
Miroslav Lichvar
d6a91057ae Add waitsync command 2011-06-23 12:13:51 +02:00
Miroslav Lichvar
c6e9065498 Fix current_total_tick calculation 2011-06-15 15:35:15 +02:00
Miroslav Lichvar
22fda21eae Don't call driver read_freq in LCL_ReadAbsoluteFrequency 2011-06-15 15:35:14 +02:00
Miroslav Lichvar
103a520aa6 Create logdir before making first tracking write 2011-06-15 15:35:14 +02:00
Miroslav Lichvar
86531a51a7 Don't update drift file on first reference update 2011-06-15 15:35:14 +02:00
Miroslav Lichvar
2b7e4d645f Don't reset kernel frequency on start without drift file 2011-06-15 15:35:00 +02:00
Miroslav Lichvar
a5f63180fc Don't use uninitialized values 2011-06-13 18:17:33 +02:00
Miroslav Lichvar
934d4e04b5 Validate leap status in refclock samples 2011-06-13 17:03:30 +02:00
Miroslav Lichvar
1b8547059a Set leap status by enum 2011-06-13 17:02:42 +02:00
Miroslav Lichvar
91279a0f28 Store reference IDs in uint32_t 2011-06-13 15:34:16 +02:00
Miroslav Lichvar
31ba3144c8 Don't limit refclock driver name to 4 chars 2011-06-13 13:49:46 +02:00
Miroslav Lichvar
0bf34725e3 Don't try to recover from our own time steps 2011-06-10 18:57:04 +02:00
Miroslav Lichvar
91749ebb2b Try to handle unexpected backward time jumps 2011-06-10 18:29:41 +02:00
Miroslav Lichvar
4ba3dd66ad Set version string in config.h 2011-06-09 14:32:22 +02:00
Miroslav Lichvar
d40696f7f3 Add .deps to .gitignore 2011-06-09 14:31:04 +02:00
Miroslav Lichvar
4a401a9e83 Make .deps order-only prerequisite 2011-06-09 13:56:45 +02:00
Miroslav Lichvar
6a2a837ede Remove kernel version check from rtc code
It should work with all currently supported kernels (>= 2.2.0).
2011-06-06 21:33:59 +02:00
Miroslav Lichvar
eca08a281c Determine hz and shift from sysconf(_SC_CLK_TCK) when available 2011-06-06 17:41:14 +02:00
Miroslav Lichvar
9fd8f76fa0 Log final version specific details 2011-06-06 17:12:31 +02:00
Miroslav Lichvar
50de930730 Drop support for old readonly adjtime 2011-06-06 17:12:31 +02:00
Miroslav Lichvar
da1097095c Drop support for pre 2.2 Linux kernels 2011-06-06 17:12:31 +02:00
Miroslav Lichvar
ec7d302a6c Support Linux 3.0 and later 2011-06-06 13:56:27 +02:00
Miroslav Lichvar
8cc7ebffa9 Accept packets with compatible NTP versions
All incoming NTP packets are now required to have version 2, 3 or 4.
2011-05-25 16:59:40 +02:00
Miroslav Lichvar
de4d14843f Set source IPv6 address on NTP reply
This is needed on systems with multiple IPv6 addresses to reply with
the same source address as the destination address of the NTP request.
2011-05-24 18:07:06 +02:00
Miroslav Lichvar
18605795a7 Merge CCWARNFLAGS with CFLAGS 2011-05-24 18:07:06 +02:00
Miroslav Lichvar
da2c8d9076 Use config.h 2011-05-24 18:07:06 +02:00
Miroslav Lichvar
3120f8adb6 Use object dependencies in Makefile 2011-05-24 18:06:49 +02:00
Miroslav Lichvar
2dcc16169b Update NEWS 2011-05-04 12:29:40 +02:00
Miroslav Lichvar
a8efd8c398 Update versions in man pages 2011-05-02 13:21:50 +02:00
Miroslav Lichvar
bb40f4aff4 Modify weight calculation again
Dividing the weights by variance or unweighted variance seems to have a
significant negative impact on response with normally distributed
network delays.

Divide by the difference between the mean and minimum distance instead.
It should be stable as there is no loop and the response seems to be a
good compromise between the original minimum distance weighting which
works well with normally distributed delays and the variance weighting
which works well with exponentially distributed delays.
2011-04-29 13:29:56 +02:00
Miroslav Lichvar
66c7ac4d24 Revert using unweighted variance in weight calculation
This reverts commit 165e6805ab.
2011-04-29 13:29:24 +02:00
Miroslav Lichvar
7f12919fea Increase smoothing factor in refclock variance 2011-04-20 12:41:05 +02:00
Miroslav Lichvar
55e0c6a0a1 Update NEWS 2011-04-18 12:59:06 +02:00
Miroslav Lichvar
20f306602b Add another chrony.conf example 2011-04-18 12:57:01 +02:00
Miroslav Lichvar
70735d8d79 Ignore extra samples in reported nruns 2011-04-18 12:36:02 +02:00
Miroslav Lichvar
165e6805ab In weight calculation use unweighted variance from last regression
This fixes a positive feedback where weights could reach inf.
Also change the SD_TO_DIST_RATIO constant to get close to the original
response.
2011-04-13 18:43:25 +02:00
Miroslav Lichvar
2a0c35646c Allow changing tick up to max_tick_bias 2011-04-12 16:40:22 +02:00
Miroslav Lichvar
28710e0449 Change default maxclockerror to 1 ppm 2011-04-11 17:54:01 +02:00
Miroslav Lichvar
c5587b60b2 Set reference time to last sample instead of time on update
This is done mainly to fix reported root dispersion to include max clock
error after selecting another source without new sample.
2011-04-11 17:52:04 +02:00
Miroslav Lichvar
bb95c39356 Update refclock documentation 2011-04-08 16:53:11 +02:00
Miroslav Lichvar
20a43409c6 Add new commands to protocol comment in candm.h 2011-04-07 18:35:02 +02:00
Miroslav Lichvar
4699f7ca0b Update client copyright message 2011-04-07 18:35:02 +02:00
Miroslav Lichvar
bc7586b3f4 Assert there are no unhandled commands in cmdmon 2011-04-07 18:34:47 +02:00
Miroslav Lichvar
8d3d45ea1a Add reselectdist command 2011-04-07 18:16:39 +02:00
Miroslav Lichvar
21ba1d3761 Don't add \n to chronyc command line arguments
This fixes parsing of some commands.
2011-04-07 16:17:58 +02:00
Miroslav Lichvar
e79584bb9e Revert marking offline sources as unreachable 2011-04-07 14:44:56 +02:00
Miroslav Lichvar
bca7819247 Don't crash when sources report is requested soon after start 2011-04-06 16:59:40 +02:00
Miroslav Lichvar
0ecabae2c3 Add include directive 2011-04-06 16:58:12 +02:00
Miroslav Lichvar
598c04eea2 Add configure option to force retry on DNS failure
This is apparently needed on system which keep nameservers specified
in /etc/resolv.conf even when there is no network connection. Should be
used with care as invalid names will be retried forever.
2011-04-05 18:14:05 +02:00
Miroslav Lichvar
faec23f6bd Don't update empty sourcestats on clock update 2011-04-05 16:32:50 +02:00
Miroslav Lichvar
896dad9224 Fix warnings produced by latest gcc 2011-02-15 18:55:34 +01:00
Miroslav Lichvar
680612cf09 Reduce Linux driver verbosity 2011-02-15 17:22:40 +01:00
Miroslav Lichvar
3fbd4bb15f Don't log error on opening driftfile
Log frequency and skew values read from the driftfile instead.
2011-02-15 16:56:30 +01:00
Miroslav Lichvar
cb9055072d Make starting log even in debug mode 2011-02-14 18:21:38 +01:00
Miroslav Lichvar
0fc9b555f1 Don't log in signal handler 2011-02-14 18:19:58 +01:00
Miroslav Lichvar
6ed58628f5 Don't use uninitialized memory when setting RTC time 2011-02-11 17:56:05 +01:00
Miroslav Lichvar
efff149988 Use system headers for Linux RTC support 2011-02-11 17:56:05 +01:00
Miroslav Lichvar
b02d4092f1 Fix compiler warnings in PPS configure test 2011-02-11 17:31:38 +01:00
Miroslav Lichvar
9dc7ea7c62 Update NEWS 2011-01-28 13:21:56 +01:00
Miroslav Lichvar
546a3cdd50 Update credits 2011-01-28 12:57:03 +01:00
Miroslav Lichvar
e8c5d15690 Remove CVS headers 2011-01-28 12:56:09 +01:00
Miroslav Lichvar
e63cba05b2 Update copyright 2011-01-27 13:05:26 +01:00
Miroslav Lichvar
e8fe1dc415 Ignore reselectdist for refclocks 2011-01-25 17:51:19 +01:00
Miroslav Lichvar
9cf08fc780 Make importance of stratum in source selection configurable
Instead of always selecting the source with minimum stratum, add weighted
stratum to the distance when comparing selectable sources. The weight
can be configured with new stratumweight directive and can be set to
zero to ignore stratum completely, by default 1.0.
2011-01-25 17:40:46 +01:00
Miroslav Lichvar
b712b3a979 Disable variance source test for now
It seems it triggers even with one source alone if it's close and
accurate or polling interval is long enough. It would need to include
max_clock_error.
2011-01-25 17:40:46 +01:00
Miroslav Lichvar
a931b2eece Add outlyer source status to cmdmon protocol
This is not used yet.
2011-01-25 17:40:46 +01:00
Miroslav Lichvar
2e74beebbf Print sources with bad stats in client as unreachable 2011-01-25 17:40:46 +01:00
Miroslav Lichvar
db510a9558 Select source with minimum distance using a scoring system
Each source has a score against currently selected source which is
updated (multiplied by ratio of their distances) when one of the two
sources has a new sample. When the score reaches a limit, the source
will be selected. This should allow to slowly select the source with
minimum distance without frequent reselecting.

To avoid switching between sources with very variable distances (e.g. on
LAN or when upstream server uses a longer polling interval), sources
that are currently not selected are penalized by a fixed distance. This
can be configured with new reselectdist directive (100 microseconds by
default).
2011-01-25 17:40:37 +01:00
Miroslav Lichvar
222198acf3 Set status on doffset and dfreq commands 2011-01-19 15:29:49 +01:00
Miroslav Lichvar
bc4d5df94e Reply with status invalid instead of bad length on invalid command 2011-01-19 14:44:10 +01:00
Miroslav Lichvar
9d35b5deac Don't leak descriptors to sendmail 2011-01-18 18:07:46 +01:00
Miroslav Lichvar
59c68d240c Don't forget to shift last class dispatch timevals on step 2010-12-20 14:12:47 +01:00
Miroslav Lichvar
930a41b845 Don't send packet in last auto_offline transmit timeout 2010-12-17 18:09:10 +01:00
Miroslav Lichvar
323f0d187e Fix switching offline auto_offline source to online 2010-12-17 18:09:10 +01:00
Miroslav Lichvar
0078705bbe Enforce timeout class separation from last dispatched timeout 2010-12-17 16:09:12 +01:00
Miroslav Lichvar
3b3ca4afdc Use enum for scheduler timeout classes 2010-12-17 15:38:23 +01:00
Miroslav Lichvar
1d6b94b458 Fix crash when timeout is removed from its handler
Remove the timeout before dispatching the handler, and allow
calling SCH_RemoveTimeout() with nonexistent id.
2010-12-17 14:52:39 +01:00
Miroslav Lichvar
30c038c3c3 Make unsynchronised entry in tracking log on start 2010-12-17 13:22:57 +01:00
Miroslav Lichvar
05e002cd42 Delay selecting source on start
On start, when servers are reachable and use the same polling interval,
wait for them to have the same reachability register (which corresponds
to the number of samples in sourcestats) before selecting one.
2010-12-17 13:22:57 +01:00
Miroslav Lichvar
7f6ed73145 Don't update local reference unnecessarily
Local reference is now updated only when a new source is selected or
match_addr is equal to the selected source, match_addr 0 is no longer
treated specially.
2010-12-17 13:22:57 +01:00
Miroslav Lichvar
0c4968ec51 Track reachability in sources module
Add new flag to source struct to indicate when source is selectable
(packets with good headers are received) and use a reachability
register for last 8 samples instead of the reachable flag. Source
drivers now provide only reachability updates.
2010-12-17 13:22:29 +01:00
Miroslav Lichvar
ff69e86559 Apply jitter test only on NTP sources for now
With refclocks it seems to fail easily, users would have to set the delay
option appropriately.
2010-12-16 18:35:39 +01:00
Miroslav Lichvar
98f79404d6 Allow selecting source only when last regression was successful 2010-12-15 17:48:30 +01:00
Miroslav Lichvar
eec438a614 Fix jitter test in source selection
Distance should be compared to square root of variance.
2010-12-15 14:25:40 +01:00
Miroslav Lichvar
c88801065f Divide regression weights by stddev instead of minimum distance
This improves accuracy with large but stable network delays.
2010-12-14 17:00:53 +01:00
Miroslav Lichvar
833022b745 Add small randomness to spacing between samples for one server 2010-12-09 16:06:42 +01:00
Miroslav Lichvar
d1b820e7e3 Shorten initial delay and sampling separation to 0.2 seconds 2010-12-09 15:14:05 +01:00
Miroslav Lichvar
4373918a2f Fix separation of timeouts scheduled for exactly the same time 2010-12-09 14:34:29 +01:00
Miroslav Lichvar
6e96b4ba33 Add reselect command 2010-12-07 16:47:58 +01:00
Miroslav Lichvar
2d326bfc48 Require password for clients command 2010-12-07 16:47:58 +01:00
Miroslav Lichvar
a6988b2a79 Update chronyc help text 2010-12-07 16:47:57 +01:00
Miroslav Lichvar
8b93e1a780 Slowly back off sampling rate when selected source loses connectivity 2010-12-07 16:47:57 +01:00
Miroslav Lichvar
4e318c1abc Require valid_header before accumulating sample
Split test7 into two and to accumulate the sample require that all tests
pass, except the one which checks packet stratum is not higher than ours.

Also, don't mark the source as unreachable when only test4c fails.
2010-12-07 16:47:57 +01:00
Miroslav Lichvar
3cb6840d2d Fix log file names in documentation 2010-12-07 16:47:57 +01:00
Miroslav Lichvar
6ed5a65064 Add maxdelaydevratio command 2010-12-07 16:47:57 +01:00
Miroslav Lichvar
b977c95be4 Add test for ratio of increase in delay to stddev
Require that the ratio of the increase in delay from the minimum one in
the stats data register to the standard deviation of the offsets in the
register is less than maxdelaydevratio or the difference between
measured offset and predicted offset is larger than the increase in
delay. In the allowed delay increase is included also skew and maximum
clock frequency error.

maxdelaydevratio is 10.0 by default.
2010-12-07 16:47:57 +01:00
Miroslav Lichvar
feb8811f37 Cache minimum peer delay in sourcestats 2010-12-03 17:25:50 +01:00
Miroslav Lichvar
0de82a70a6 Keep only absolute values of peer delays in sourcestats
This saves some fabs() calls.
2010-12-03 13:17:09 +01:00
Miroslav Lichvar
cc3a8918f0 Include maximum clock frequency error in our dispersion
Add maxclockerror directive to set the stability of the clock (10 ppm by
default) and include it in our dispersion.
2010-12-03 13:15:14 +01:00
Miroslav Lichvar
63ef2badd6 Fix printing of NP and NR over 99 in sourcestats 2010-12-01 14:32:26 +01:00
Miroslav Lichvar
e98080b8bb Use only 3 chars from refclock driver name in default refid 2010-11-30 18:18:28 +01:00
Miroslav Lichvar
bed5b72cbe Add polltarget command 2010-10-14 15:08:35 +02:00
Miroslav Lichvar
7ab2c0e4a5 Add logbanner directive 2010-10-13 17:50:22 +02:00
Miroslav Lichvar
7a6ee1d729 Base poll adjustment on number of sourcestats samples
Instead of following skew changes, adjust polling interval so that the
number of measurements used in the regression algorithm remains close to
a target value. It can be configured with a new polltarget option
(6 by default).
2010-10-13 16:49:28 +02:00
Miroslav Lichvar
d9596334c3 Move default source parameters to macros 2010-10-13 12:58:26 +02:00
Miroslav Lichvar
16676ae726 Add -m option to allow multiple commands on command line 2010-10-04 15:53:35 +02:00
Miroslav Lichvar
fd3702f973 Add retries and timeout commands 2010-10-04 15:00:07 +02:00
Miroslav Lichvar
d674d23b45 Adjust chronyc timeout
Start at 1 second and increase it exponentially with maximum number of
attempts 3.
2010-10-04 13:16:52 +02:00
Miroslav Lichvar
5b8835f46b Support prefer and noselect options in chronyc 2010-08-26 10:29:58 +02:00
Miroslav Lichvar
ddb2cf3b8b Merge code for adding NTP server and peer in cmdmon 2010-08-26 09:35:57 +02:00
Miroslav Lichvar
f924862e89 Add prefer and noselect options 2010-08-25 18:32:40 +02:00
Miroslav Lichvar
061d497df0 Fix crash when reloading history with zero samples 2010-08-25 18:32:40 +02:00
Miroslav Lichvar
3a222336d7 Fix reloading sample histories with refclocks 2010-08-25 18:10:35 +02:00
Miroslav Lichvar
78300d018a Add minstratum command 2010-08-25 17:43:17 +02:00
Miroslav Lichvar
e95676f65f Document minstratum option 2010-08-25 17:43:15 +02:00
Benny Lyne Amorsen
c8fe69c956 Add minstratum option
Stratum in received packets is raised to the configured minimum.
2010-08-25 12:46:14 +02:00
Miroslav Lichvar
fe4b661fe7 Add -n option to allow using syslog without forking 2010-08-19 17:21:11 +02:00
Miroslav Lichvar
5344028c40 Use 5% critical region for number of runs
This results in more samples used in regression and slightly improved
response with high jitters.
2010-08-17 17:52:19 +02:00
Miroslav Lichvar
e591e3622b Extend runs test
Double the number of samples that are used in the runs test. E.g. with 64
samples in regression the runs test will be tried over the 64 samples and
up to 64 previous samples. The minimum number of samples in now 4.

This improves the response with low-mid jitters by about 50%.
2010-08-17 16:40:25 +02:00
Miroslav Lichvar
d8fc5fee0a Run configure tests with LDFLAGS 2010-08-17 12:31:03 +02:00
Miroslav Lichvar
eeb73b3670 Fix updating of best_single_sample 2010-08-16 16:44:49 +02:00
Miroslav Lichvar
2f2e524bc6 Don't use timezone parameter in gettimeofday and settimeofday calls 2010-08-12 14:43:26 +02:00
Miroslav Lichvar
6b0198c2d7 Replace all CROAK calls with assert or LOG_FATAL
Remove croak() and use assert() or LOG_FATAL() everywhere. Hopefully
the problems with debugging mentioned in the croak() comment are long gone.
2010-08-12 14:30:05 +02:00
Miroslav Lichvar
2a64b75893 Regenerate critical values for number of runs
Generate more values to allow regression with 128 samples. Possibly a
different approach was used to generate the values, or the previous table
was actually using 11% critical region and had an extra value in the
12th place.
2010-08-11 18:50:23 +02:00
Miroslav Lichvar
034e172033 Assert number of points in regress functions 2010-08-11 18:25:32 +02:00
Miroslav Lichvar
1faeb45063 Update offset correction errors only when needed 2010-08-11 17:16:16 +02:00
Miroslav Lichvar
fa84496423 Fix updating of nano slew offset correction error 2010-08-11 16:57:19 +02:00
Miroslav Lichvar
a3d47ffc81 Store sourcestats samples in circular buffer
The samples now don't have to be moved when pruning the register.
2010-08-10 16:39:52 +02:00
Miroslav Lichvar
d841c86a6e Cleanup sourcestats code a bit 2010-08-10 15:35:17 +02:00
Miroslav Lichvar
3b4e4b785d Change length of resid buffer to MAX_POINTS 2010-08-06 14:51:37 +02:00
Miroslav Lichvar
7ba6b617a1 Remove weights from sourcestats record
Weights are calculated before each regression call, no need to store them.
2010-08-06 14:39:09 +02:00
Miroslav Lichvar
100f732e20 Remove SST_DoUpdateRegression
The function is not used anywhere and it requires weights to be stored
sourcestats.
2010-08-06 14:36:56 +02:00
Miroslav Lichvar
cb28aeeacc Add nanosecond slewing to Linux driver
For offset adjustments below 10 microseconds use kernel PLL with
locked frequency and 1s time constant.
2010-08-06 11:50:35 +02:00
Miroslav Lichvar
7994b31de4 Reset adjtime offset on start 2010-08-05 13:27:52 +02:00
Miroslav Lichvar
6dcf3238f6 Clarify some cmdmon warning messages 2010-06-14 09:47:07 +02:00
Miroslav Lichvar
f6320e7050 Don't hang in our_round
The routine could loop infinitely when rounding a large value, replace
it with our_lround.
2010-06-07 14:19:58 +02:00
Miroslav Lichvar
597bb80d18 Set minimum allowed skew to 1e-12 2010-05-26 16:55:49 +02:00
Miroslav Lichvar
9775f3a030 Read chrony.conf before checking/writing pid file
This fixes the pidfile directive.
2010-05-20 16:10:51 +02:00
Miroslav Lichvar
a080d00352 Add rtcsync directive
The directive enables the 11 minute kernel mode. It cannot be used
when the normal RTC tracking is enabled.
2010-05-14 14:41:11 +02:00
Miroslav Lichvar
5fb0a9d53b Rehash NTP source table after removing source
This is needed to avoid breaking a probe sequence and losing another
source. It is costly, but it's not expected to happen frequently.
2010-05-13 18:29:00 +02:00
Miroslav Lichvar
40d82675bd Make use of UTI_AdjustTimeval in slew handlers 2010-05-07 18:52:05 +02:00
Miroslav Lichvar
f851e1f90e Fix RTC slew handler
The frequency adjustment needs to be done in the opposite direction.
2010-05-07 18:51:35 +02:00
Miroslav Lichvar
73d775c8b4 Don't use AI_ADDRCONFIG hint
We want to get IPv4/6 addresses even if the local system currently has
no IPv4/6 address configured.
2010-04-28 19:15:35 +02:00
Miroslav Lichvar
97f3e9404a Change online status also for unresolved sources 2010-04-28 17:18:03 +02:00
Miroslav Lichvar
83da131e99 Retry name resolving before marking sources online 2010-04-28 15:45:05 +02:00
Miroslav Lichvar
7973aef7b7 Don't log network is unreachable errors 2010-04-27 15:56:48 +02:00
Miroslav Lichvar
9a3bdcc20b Fix name resolving when IPv6 support is disabled 2010-04-27 14:35:28 +02:00
Miroslav Lichvar
aa91c608f4 Add delayed name resolving for servers and peers
Resolving is retried in increasing intervals (maximum is one hour)
until it succeeds or fails with a non-temporary error.

Unresolved sources are included in the activity report as offline
sources and the online command can be used to retry it immediately.

This could be improved by resolving in a separate thread/process
to avoid blocking.
2010-04-27 14:35:28 +02:00
Miroslav Lichvar
3d260d41b3 Don't retry resolving in DNS_Name2IPAddress
Instead of retrying to resolve it in the function and blocking for a
long time, return a TryAgain status and let the caller retry it later if
necessary.
2010-04-27 14:35:28 +02:00
Miroslav Lichvar
2458325c09 Merge NSR/NCR server and peer functions 2010-04-27 14:35:27 +02:00
Miroslav Lichvar
ab68a9d1d3 Set maxupdateskew to 1000 ppm by default
This will prevent from using unreliable frequency estimate on iburst
when starting without drift file.
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
93b5b08bed Add iburst server option 2010-04-27 14:35:27 +02:00
Miroslav Lichvar
be4369936b Clamp tick value before calling adjtimex
If tick is outside allowed adjtimex range, clamp it and log a warning
instead of aborting.
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
1a7415a6ab Return actual frequency in drv_set_freq functions
This is needed to keep sourcestats accurate when the actual frequency is
different from the requested frequency due to clamping (or possibly
rounding in future system drivers).
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
c15db71f9e Add dispersion after Linux makestep 2010-04-27 14:35:27 +02:00
Miroslav Lichvar
74cb1c877c Mark source unreachable after offline burst 2010-04-27 14:35:27 +02:00
Miroslav Lichvar
a949ab6935 Increase burst polling interval
To avoid getting KoD RATE from NTP server (triggering discard minimum 1)
when burst sampling, increase polling interval to 2 seconds.
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
f0fd7099c0 Stop burst sampling when received KoD RATE 2010-04-27 14:35:27 +02:00
Miroslav Lichvar
e0009f9f40 Update drift file at most once per hour
Instead of writing to the file on every reference update, update it
on first update, on exit and otherwise only once per hour.
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
14d2576924 Remove absolute frequency from handler parameters
None of the current handlers really need it and with temperature
compensation enabled it would be necessary to undo the compensation
before passing it to the handlers.
2010-04-27 14:35:27 +02:00
Miroslav Lichvar
c386d11765 Add temperature compensation
A new tempcomp directive can be used to specify a file for reading
current temperature, update interval and compensation coefficients. The
clock frequency corrections are applied in local module and are invisible
in upper layers. The measurements and corrections can be logged to
tempcomp.log file.
2010-04-27 14:35:11 +02:00
Miroslav Lichvar
f12bc10917 Add fallback drifts
Fallback drifts are long-term averages of the system clock drift
calculated over exponentially increasing intervals. They are used when
the clock is unsynchronised to avoid quickly drifting away from true
time if there was a short-term deviation in drift before the
synchronisation was lost.
2010-04-27 14:27:05 +02:00
Miroslav Lichvar
99d18abf59 Fix frequency accumulation 2010-04-21 13:59:37 +02:00
Miroslav Lichvar
bc29c84610 Fix possible memory leak in mkdir_and_parents() 2010-04-13 15:16:49 +02:00
Miroslav Lichvar
e78e65ef22 Refactor file logging 2010-04-13 15:16:41 +02:00
Håkan Johansson
f9103531c4 Avoid large times in chronyc sources / sourcestats overflowing lines
Main trouble was double values too large to be represented as ints being
converted to -INT_MAX and then passing the < 9999 cut.
2010-04-07 14:26:41 +02:00
Miroslav Lichvar
2ea87490f4 Mark offline sources unreachable 2010-04-02 15:55:58 +02:00
Miroslav Lichvar
5fb5551c36 Add refclock precision 2010-03-02 14:23:54 +01:00
Miroslav Lichvar
b9b0326d15 Reduce noise in refclock sample dispersions
Use the estimated dispersion only if it's higher than long-term average.
This should improve performance with short polling intervals.
2010-03-02 14:23:50 +01:00
Miroslav Lichvar
97f2f16fd6 Log also filtered samples 2010-03-02 13:19:33 +01:00
Miroslav Lichvar
fc1514db04 Adjust refclock filter parameters
Drop only about 40 percent of samples, change default length to 64,
require at least 4 samples between polls (or full filter for lengths
below 4).
2010-03-02 13:19:33 +01:00
Miroslav Lichvar
7fb0598b50 Make linear fit in refclock dispersion calculation
This should improve reaction to sudden temperature changes with
very precise refclocks and/or long polling intervals.
2010-03-02 13:19:02 +01:00
Miroslav Lichvar
fd375ca55b Estimate offset correction error in Linux driver 2010-02-18 14:17:16 +01:00
Miroslav Lichvar
0f70959d8e Add dispersion notification handlers 2010-02-16 18:51:37 +01:00
Miroslav Lichvar
8cb6fcad7e Include offset correction error in dispersion 2010-02-16 18:38:46 +01:00
Miroslav Lichvar
20d898d182 Prepare for handling offset correction error 2010-02-16 17:46:42 +01:00
Miroslav Lichvar
10c9a7d4b7 Don't set system precision to log2 based value 2010-02-16 17:46:42 +01:00
Miroslav Lichvar
441e42c276 Fix stratum with locked PPS refclock and local stratum 2010-02-16 17:46:42 +01:00
103 changed files with 6695 additions and 3308 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.deps
*.swp
*.o
Makefile

View File

@@ -1,9 +1,5 @@
##################################################
#
# $Header: /cvs/src/chrony/Makefile.in,v 1.48 2003/09/19 22:48:26 richard Exp $
#
# =======================================================================
#
# chronyd/chronyc - Programs for keeping computer clocks accurate.
#
# Copyright (C) Richard P. Curnow 1997-2003
@@ -33,30 +29,28 @@ INFODIR=@INFODIR@
DOCDIR=@DOCDIR@
CC = @CC@
CCWARNFLAGS = @CCWARNFLAGS@
OPTFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@ @SYSDEFS@ @EXTRA_DEFS@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
DESTDIR=
HASH_OBJ = @HASH_OBJ@
OBJS = util.o sched.o regress.o local.o \
sys.o main.o ntp_io.o ntp_core.o ntp_sources.o \
sources.o sourcestats.o reference.o \
logging.o conf.o cmdmon.o md5.o keys.o \
logging.o conf.o cmdmon.o keys.o \
nameserv.o acquire.o manual.o addrfilt.o \
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
broadcast.o refclock.o refclock_shm.o refclock_sock.o \
refclock_pps.o
refclock_pps.o tempcomp.o $(HASH_OBJ)
EXTRA_OBJS=@EXTRA_OBJECTS@
CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \
pktlength.o util.o
CLI_OBJS = client.o nameserv.o getdate.o cmdparse.o \
pktlength.o util.o $(HASH_OBJ)
SRCS = $(patsubst %.o,%.c,$(OBJS))
EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS))
CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS))
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
@@ -64,36 +58,29 @@ LIBS = @LIBS@
EXTRA_LIBS=@EXTRA_LIBS@
EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@
CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
# Until we have a main procedure we can link, just build object files
# to test compilation
all : chronyd chronyc
chronyd : $(OBJS) $(EXTRA_OBJS)
$(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS)
$(CC) $(CFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) @HASH_LINK@ $(LIBS) $(EXTRA_LIBS)
chronyc : $(CLI_OBJS)
$(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
conf.o : conf.c
$(CC) $(CFLAGS) $(CPPFLAGS) -DDEFAULT_CONF_DIR=\"$(SYSCONFDIR)\" -c $<
$(CC) $(CFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) @READLINE_LINK@ @HASH_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
client.o : client.c
$(CC) $(CFLAGS) $(CPPFLAGS) @READLINE_COMPILE@ -c $<
.depend :
gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend
$(HASH_OBJ) : $(patsubst %.o,%.c,$(HASH_OBJ))
$(CC) $(CFLAGS) $(CPPFLAGS) @HASH_COMPILE@ -c $<
distclean :
-rm -f *.o *.s chronyc chronyd core options.h Makefile *~
distclean : clean
-rm -f Makefile
clean :
-rm -f *.o *.s chronyc chronyd core *~
version.h : version.txt
./mkversion
-rm -rf .deps
getdate.c : ;
getdate :
@@ -137,8 +124,6 @@ install: chronyd chronyc
%.s : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -S $<
main.o logging.o client.o : version.h
# makeinfo v4 required to generate plain text and html
MAKEINFO:=makeinfo
@@ -167,3 +152,10 @@ chrony.info : chrony.texi
faq.php : faq.txt faqgen.pl
perl faqgen.pl < faq.txt > faq.php
.deps:
@mkdir .deps
.deps/%.d: %.c | .deps
@$(CC) -MM $(CPPFLAGS) -MT '$(<:%.c=%.o) $@' $< -o $@
-include $(ALL_OBJS:%.o=.deps/%.d)

65
NEWS
View File

@@ -1,3 +1,68 @@
New in version 1.27
===================
* Support for stronger keys via NSS or libtomcrypt library
* Support reading leap second data from tz database
* Support for precise clock stepping on Linux
* Support for nanoseconds in SHM refclock
* Make offset corrections smoother on Linux
* Make transmit timestamps random below clock precision
* Add corrtimeratio and maxchange directives
* Extend tracking, sources and activity reports
* Wait in foreground process until daemon is fully initialized
* Fix crash with slow name resolving
* Fix iburst with jittery sources
* 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
* Changed chronyc protocol, incompatible with older versions
New in version 1.26
===================
* Add compatibility with Linux 3.0 and later
* Use proper source address in NTP replies on multihomed IPv6 hosts
* Accept NTP packets with versions 4, 3 and 2
* Cope with unexpected backward time jumps
* Don't reset kernel frequency on start without drift file
* Retry on permanent DNS error by default
* Add waitsync command
New in version 1.25
===================
* Improve accuracy with NTP sources
* Improve accuracy with reference clocks
* Improve polling interval adjustment
* Improve stability with temporary asymmetric delays
* Improve source selection
* Improve initial synchronisation
* Add delayed server name resolving
* Add temperature compensation
* Add nanosecond slewing to Linux driver
* Add fallback drifts
* Add iburst, minstratum, maxdelaydevratio, polltarget,
prefer, noselect options
* Add rtcsync directive to enable Linux 11-minute mode
* Add reselectdist, stratumweight, logbanner, maxclockerror,
include directives
* Add -n option to not detach daemon from terminal
* Fix pidfile directive
* Fix name resolving with disabled IPv6 support
* Fix reloading sample histories with reference clocks
* Fix crash with auto_offline option
* Fix online command on auto_offline sources
* Fix file descriptor leaks
* Increase burst polling interval and stop on KoD RATE
* Set maxupdateskew to 1000 ppm by default
* Require password for clients command
* Update drift file at most once per hour
* Use system headers for Linux RTC support
* Reduce default chronyc timeout and make it configurable
* Avoid large values in chronyc sources and sourcestats output
* Add reselect command to force reselecting best source
* Add -m option to allow multiple commands on command line
New in version 1.24
===================

13
README
View File

@@ -144,6 +144,9 @@ Acknowledgements
The following people have provided patches and other major contributions
to the program :
Benny Lyne Amorsen <benny@amorsen.dk>
Patch to add minstratum option
Andrew Bishop <amb@gedanken.demon.co.uk>
Fixes for bugs in logging when in daemon mode
Fixes for compiler warnings
@@ -198,6 +201,9 @@ Liam Hatton <me@liamhatton.com>
Jachym Holecek <jakym@volny.cz>
Patch to make Linux real time clock work with devfs
Håkan Johansson <f96hajo@chalmers.se>
Patch to avoid large values in sources and sourcestats output
Jim Knoble <jmknoble@pobox.com>
Fixes for compiler warnings
@@ -209,7 +215,12 @@ Miroslav Lichvar <mlichvar@redhat.com>
IPv6 support
Linux capabilities support
Leap second support
Various bug fixes and improvements
Improved source selection
Improved sample history trimming
Improved polling interval adjustment
Improved stability with temporary asymmetric delays
Temperature compensation
Many other bug fixes and improvements
Victor Moroz <vim@prv.adlum.ru>
Patch to support Linux with HZ!=100

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/acquire.c,v 1.24 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -41,6 +37,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "acquire.h"
@@ -65,6 +63,10 @@
#define RETRANSMISSION_TIMEOUT (1.0)
#define NTP_VERSION 3
#define NTP_MAX_COMPAT_VERSION 4
#define NTP_MIN_COMPAT_VERSION 2
typedef struct {
IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source
@@ -168,6 +170,9 @@ prepare_socket(int family)
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
}
/* Close on exec */
UTI_FdSetCloexec(sock_fd);
if (port_number == 0) {
/* Don't bother binding this socket - we're not fussed what port
number it gets */
@@ -245,13 +250,13 @@ static void
probe_source(SourceRecord *src)
{
NTP_Packet pkt;
int version = 3;
int version = NTP_VERSION;
NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked;
double local_time_err;
union sockaddr_in46 his_addr;
int sock_fd;
socklen_t addrlen;
uint32_t ts_fuzz;
#if 0
printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
@@ -266,7 +271,7 @@ probe_source(SourceRecord *src)
pkt.precision = -6; /* as ntpdate */
pkt.root_delay = double_to_int32(1.0); /* 1 second */
pkt.root_dispersion = double_to_int32(1.0); /* likewise */
pkt.reference_id = 0UL;
pkt.reference_id = 0;
pkt.reference_ts.hi = 0; /* Set to 0 */
pkt.reference_ts.lo = 0; /* Set to 0 */
pkt.originate_ts.hi = 0; /* Set to 0 */
@@ -300,8 +305,9 @@ probe_source(SourceRecord *src)
}
LCL_ReadCookedTime(&cooked, &local_time_err);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
ts_fuzz = UTI_GetNTPTsFuzz(LCL_GetSysPrecisionAsLog());
LCL_ReadCookedTime(&cooked, NULL);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts, ts_fuzz);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
0,
@@ -372,7 +378,7 @@ process_receive(NTP_Packet *msg, SourceRecord *src, struct timeval *now)
mode = lvm & 0x7;
if ((leap == LEAP_Unsynchronised) ||
(version != 3) ||
(version < NTP_MIN_COMPAT_VERSION || version > NTP_MAX_COMPAT_VERSION) ||
(mode != MODE_SERVER && mode != MODE_PASSIVE)) {
return;
}
@@ -449,7 +455,7 @@ read_from_socket(void *anything)
his_addr_len = sizeof(his_addr);
/* Get timestamp */
SCH_GetFileReadyTime(&now);
SCH_GetFileReadyTime(&now, NULL);
sock_fd = (long)anything;
status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
@@ -704,7 +710,7 @@ process_measurements(void)
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
fabs(estimated_offset),
(estimated_offset >= 0) ? "fast" : "slow");
LCL_AccumulateOffset(estimated_offset);
LCL_AccumulateOffset(estimated_offset, 0.0);
}
} else {

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/acquire.h,v 1.9 2002/02/28 23:27:07 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/addressing.h,v 1.7 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/addrfilt.c,v 1.8 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -32,6 +28,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "addrfilt.h"

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/addrfilt.h,v 1.6 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/broadcast.c,v 1.3 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -28,6 +24,8 @@
Deal with broadcast server functions.
*/
#include "config.h"
#include "sysincl.h"
#include "memory.h"
@@ -75,15 +73,14 @@ timeout_handler(void *arbitrary)
int leap;
int are_we_synchronised, our_stratum;
NTP_Leap leap_status;
unsigned long our_ref_id;
uint32_t our_ref_id, ts_fuzz;
struct timeval our_ref_time;
double our_root_delay, our_root_dispersion;
double local_time_err;
struct timeval local_transmit;
version = 3;
LCL_ReadCookedTime(&local_transmit, &local_time_err);
LCL_ReadCookedTime(&local_transmit, NULL);
REF_GetReferenceParams(&local_transmit,
&are_we_synchronised, &leap_status,
&our_stratum,
@@ -94,7 +91,7 @@ timeout_handler(void *arbitrary)
if (are_we_synchronised) {
leap = (int) leap_status;
} else {
leap = 3;
leap = LEAP_Unsynchronised;
}
message.lvm = ((leap << 6) &0xc0) | ((version << 3) & 0x38) | (MODE_BROADCAST & 0x07);
@@ -110,19 +107,20 @@ timeout_handler(void *arbitrary)
message.reference_id = htonl((NTP_int32) our_ref_id);
/* 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.lo = 0UL;
message.receive_ts.hi = 0UL;
message.receive_ts.lo = 0UL;
LCL_ReadCookedTime(&local_transmit, &local_time_err);
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts);
ts_fuzz = UTI_GetNTPTsFuzz(message.precision);
LCL_ReadCookedTime(&local_transmit, NULL);
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz);
NIO_SendNormalPacket(&message, &d->addr);
/* Requeue timeout. Don't care if interval drifts gradually, so just do it
* at the end. */
SCH_AddTimeoutInClass((double) d->interval, 1.0,
SCH_AddTimeoutInClass((double) d->interval, 1.0, 0.02,
SCH_NtpBroadcastClass,
timeout_handler, (void *) d);
@@ -149,7 +147,7 @@ BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval;
SCH_AddTimeoutInClass((double) interval, 1.0,
SCH_AddTimeoutInClass((double) interval, 1.0, 0.0,
SCH_NtpBroadcastClass,
timeout_handler, (void *)(destinations + n_destinations));

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/broadcast.h,v 1.2 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

80
candm.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/candm.h,v 1.40 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -35,6 +31,7 @@
#include "sysincl.h"
#include "addressing.h"
#include "hash.h"
/* This is the default port to use for CANDM, if no alternative is
defined */
@@ -86,7 +83,12 @@
#define REQ_MANUAL_DELETE 42
#define REQ_MAKESTEP 43
#define REQ_ACTIVITY 44
#define N_REQUEST_TYPES 45
#define REQ_MODIFY_MINSTRATUM 45
#define REQ_MODIFY_POLLTARGET 46
#define REQ_MODIFY_MAXDELAYDEVRATIO 47
#define REQ_RESELECT 48
#define REQ_RESELECTDISTANCE 49
#define N_REQUEST_TYPES 50
/* Special utoken value used to log on with first exchange being the
password. (This time value has long since gone by) */
@@ -162,6 +164,24 @@ typedef struct {
int32_t EOR;
} REQ_Modify_Maxdelayratio;
typedef struct {
IPAddr address;
Float new_max_delay_dev_ratio;
int32_t EOR;
} REQ_Modify_Maxdelaydevratio;
typedef struct {
IPAddr address;
int32_t new_min_stratum;
int32_t EOR;
} REQ_Modify_Minstratum;
typedef struct {
IPAddr address;
int32_t new_poll_target;
int32_t EOR;
} REQ_Modify_Polltarget;
typedef struct {
Float new_max_update_skew;
int32_t EOR;
@@ -215,6 +235,9 @@ typedef struct {
/* Flags used in NTP source requests */
#define REQ_ADDSRC_ONLINE 0x1
#define REQ_ADDSRC_AUTOOFFLINE 0x2
#define REQ_ADDSRC_IBURST 0x4
#define REQ_ADDSRC_PREFER 0x8
#define REQ_ADDSRC_NOSELECT 0x10
typedef struct {
IPAddr ip_addr;
@@ -314,6 +337,15 @@ typedef struct {
int32_t EOR;
} REQ_Activity;
typedef struct {
int32_t EOR;
} REQ_Reselect;
typedef struct {
Float distance;
int32_t EOR;
} REQ_ReselectDistance;
/* ================================================== */
#define PKT_TYPE_CMD_REQUEST 1
@@ -334,11 +366,14 @@ typedef struct {
Version 4 : IPv6 addressing added, 64-bit time values, sourcestats
and tracking reports extended, added flags to NTP source request,
trimmed source report, replaced fixed-point format with floating-point
and used also instead of integer microseconds
and used also instead of integer microseconds, new commands: modify stratum,
modify polltarget, modify maxdelaydevratio, reselect, reselectdistance
Version 5 : auth data moved to the end of the packet to allow hashes with
different sizes, extended sources, tracking and activity reports
*/
#define PROTO_VERSION_NUMBER 4
#define PROTO_VERSION_NUMBER 5
/* The oldest protocol version that is compatible enough with
the current version to report a version mismatch */
@@ -358,7 +393,6 @@ typedef struct {
uint32_t sequence; /* Client's sequence number */
uint32_t utoken; /* Unique token per incarnation of daemon */
uint32_t token; /* Command token (to prevent replay attack) */
uint32_t auth[4]; /* MD5 authentication of the packet */
union {
REQ_Online online;
@@ -369,6 +403,9 @@ typedef struct {
REQ_Dump dump;
REQ_Modify_Maxdelay modify_maxdelay;
REQ_Modify_Maxdelayratio modify_maxdelayratio;
REQ_Modify_Maxdelaydevratio modify_maxdelaydevratio;
REQ_Modify_Minstratum modify_minstratum;
REQ_Modify_Polltarget modify_polltarget;
REQ_Modify_Maxupdateskew modify_maxupdateskew;
REQ_Logon logon;
REQ_Settime settime;
@@ -396,8 +433,14 @@ typedef struct {
REQ_ManualDelete manual_delete;
REQ_MakeStep make_step;
REQ_Activity activity;
REQ_Reselect reselect;
REQ_ReselectDistance reselect_distance;
} data; /* Command specific parameters */
/* authentication of the packet, there is no hole after the actual data
from the data union, this field only sets the maximum auth size */
uint8_t auth[MAX_HASH_LENGTH];
} CMD_Request;
/* ================================================== */
@@ -463,7 +506,11 @@ typedef struct {
#define RPY_SD_ST_UNREACH 1
#define RPY_SD_ST_FALSETICKER 2
#define RPY_SD_ST_JITTERY 3
#define RPY_SD_ST_OTHER 4
#define RPY_SD_ST_CANDIDATE 4
#define RPY_SD_ST_OUTLYER 5
#define RPY_SD_FLAG_NOSELECT 0x1
#define RPY_SD_FLAG_PREFER 0x2
typedef struct {
IPAddr ip_addr;
@@ -471,6 +518,8 @@ typedef struct {
uint16_t stratum;
uint16_t state;
uint16_t mode;
uint16_t flags;
uint16_t reachability;
uint32_t since_sample;
Float orig_latest_meas;
Float latest_meas;
@@ -481,14 +530,18 @@ typedef struct {
typedef struct {
uint32_t ref_id;
IPAddr ip_addr;
uint32_t stratum;
uint16_t stratum;
uint16_t leap_status;
Timeval ref_time;
Float current_correction;
Float last_offset;
Float rms_offset;
Float freq_ppm;
Float resid_freq_ppm;
Float skew_ppm;
Float root_delay;
Float root_dispersion;
Float last_update_interval;
int32_t EOR;
} RPY_Tracking;
@@ -576,6 +629,7 @@ typedef struct {
int32_t offline;
int32_t burst_online;
int32_t burst_offline;
int32_t unresolved;
int32_t EOR;
} RPY_Activity;
@@ -594,8 +648,6 @@ typedef struct {
uint32_t utoken; /* Unique token per incarnation of daemon */
uint32_t token; /* New command token (only if command was successfully
authenticated) */
uint32_t auth[4]; /* MD5 authentication of the packet */
union {
RPY_Null null;
RPY_N_Sources n_sources;
@@ -611,6 +663,10 @@ typedef struct {
RPY_Activity activity;
} data; /* Reply specific parameters */
/* authentication of the packet, there is no hole after the actual data
from the data union, this field only sets the maximum auth size */
uint8_t auth[MAX_HASH_LENGTH];
} CMD_Reply;
/* ================================================== */

View File

@@ -1,4 +1,4 @@
.TH CHRONY 1 "December 04, 2009" chrony "User's Manual"
.TH CHRONY 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
.SH NAME
chrony \- programs for keeping computer clocks accurate

View File

@@ -1,4 +1,4 @@
.TH chrony.conf 5 "December 04, 2009" chrony "Configuration Files"
.TH chrony.conf 5 "@MAN_DATE@" "chrony @VERSION@" "Configuration Files"
.SH NAME
chrony.conf \- chronyd configuration file

View File

@@ -1,29 +0,0 @@
Begin3
Title: chrony
Version: 1.18
Entered-date: 01APR02
Description: A pair of programs for keeping computer clocks accurate.
chronyd is a background (daemon) program and chronyc is a
command-line interface to it. Time reference sources for
chronyd can be RFC1305 NTP servers, human (via keyboard and
chronyc), and the computer's real-time clock at boot time
(Linux only). chronyd can determine the rate at which the
computer gains or loses time and compensate for it whilst no
external reference is present. chronyd's 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.
Keywords: time NTP RFC1305 RTC adjtime
Author: rc@rc0.org.uk (Richard Curnow)
Maintained-by: rc@rc0.org.uk (Richard Curnow)
Primary-site: chrony.tuxfamily.org
295k chrony-1.18.tar.gz
2k chrony.lsm
Platforms: Linux 2.0/2.1/2.2/2.3/2.4 (x86, powerpc)
Solaris 2.5/6/7/8, SunOS 4.1.4. (Sparc)
BSDI/386.
NetBSD
Solaris 2.8 (x86)
Copying-policy: GPL
End

File diff suppressed because it is too large Load Diff

View File

@@ -35,8 +35,13 @@ struct timex {
int :32; int :32; int :32; int :32;
};
#define ADJ_OFFSET 0x0001 /* time offset */
#define ADJ_FREQUENCY 0x0002 /* frequency offset */
#define ADJ_MAXERROR 0x0004 /* maximum time error */
#define ADJ_STATUS 0x0010 /* clock status */
#define ADJ_TIMECONST 0x0020 /* pll time constant */
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
#define ADJ_NANO 0x2000 /* select nanosecond resolution */
#define ADJ_TICK 0x4000 /* tick value */
#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
@@ -59,6 +64,7 @@ struct timex {
#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
#define STA_NANO 0x2000 /* resolution (0 = us, 1 = ns) (ro) */
/* This doesn't seem to be in any include files !! */

View File

@@ -1,4 +1,4 @@
.TH CHRONYC 1 "December 04, 2009" chrony "User's Manual"
.TH CHRONYC 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
.SH NAME
chronyc \- command-line interface for chronyd
@@ -38,14 +38,14 @@ resolve hostnames only to IPv4 addresses
\fB\-6\fR
resolve hostnames only to IPv6 addresses
.TP
\fB\-m\fR
allow multiple commands to be specified on the command line. Each argument
will be interpreted as a whole command.
.TP
\fIcommand\fR
specify command. If no command is given, chronyc will read commands
interactively.
.SH VERSION
1.24
.SH BUGS
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
@@ -63,4 +63,3 @@ Man Pages Project". Please see \fIhttp://www.netmeister.org/misc/m2p2/index.htm
for details.
The complete chrony documentation is supplied in texinfo format.

View File

@@ -1,4 +1,4 @@
.TH CHRONYD 8 "December 04, 2009" chrony "System Administration"
.TH CHRONYD 8 "@MAN_DATE@" "chrony @VERSION@" "System Administration"
.SH NAME
chronyd \- chrony background daemon
@@ -45,6 +45,10 @@ Linux.
This option will lock chronyd into RAM so that it will never be paged out.
This mode is only supported on Linux.
.TP
.B \-n
When run in this mode, the program will not detach itself from the
terminal.
.TP
.B \-d
When run in this mode, the program will not detach itself from the
terminal, and all messages will be sent to the terminal instead of
@@ -104,9 +108,6 @@ Resolve hostnames only to IPv6 addresses.
.SH FILES
\fI/etc/chrony.conf\fR
.SH VERSION
Version 1.24
.SH BUGS
To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR

643
client.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/clientlog.c,v 1.11 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -35,6 +31,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "clientlog.h"
#include "conf.h"

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/clientlog.h,v 1.9 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

371
cmdmon.c
View File

@@ -1,13 +1,9 @@
/*
$Header: /cvs/src/chrony/cmdmon.c,v 1.55 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009-2012
*
* 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
@@ -29,6 +25,8 @@
Command and monitoring module in the main program
*/
#include "config.h"
#include "sysincl.h"
#include "cmdmon.h"
@@ -152,13 +150,18 @@ static int permissions[] = {
PERMIT_OPEN, /* RTCREPORT */
PERMIT_AUTH, /* TRIMRTC */
PERMIT_AUTH, /* CYCLELOGS */
PERMIT_OPEN, /* SUBNETS_ACCESSED */
PERMIT_OPEN, /* CLIENT_ACCESSES (by subnet) */
PERMIT_OPEN, /* CLIENT_ACCESSES_BY_INDEX */
PERMIT_AUTH, /* SUBNETS_ACCESSED */
PERMIT_AUTH, /* CLIENT_ACCESSES (by subnet) */
PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX */
PERMIT_OPEN, /* MANUAL_LIST */
PERMIT_AUTH, /* MANUAL_DELETE */
PERMIT_AUTH, /* MAKESTEP */
PERMIT_OPEN /* ACTIVITY */
PERMIT_OPEN, /* ACTIVITY */
PERMIT_AUTH, /* MODIFY_MINSTRATUM */
PERMIT_AUTH, /* MODIFY_POLLTARGET */
PERMIT_AUTH, /* MODIFY_MAXDELAYDEVRATIO */
PERMIT_AUTH, /* RESELECT */
PERMIT_AUTH /* RESELECTDISTANCE */
};
/* ================================================== */
@@ -195,6 +198,9 @@ prepare_socket(int family)
return -1;
}
/* Close on exec */
UTI_FdSetCloexec(sock_fd);
/* Allow reuse of port number */
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_CmdMon, "Could not set reuseaddr socket options");
@@ -261,16 +267,10 @@ prepare_socket(int family)
void
CAM_Initialise(void)
{
if (initialised) {
CROAK("Shouldn't be initialised");
}
assert(!initialised);
initialised = 1;
if ((sizeof(permissions)/sizeof(permissions[0])) != N_REQUEST_TYPES) {
CROAK("Permissions table size wrong");
}
assert(sizeof (permissions) / sizeof (permissions[0]) == N_REQUEST_TYPES);
utoken = (unsigned long) time(NULL);
@@ -328,57 +328,28 @@ CAM_Finalise(void)
rest of the packet */
static int
check_rx_packet_auth(CMD_Request *packet)
check_rx_packet_auth(CMD_Request *packet, int packet_len)
{
char *key;
int keylen;
int pkt_len;
MD5_CTX ctx;
int pkt_len, auth_len;
pkt_len = PKL_CommandLength(packet);
auth_len = packet_len - pkt_len;
KEY_CommandKey(&key, &keylen);
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) key, keylen);
MD5Update(&ctx, (unsigned char *) packet, offsetof(CMD_Request, auth));
if (pkt_len > offsetof(CMD_Request, data)) {
MD5Update(&ctx, (unsigned char *) &(packet->data), pkt_len - offsetof(CMD_Request, data));
}
MD5Final(&ctx);
if (!memcmp((void *) &ctx.digest, (void *) &(packet->auth), 16)) {
return 1;
} else {
return 0;
}
return KEY_CheckAuth(KEY_GetCommandKey(), (unsigned char *)packet,
pkt_len, ((unsigned char *)packet) + pkt_len, auth_len);
}
/* ================================================== */
static void
static int
generate_tx_packet_auth(CMD_Reply *packet)
{
char *key;
int keylen;
MD5_CTX ctx;
int pkt_len;
pkt_len = PKL_ReplyLength(packet);
KEY_CommandKey(&key, &keylen);
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) key, keylen);
MD5Update(&ctx, (unsigned char *) packet, offsetof(CMD_Request, auth));
if (pkt_len > offsetof(CMD_Reply, data)) {
MD5Update(&ctx, (unsigned char *) &(packet->data), pkt_len - offsetof(CMD_Reply, data));
}
MD5Final(&ctx);
memcpy(&(packet->auth), &ctx.digest, 16);
return KEY_GenerateAuth(KEY_GetCommandKey(), (unsigned char *)packet,
pkt_len, ((unsigned char *)packet) + pkt_len, sizeof (packet->auth));
}
/* ================================================== */
@@ -720,7 +691,7 @@ print_reply_packet(CMD_Reply *pkt)
/* ================================================== */
static void
transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to, int auth_len)
{
int status;
int tx_message_length;
@@ -742,7 +713,7 @@ transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
assert(0);
}
tx_message_length = PKL_ReplyLength(msg);
tx_message_length = PKL_ReplyLength(msg) + auth_len;
status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
&where_to->u, addrlen);
@@ -908,6 +879,59 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
/* ================================================== */
static void
handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address);
status = NSR_ModifyMaxdelaydevratio(&address,
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio));
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE);
}
}
/* ================================================== */
static void
handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
status = NSR_ModifyMinstratum(&address,
ntohl(rx_message->data.modify_minstratum.new_min_stratum));
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE);
}
}
/* ================================================== */
static void
handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int status;
IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_polltarget.address, &address);
status = NSR_ModifyPolltarget(&address,
ntohl(rx_message->data.modify_polltarget.new_poll_target));
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE);
}
}
/* ================================================== */
static void
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
{
@@ -991,10 +1015,9 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_SourceReport report;
struct timeval now_corr;
double local_clock_err;
/* Get data */
LCL_ReadCookedTime(&now_corr, &local_clock_err);
LCL_ReadCookedTime(&now_corr, NULL);
if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
case SRC_NTP:
@@ -1024,8 +1047,8 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
case RPT_JITTERY:
tx_message->data.source_data.state = htons(RPY_SD_ST_JITTERY);
break;
case RPT_OTHER:
tx_message->data.source_data.state = htons(RPY_SD_ST_OTHER);
case RPT_CANDIDATE:
tx_message->data.source_data.state = htons(RPY_SD_ST_CANDIDATE);
break;
}
switch (report.mode) {
@@ -1039,6 +1062,18 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.source_data.mode = htons(RPY_SD_MD_REF);
break;
}
switch (report.sel_option) {
case RPT_NORMAL:
tx_message->data.source_data.flags = htons(0);
break;
case RPT_PREFER:
tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER);
break;
case RPT_NOSELECT:
tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER);
break;
}
tx_message->data.source_data.reachability = htons(report.reachability);
tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago);
tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas);
tx_message->data.source_data.latest_meas = UTI_FloatHostToNetwork(report.latest_meas);
@@ -1216,7 +1251,7 @@ handle_cmdaccheck(CMD_Request *rx_message, CMD_Reply *tx_message)
/* ================================================== */
static void
handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_message)
{
NTP_Remote_Address rem_addr;
SourceParameters params;
@@ -1231,9 +1266,18 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
params.sel_option = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SelectPrefer :
ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SelectNoselect : SRC_SelectNormal;
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddServer(&rem_addr, &params);
/* not transmitted in cmdmon protocol yet */
params.min_stratum = SRC_DEFAULT_MINSTRATUM;
params.poll_target = SRC_DEFAULT_POLLTARGET;
params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
status = NSR_AddSource(&rem_addr, type, &params);
switch (status) {
case NSR_Success:
tx_message->status = htons(STT_SUCCESS);
@@ -1248,47 +1292,7 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource:
CROAK("Impossible");
break;
}
}
/* ================================================== */
static void
handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
{
NTP_Remote_Address rem_addr;
SourceParameters params;
NSR_Status status;
UTI_IPNetworkToHost(&rx_message->data.ntp_source.ip_addr, &rem_addr.ip_addr);
rem_addr.local_ip_addr.family = IPADDR_UNSPEC;
rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddPeer(&rem_addr, &params);
switch (status) {
case NSR_Success:
tx_message->status = htons(STT_SUCCESS);
break;
case NSR_AlreadyInUse:
tx_message->status = htons(STT_SOURCEALREADYKNOWN);
break;
case NSR_TooManySources:
tx_message->status = htons(STT_TOOMANYSOURCES);
break;
case NSR_InvalidAF:
tx_message->status = htons(STT_INVALIDAF);
break;
case NSR_NoSuchSource:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -1316,7 +1320,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
case NSR_TooManySources:
case NSR_AlreadyInUse:
case NSR_InvalidAF:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -1348,6 +1352,7 @@ handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
tx_message->status = htons(STT_SUCCESS);
}
/* ================================================== */
@@ -1361,7 +1366,8 @@ handle_doffset(CMD_Request *rx_message, CMD_Reply *tx_message)
usec = (long)(ntohl(rx_message->data.doffset.usec));
doffset = (double) sec + 1.0e-6 * (double) usec;
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
LCL_AccumulateOffset(doffset);
LCL_AccumulateOffset(doffset, 0.0);
tx_message->status = htons(STT_SUCCESS);
}
/* ================================================== */
@@ -1376,14 +1382,18 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->reply = htons(RPY_TRACKING);
tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
tx_message->data.tracking.stratum = htonl(rpt.stratum);
tx_message->data.tracking.stratum = htons(rpt.stratum);
tx_message->data.tracking.leap_status = htons(rpt.leap_status);
UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
tx_message->data.tracking.current_correction = UTI_FloatHostToNetwork(rpt.current_correction);
tx_message->data.tracking.last_offset = UTI_FloatHostToNetwork(rpt.last_offset);
tx_message->data.tracking.rms_offset = UTI_FloatHostToNetwork(rpt.rms_offset);
tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
tx_message->data.tracking.last_update_interval = UTI_FloatHostToNetwork(rpt.last_update_interval);
}
/* ================================================== */
@@ -1394,9 +1404,8 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
int status;
RPT_SourcestatsReport report;
struct timeval now_corr;
double local_clock_err;
LCL_ReadCookedTime(&now_corr, &local_clock_err);
LCL_ReadCookedTime(&now_corr, NULL);
status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
&report, &now_corr);
@@ -1461,11 +1470,7 @@ handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
{
NCR_CycleLogFile();
SST_CycleLogFile();
REF_CycleLogFile();
RTC_CycleLogFile();
RCL_CycleLogFile();
LOG_CycleLogFiles();
tx_message->status = htons(STT_SUCCESS);
return;
@@ -1512,7 +1517,7 @@ handle_subnets_accessed(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_INACTIVE);
return;
default:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -1531,9 +1536,8 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
IPAddr ip;
int i;
struct timeval now;
double local_time_error;
LCL_ReadCookedTime(&now, &local_time_error);
LCL_ReadCookedTime(&now, NULL);
nc = ntohl(rx_message->data.client_accesses.n_clients);
tx_message->status = htons(STT_SUCCESS);
@@ -1568,7 +1572,7 @@ handle_client_accesses(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_INACTIVE);
return;
default:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -1585,9 +1589,8 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
unsigned long first_index, n_indices, last_index, n_indices_in_table;
int i, j;
struct timeval now;
double local_time_error;
LCL_ReadCookedTime(&now, &local_time_error);
LCL_ReadCookedTime(&now, NULL);
first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices);
@@ -1621,7 +1624,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_INACTIVE);
return;
default:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -1692,12 +1695,35 @@ handle_activity(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.activity.offline = htonl(report.offline);
tx_message->data.activity.burst_online = htonl(report.burst_online);
tx_message->data.activity.burst_offline = htonl(report.burst_offline);
tx_message->data.activity.unresolved = htonl(report.unresolved);
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_ACTIVITY);
}
/* ================================================== */
static void
handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
{
double dist;
dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
SRC_SetReselectDistance(dist);
tx_message->status = htons(STT_SUCCESS);
return;
}
/* ================================================== */
static void
handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
{
SRC_ReselectSource();
tx_message->status = htons(STT_SUCCESS);
return;
}
/* ================================================== */
#if 0
/* ================================================== */
@@ -1718,7 +1744,7 @@ read_from_cmd_socket(void *anything)
{
int status;
int read_length; /* Length of packet read */
int expected_length; /* Expected length of packet */
int expected_length; /* Expected length of packet without auth data */
unsigned long flags;
CMD_Request rx_message;
CMD_Reply tx_message, *prev_tx_message;
@@ -1728,7 +1754,8 @@ read_from_cmd_socket(void *anything)
socklen_t from_length;
IPAddr remote_ip;
unsigned short remote_port;
int md5_ok;
int auth_length;
int auth_ok;
int utoken_ok, token_ok;
int issue_token;
int valid_ts;
@@ -1742,7 +1769,6 @@ read_from_cmd_socket(void *anything)
unsigned long rx_attempt;
struct timeval now;
struct timeval cooked_now;
double local_clock_err;
flags = 0;
rx_message_length = sizeof(rx_message);
@@ -1760,9 +1786,10 @@ read_from_cmd_socket(void *anything)
read_length = status;
expected_length = PKL_CommandLength(&rx_message);
rx_command = ntohs(rx_message.command);
LCL_ReadRawTime(&now);
LCL_ReadCookedTime(&cooked_now, &local_clock_err);
LCL_CookTime(&now, &cooked_now, NULL);
tx_message.version = PROTO_VERSION_NUMBER;
tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
@@ -1822,27 +1849,42 @@ read_from_cmd_socket(void *anything)
if (rx_message.version != PROTO_VERSION_NUMBER) {
tx_message.status = htons(STT_NOHOSTACCESS);
if (!LOG_RateLimited()) {
LOG(LOGS_WARN, LOGF_CmdMon, "Read packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
}
if (allowed)
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT) {
tx_message.status = htons(STT_BADPKTVERSION);
transmit_reply(&tx_message, &where_from);
/* add empty MD5 auth so older clients will not drop
the reply due to bad length */
memset(((char *)&tx_message) + PKL_ReplyLength(&tx_message), 0, 16);
transmit_reply(&tx_message, &where_from, 16);
}
return;
}
if (read_length != expected_length) {
if (rx_command >= N_REQUEST_TYPES) {
if (!LOG_RateLimited()) {
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
LOG(LOGS_WARN, LOGF_CmdMon, "Read command packet with invalid command %d from %s:%hu", rx_command, UTI_IPToString(&remote_ip), remote_port);
}
if (allowed)
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
tx_message.status = htons(STT_INVALID);
transmit_reply(&tx_message, &where_from, 0);
return;
}
if (read_length < expected_length) {
if (!LOG_RateLimited()) {
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized command packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
}
if (allowed)
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
tx_message.status = htons(STT_BADPKTLENGTH);
transmit_reply(&tx_message, &where_from);
transmit_reply(&tx_message, &where_from, 0);
return;
}
@@ -1859,31 +1901,29 @@ read_from_cmd_socket(void *anything)
}
tx_message.status = htons(STT_NOHOSTACCESS);
transmit_reply(&tx_message, &where_from);
transmit_reply(&tx_message, &where_from, 0);
return;
}
rx_command = ntohs(rx_message.command);
/* OK, we have a valid message. Now dispatch on message type and process it. */
/* Do authentication stuff and command tokens here. Well-behaved
clients will set their utokens to 0 to save us wasting our time
if the packet is unauthenticatable. */
if (rx_message.utoken != 0) {
md5_ok = check_rx_packet_auth(&rx_message);
auth_ok = check_rx_packet_auth(&rx_message, read_length);
} else {
md5_ok = 0;
auth_ok = 0;
}
/* All this malarky is to protect the system against various forms
of attack.
Simple packet forgeries are blocked by requiring the packet to
authenticate properly with MD5. (The assumption is that the
command key is in a read-only keys file read by the daemon, and
is known only to administrators.)
authenticate properly with MD5 or other crypto hash. (The
assumption is that the command key is in a read-only keys file
read by the daemon, and is known only to administrators.)
Replay attacks are prevented by 2 fields in the packet. The
'token' field is where the client plays back to us a token that
@@ -1925,13 +1965,13 @@ read_from_cmd_socket(void *anything)
rx_message_seq = ntohl(rx_message.sequence);
rx_attempt = ntohs(rx_message.attempt);
if (md5_ok && utoken_ok) {
if (auth_ok && utoken_ok) {
token_ok = check_token(rx_message_token);
} else {
token_ok = 0;
}
if (md5_ok && utoken_ok && !token_ok) {
if (auth_ok && utoken_ok && !token_ok) {
/* This might be a resent message, due to the client not getting
our reply to the first attempt. See if we can find the message. */
prev_tx_message = lookup_reply(rx_message_token, rx_message_seq, rx_attempt);
@@ -1949,14 +1989,14 @@ read_from_cmd_socket(void *anything)
}
if (md5_ok && utoken_ok && token_ok) {
if (auth_ok && utoken_ok && token_ok) {
/* See whether we can discard the previous reply from storage */
token_acknowledged(rx_message_token, &now);
}
valid_ts = 0;
if (md5_ok) {
if (auth_ok) {
struct timeval ts;
UTI_TimevalNetworkToHost(&rx_message.data.logon.ts, &ts);
@@ -1971,7 +2011,7 @@ read_from_cmd_socket(void *anything)
issue_token = 0;
}
authenticated = md5_ok & utoken_ok & token_ok;
authenticated = auth_ok & utoken_ok & token_ok;
if (authenticated) {
CLG_LogCommandAccess(&remote_ip, CLG_CMD_AUTH, cooked_now.tv_sec);
@@ -1991,10 +2031,9 @@ read_from_cmd_socket(void *anything)
tx_message.token = htonl(tx_message_token);
/* If command type is invalid, send back reply */
if (rx_command >= N_REQUEST_TYPES) {
tx_message.status = htons(STT_INVALID);
tx_message.reply = htons(RPY_NULL);
/* This should be already handled */
assert(0);
} else {
allowed = 0;
@@ -2018,7 +2057,7 @@ read_from_cmd_socket(void *anything)
allowed = 1;
break;
default:
CROAK("Impossible");
assert(0);
}
if (allowed) {
@@ -2060,6 +2099,10 @@ read_from_cmd_socket(void *anything)
handle_modify_maxdelayratio(&rx_message, &tx_message);
break;
case REQ_MODIFY_MAXDELAYDEVRATIO:
handle_modify_maxdelaydevratio(&rx_message, &tx_message);
break;
case REQ_MODIFY_MAXUPDATESKEW:
handle_modify_maxupdateskew(&rx_message, &tx_message);
break;
@@ -2068,15 +2111,15 @@ read_from_cmd_socket(void *anything)
/* If the log-on fails, record the reason why */
if (!issue_token && !LOG_RateLimited()) {
LOG(LOGS_WARN, LOGF_CmdMon,
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
"Bad command logon from %s port %d (auth_ok=%d valid_ts=%d)",
UTI_IPToString(&remote_ip),
remote_port,
md5_ok, valid_ts);
auth_ok, valid_ts);
}
if (issue_token == 1) {
tx_message.status = htons(STT_SUCCESS);
} else if (!md5_ok) {
} else if (!auth_ok) {
tx_message.status = htons(STT_UNAUTH);
} else if (!valid_ts) {
tx_message.status = htons(STT_INVALIDTS);
@@ -2151,11 +2194,11 @@ read_from_cmd_socket(void *anything)
break;
case REQ_ADD_SERVER:
handle_add_server(&rx_message, &tx_message);
handle_add_source(NTP_SERVER, &rx_message, &tx_message);
break;
case REQ_ADD_PEER:
handle_add_peer(&rx_message, &tx_message);
handle_add_source(NTP_PEER, &rx_message, &tx_message);
break;
case REQ_DEL_SOURCE:
@@ -2222,8 +2265,24 @@ read_from_cmd_socket(void *anything)
handle_activity(&rx_message, &tx_message);
break;
case REQ_RESELECTDISTANCE:
handle_reselect_distance(&rx_message, &tx_message);
break;
case REQ_RESELECT:
handle_reselect(&rx_message, &tx_message);
break;
case REQ_MODIFY_MINSTRATUM:
handle_modify_minstratum(&rx_message, &tx_message);
break;
case REQ_MODIFY_POLLTARGET:
handle_modify_polltarget(&rx_message, &tx_message);
break;
default:
/* Ignore message */
assert(0);
break;
}
} else {
@@ -2231,8 +2290,10 @@ read_from_cmd_socket(void *anything)
}
}
if (md5_ok) {
generate_tx_packet_auth(&tx_message);
if (auth_ok) {
auth_length = generate_tx_packet_auth(&tx_message);
} else {
auth_length = 0;
}
if (token_ok) {
@@ -2251,7 +2312,7 @@ read_from_cmd_socket(void *anything)
static int do_it=1;
if (do_it) {
transmit_reply(&tx_message, &where_from);
transmit_reply(&tx_message, &where_from, auth_length);
}
#if 0

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/cmdmon.h,v 1.8 2002/02/28 23:27:09 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/cmdparse.c,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -30,9 +26,12 @@
*/
#include "config.h"
#include "sysincl.h"
#include "cmdparse.h"
#include "memory.h"
#include "nameserv.h"
#define MAXLEN 2047
@@ -47,24 +46,27 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
char cmd[MAXLEN+1], hostname[MAXLEN+1];
CPS_Status result;
src->port = 123;
src->params.minpoll = 6;
src->params.maxpoll = 10;
src->params.presend_minpoll = 0;
src->port = SRC_DEFAULT_PORT;
src->params.minpoll = SRC_DEFAULT_MINPOLL;
src->params.maxpoll = SRC_DEFAULT_MAXPOLL;
src->params.presend_minpoll = SRC_DEFAULT_PRESEND_MINPOLL;
src->params.authkey = INACTIVE_AUTHKEY;
src->params.max_delay = 16.0;
src->params.max_delay_ratio = 16384.0;
src->params.max_delay = SRC_DEFAULT_MAXDELAY;
src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO;
src->params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
src->params.online = 1;
src->params.auto_offline = 0;
src->params.iburst = 0;
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
src->params.sel_option = SRC_SelectNormal;
result = CPS_Success;
ok = 0;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
ok = 1;
}
}
if (!ok) {
result = CPS_BadHost;
@@ -112,6 +114,14 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else {
line += n;
}
} else if (!strncasecmp(cmd, "maxdelaydevratio", 16)) {
if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) {
result = CPS_BadMaxdelaydevratio;
ok = 0;
done = 1;
} else {
line += n;
}
/* This MUST come before the following one ! */
} else if (!strncasecmp(cmd, "maxdelayratio", 13)) {
if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) {
@@ -143,6 +153,33 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} else if (!strncasecmp(cmd, "auto_offline", 12)) {
src->params.auto_offline = 1;
} else if (!strncasecmp(cmd, "iburst", 6)) {
src->params.iburst = 1;
} else if (!strncasecmp(cmd, "minstratum", 10)) {
if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) {
result = CPS_BadMinstratum;
ok = 0;
done = 1;
} else {
line += n;
}
} else if (!strncasecmp(cmd, "polltarget", 10)) {
if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
result = CPS_BadPolltarget;
ok = 0;
done = 1;
} else {
line += n;
}
} else if (!strncasecmp(cmd, "noselect", 8)) {
src->params.sel_option = SRC_SelectNoselect;
} else if (!strncasecmp(cmd, "prefer", 6)) {
src->params.sel_option = SRC_SelectPrefer;
} else {
result = CPS_BadOption;
ok = 0;
@@ -154,6 +191,13 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
} while (!done);
}
if (ok) {
n = strlen(hostname);
src->name = MallocArray(char, n + 1);
strncpy(src->name, hostname, n);
src->name[n] = '\0';
}
return result;
}

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/cmdparse.h,v 1.7 2002/02/28 23:27:09 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -42,13 +38,16 @@ typedef enum {
CPS_BadMinpoll,
CPS_BadMaxpoll,
CPS_BadPresend,
CPS_BadMaxdelaydevratio,
CPS_BadMaxdelayratio,
CPS_BadMaxdelay,
CPS_BadKey
CPS_BadKey,
CPS_BadMinstratum,
CPS_BadPolltarget
} CPS_Status;
typedef struct {
IPAddr ip_addr;
char *name;
unsigned short port;
SourceParameters params;
} CPS_NTP_Source;

391
conf.c
View File

@@ -1,13 +1,9 @@
/*
$Header: /cvs/src/chrony/conf.c,v 1.45 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009-2012
*
* 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
@@ -40,6 +36,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "conf.h"
@@ -74,8 +72,13 @@ static void parse_dumponexit(const char *);
static void parse_keyfile(const char *);
static void parse_rtcfile(const char *);
static void parse_log(const char *);
static void parse_logbanner(const char *);
static void parse_logdir(const char *);
static void parse_maxupdateskew(const char *);
static void parse_maxclockerror(const char *);
static void parse_corrtimeratio(const char *);
static void parse_reselectdist(const char *);
static void parse_stratumweight(const char *);
static void parse_peer(const char *);
static void parse_acquisitionport(const char *);
static void parse_port(const char *);
@@ -90,9 +93,12 @@ static void parse_cmdallow(const char *);
static void parse_cmddeny(const char *);
static void parse_cmdport(const char *);
static void parse_rtconutc(const char *);
static void parse_rtcsync(const char *);
static void parse_noclientlog(const char *);
static void parse_clientloglimit(const char *);
static void parse_fallbackdrift(const char *);
static void parse_makestep(const char *);
static void parse_maxchange(const char *);
static void parse_logchange(const char *);
static void parse_mailonchange(const char *);
static void parse_bindaddress(const char *);
@@ -104,6 +110,9 @@ static void parse_linux_hz(const char *);
static void parse_linux_freq_scale(const char *);
static void parse_sched_priority(const char *);
static void parse_lockall(const char *);
static void parse_tempcomp(const char *);
static void parse_include(const char *);
static void parse_leapsectz(const char *);
/* ================================================== */
/* Configuration variables */
@@ -115,7 +124,12 @@ static char *keys_file = NULL;
static char *drift_file = NULL;
static char *rtc_file = NULL;
static unsigned long command_key_id;
static double max_update_skew = DBL_MAX;
static double max_update_skew = 1000.0;
static double correction_time_ratio = 1.0;
static double max_clock_error = 1.0; /* in ppm */
static double reselect_distance = 1e-4;
static double stratum_weight = 1.0;
static int cmd_port = -1;
@@ -124,7 +138,9 @@ static int do_log_statistics = 0;
static int do_log_tracking = 0;
static int do_log_rtc = 0;
static int do_log_refclocks = 0;
static int do_log_tempcomp = 0;
static int do_dump_on_exit = 0;
static int log_banner = 32;
static char *logdir = ".";
static char *dumpdir = ".";
@@ -147,10 +163,19 @@ static int enable_manual=0;
incl. daylight saving). */
static int rtc_on_utc = 0;
/* Flag set if the RTC should be automatically synchronised by kernel */
static int rtc_sync = 0;
/* Limit and threshold for clock stepping */
static int make_step_limit = 0;
static double make_step_threshold = 0.0;
/* Number of updates before offset checking, number of ignored updates
before exiting and the maximum allowed offset */
static int max_offset_delay = -1;
static int max_offset_ignore;
static double max_offset;
/* Flag set if we should log to syslog when a time adjustment
exceeding the threshold is initiated */
static int do_log_change = 0;
@@ -166,6 +191,10 @@ static int no_client_log = 0;
/* Limit memory allocated for the clients log */
static unsigned long client_log_limit = 524288;
/* Minimum and maximum fallback drift intervals */
static int fb_drift_min = 0;
static int fb_drift_max = 0;
/* IP addresses for binding the NTP socket to. UNSPEC family means INADDR_ANY
will be used */
static IPAddr bind_address4, bind_address6;
@@ -178,6 +207,11 @@ static IPAddr bind_cmd_address4, bind_cmd_address6;
* chronyds being started. */
static char *pidfile = "/var/run/chronyd.pid";
/* Temperature sensor, update interval and compensation coefficients */
static char *tempcomp_file = NULL;
static double tempcomp_interval;
static double tempcomp_T0, tempcomp_k0, tempcomp_k1, tempcomp_k2;
/* Boolean for whether the Linux HZ value has been overridden, and the
* new value. */
static int set_linux_hz = 0;
@@ -191,6 +225,9 @@ static double linux_freq_scale;
static int sched_priority = 0;
static int lock_memory = 0;
/* Name of a system timezone containing leap seconds occuring at midnight */
static char *leapsec_tz = NULL;
/* ================================================== */
typedef struct {
@@ -208,11 +245,14 @@ static const Command commands[] = {
{"driftfile", 9, parse_driftfile},
{"keyfile", 7, parse_keyfile},
{"rtcfile", 7, parse_rtcfile},
{"logbanner", 9, parse_logbanner},
{"logdir", 6, parse_logdir},
{"log", 3, parse_log},
{"dumponexit", 10, parse_dumponexit},
{"dumpdir", 7, parse_dumpdir},
{"maxupdateskew", 13, parse_maxupdateskew},
{"maxclockerror", 13, parse_maxclockerror},
{"corrtimeratio", 13, parse_corrtimeratio},
{"commandkey", 10, parse_commandkey},
{"initstepslew", 12, parse_initstepslew},
{"local", 5, parse_local},
@@ -223,9 +263,12 @@ static const Command commands[] = {
{"cmddeny", 7, parse_cmddeny},
{"cmdport", 7, parse_cmdport},
{"rtconutc", 8, parse_rtconutc},
{"rtcsync", 7, parse_rtcsync},
{"noclientlog", 11, parse_noclientlog},
{"clientloglimit", 14, parse_clientloglimit},
{"fallbackdrift", 13, parse_fallbackdrift},
{"makestep", 8, parse_makestep},
{"maxchange", 9, parse_maxchange},
{"logchange", 9, parse_logchange},
{"mailonchange", 12, parse_mailonchange},
{"bindaddress", 11, parse_bindaddress},
@@ -233,6 +276,11 @@ static const Command commands[] = {
{"rtcdevice", 9, parse_rtcdevice},
{"pidfile", 7, parse_pidfile},
{"broadcast", 9, parse_broadcast},
{"tempcomp", 8, parse_tempcomp},
{"reselectdist", 12, parse_reselectdist},
{"stratumweight", 13, parse_stratumweight},
{"include", 7, parse_include},
{"leapsectz", 9, parse_leapsectz},
{"linux_hz", 8, parse_linux_hz},
{"linux_freq_scale", 16, parse_linux_freq_scale},
{"sched_priority", 14, parse_sched_priority},
@@ -246,15 +294,9 @@ static int line_number;
/* ================================================== */
typedef enum {
SERVER, PEER
} NTP_Source_Type;
typedef struct {
NTP_Source_Type type;
IPAddr ip_addr;
unsigned short port;
SourceParameters params;
CPS_NTP_Source params;
} NTP_Source;
#define MAX_NTP_SOURCES 64
@@ -291,6 +333,7 @@ CNF_ReadFile(const char *filename)
char line[2048];
char *p;
int i, ok;
int prev_line_number;
if (filename == NULL) {
filename = DEFAULT_CONF_FILE;
@@ -301,6 +344,9 @@ CNF_ReadFile(const char *filename)
LOG(LOGS_ERR, LOGF_Configure, "Could not open configuration file [%s]", filename);
} else {
/* Save current line number in case this is an included file */
prev_line_number = line_number;
line_number = 0;
/* Success */
@@ -335,6 +381,8 @@ CNF_ReadFile(const char *filename)
}
line_number = prev_line_number;
fclose(in);
}
@@ -345,23 +393,14 @@ CNF_ReadFile(const char *filename)
static void
parse_source(const char *line, NTP_Source_Type type)
{
int i;
NTP_Source s;
CPS_Status status;
CPS_NTP_Source params;
s.type = type;
status = CPS_ParseNTPSourceAdd(line, &params);
ntp_sources[n_ntp_sources].type = type;
status = CPS_ParseNTPSourceAdd(line, &ntp_sources[n_ntp_sources].params);
switch (status) {
case CPS_Success:
s.port = params.port;
s.ip_addr = params.ip_addr;
s.params = params.params;
i = n_ntp_sources++;
ntp_sources[i] = s;
n_ntp_sources++;
break;
case CPS_BadOption:
LOG(LOGS_WARN, LOGF_Configure, "Unrecognized subcommand at line %d", line_number);
@@ -381,6 +420,9 @@ parse_source(const char *line, NTP_Source_Type type)
case CPS_BadPresend:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable presend value at line %d", line_number);
break;
case CPS_BadMaxdelaydevratio:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable max delay dev ratio value at line %d", line_number);
break;
case CPS_BadMaxdelayratio:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable max delay ratio value at line %d", line_number);
break;
@@ -390,6 +432,12 @@ parse_source(const char *line, NTP_Source_Type type)
case CPS_BadKey:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable key value at line %d", line_number);
break;
case CPS_BadMinstratum:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable minstratum value at line %d", line_number);
break;
case CPS_BadPolltarget:
LOG(LOGS_WARN, LOGF_Configure, "Unreadable polltarget value at line %d", line_number);
break;
}
return;
@@ -419,7 +467,7 @@ parse_lockall(const char *line)
static void
parse_server(const char *line)
{
parse_source(line, SERVER);
parse_source(line, NTP_SERVER);
}
/* ================================================== */
@@ -427,7 +475,7 @@ parse_server(const char *line)
static void
parse_peer(const char *line)
{
parse_source(line, PEER);
parse_source(line, NTP_PEER);
}
/* ================================================== */
@@ -436,11 +484,12 @@ static void
parse_refclock(const char *line)
{
int i, n, poll, dpoll, filter_length, pps_rate;
unsigned long ref_id, lock_ref_id;
double offset, delay;
uint32_t ref_id, lock_ref_id;
double offset, delay, precision;
const char *tmp;
char name[5], cmd[10 + 1], *param;
char cmd[10 + 1], *name, *param;
unsigned char ref[5];
SRC_SelectOption sel_option;
i = n_refclock_sources;
if (i >= MAX_RCL_SOURCES)
@@ -448,18 +497,29 @@ parse_refclock(const char *line)
poll = 4;
dpoll = 0;
filter_length = 15;
filter_length = 64;
pps_rate = 0;
offset = 0.0;
delay = 1e-9;
precision = 0.0;
ref_id = 0;
lock_ref_id = 0;
sel_option = SRC_SelectNormal;
if (sscanf(line, "%4s%n", name, &n) != 1) {
while (isspace(line[0]))
line++;
tmp = line;
while (line[0] != '\0' && !isspace(line[0]))
line++;
if (line == tmp) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name at line %d", line_number);
return;
}
line += n;
name = MallocArray(char, 1 + line - tmp);
strncpy(name, tmp, line - tmp);
name[line - tmp] = '\0';
while (isspace(line[0]))
line++;
@@ -469,6 +529,7 @@ parse_refclock(const char *line)
if (line == tmp) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock parameter at line %d", line_number);
Free(name);
return;
}
@@ -507,6 +568,15 @@ parse_refclock(const char *line)
} else if (!strncasecmp(cmd, "delay", 5)) {
if (sscanf(line, "%lf%n", &delay, &n) != 1)
break;
} else if (!strncasecmp(cmd, "precision", 9)) {
if (sscanf(line, "%lf%n", &precision, &n) != 1)
break;
} else if (!strncasecmp(cmd, "noselect", 8)) {
n = 0;
sel_option = SRC_SelectNoselect;
} else if (!strncasecmp(cmd, "prefer", 6)) {
n = 0;
sel_option = SRC_SelectPrefer;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Unknown refclock parameter %s at line %d", cmd, line_number);
break;
@@ -514,7 +584,7 @@ parse_refclock(const char *line)
line += n;
}
strncpy(refclock_sources[i].driver_name, name, 4);
refclock_sources[i].driver_name = name;
refclock_sources[i].driver_parameter = param;
refclock_sources[i].driver_poll = dpoll;
refclock_sources[i].poll = poll;
@@ -522,6 +592,8 @@ parse_refclock(const char *line)
refclock_sources[i].pps_rate = pps_rate;
refclock_sources[i].offset = offset;
refclock_sources[i].delay = delay;
refclock_sources[i].precision = precision;
refclock_sources[i].sel_option = sel_option;
refclock_sources[i].ref_id = ref_id;
refclock_sources[i].lock_ref_id = lock_ref_id;
@@ -566,6 +638,46 @@ parse_maxupdateskew(const char *line)
/* ================================================== */
static void
parse_maxclockerror(const char *line)
{
if (sscanf(line, "%lf", &max_clock_error) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read max clock error at line %d in file", line_number);
}
}
/* ================================================== */
static void
parse_corrtimeratio(const char *line)
{
if (sscanf(line, "%lf", &correction_time_ratio) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read correction time ratio at line %d", line_number);
}
}
/* ================================================== */
static void
parse_reselectdist(const char *line)
{
if (sscanf(line, "%lf", &reselect_distance) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read reselect distance at line %d in file", line_number);
}
}
/* ================================================== */
static void
parse_stratumweight(const char *line)
{
if (sscanf(line, "%lf", &stratum_weight) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read stratum weight at line %d in file", line_number);
}
}
/* ================================================== */
static void
parse_driftfile(const char *line)
{
@@ -621,6 +733,16 @@ parse_rtcdevice(const char *line)
/* ================================================== */
static void
parse_logbanner(const char *line)
{
if (sscanf(line, "%d", &log_banner) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read logbanner number at line %d in file", line_number);
}
}
/* ================================================== */
static void
parse_logdir(const char *line)
{
@@ -668,6 +790,9 @@ parse_log(const char *line)
} else if (!strncmp(line, "refclocks", 9)) {
do_log_refclocks = 1;
line += 9;
} else if (!strncmp(line, "tempcomp", 8)) {
do_log_tempcomp = 1;
line += 8;
} else {
break;
}
@@ -736,7 +861,7 @@ parse_initstepslew(const char *line)
}
while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
if (DNS_Name2IPAddress(hostname, &ip_addr) == DNS_Success) {
init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs;
}
@@ -777,6 +902,14 @@ parse_rtconutc(const char *line)
/* ================================================== */
static void
parse_rtcsync(const char *line)
{
rtc_sync = 1;
}
/* ================================================== */
static void
parse_noclientlog(const char *line)
{
@@ -800,6 +933,16 @@ parse_clientloglimit(const char *line)
/* ================================================== */
static void
parse_fallbackdrift(const char *line)
{
if (sscanf(line, "%d %d", &fb_drift_min, &fb_drift_max) != 2) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read fallback drift intervals at line %d", line_number);
}
}
/* ================================================== */
static void
parse_makestep(const char *line)
{
@@ -813,6 +956,19 @@ parse_makestep(const char *line)
/* ================================================== */
static void
parse_maxchange(const char *line)
{
if (sscanf(line, "%lf %d %d", &max_offset, &max_offset_delay, &max_offset_ignore) != 3) {
max_offset_delay = -1;
LOG(LOGS_WARN, LOGF_Configure,
"Could not read offset, check delay or ignore limit for maximum change at line %d\n",
line_number);
}
}
/* ================================================== */
static void
parse_logchange(const char *line)
{
@@ -934,7 +1090,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
}
} else {
if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
if (DNS_Name2IPAddress(p, &ip_addr) == DNS_Success) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
@@ -1093,6 +1249,54 @@ parse_broadcast(const char *line)
/* ================================================== */
static void
parse_tempcomp(const char *line)
{
const char *tmp;
while (isspace(line[0]))
line++;
tmp = line;
while (line[0] != '\0' && !isspace(line[0]))
line++;
if (line == tmp) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read tempcomp filename at line %d", line_number);
return;
}
if (sscanf(line, "%lf %lf %lf %lf %lf", &tempcomp_interval, &tempcomp_T0, &tempcomp_k0, &tempcomp_k1, &tempcomp_k2) != 5) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read tempcomp interval or coefficients at line %d", line_number);
return;
}
tempcomp_file = MallocArray(char, 1 + line - tmp);
strncpy(tempcomp_file, tmp, line - tmp);
tempcomp_file[line - tmp] = '\0';
}
/* ================================================== */
static void
parse_include(const char *line)
{
while (isspace(line[0]))
line++;
CNF_ReadFile(line);
}
/* ================================================== */
static void
parse_leapsectz(const char *line)
{
/* This must allocate enough space! */
leapsec_tz = MallocArray(char, 1 + strlen(line));
sscanf(line, "%s", leapsec_tz);
}
/* ================================================== */
static void
parse_linux_hz(const char *line)
{
@@ -1131,25 +1335,14 @@ CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything)
void
CNF_AddSources(void) {
NTP_Remote_Address server;
int i;
for (i=0; i<n_ntp_sources; i++) {
server.ip_addr = ntp_sources[i].ip_addr;
memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
server.port = ntp_sources[i].port;
switch (ntp_sources[i].type) {
case SERVER:
NSR_AddServer(&server, &ntp_sources[i].params);
break;
case PEER:
NSR_AddPeer(&server, &ntp_sources[i].params);
break;
NSR_AddUnresolvedSource(ntp_sources[i].params.name, ntp_sources[i].params.port,
ntp_sources[i].type, &ntp_sources[i].params.params);
}
}
NSR_ResolveSources();
return;
@@ -1205,6 +1398,14 @@ CNF_GetDriftFile(void)
/* ================================================== */
int
CNF_GetLogBanner(void)
{
return log_banner;
}
/* ================================================== */
char *
CNF_GetLogDir(void)
{
@@ -1252,6 +1453,7 @@ CNF_GetLogRtc(void)
}
/* ================================================== */
int
CNF_GetLogRefclocks(void)
{
@@ -1260,6 +1462,14 @@ CNF_GetLogRefclocks(void)
/* ================================================== */
int
CNF_GetLogTempComp(void)
{
return do_log_tempcomp;
}
/* ================================================== */
char *
CNF_GetKeysFile(void)
{
@@ -1308,6 +1518,38 @@ CNF_GetMaxUpdateSkew(void)
/* ================================================== */
double
CNF_GetMaxClockError(void)
{
return max_clock_error;
}
/* ================================================== */
double
CNF_GetCorrectionTimeRatio(void)
{
return correction_time_ratio;
}
/* ================================================== */
double
CNF_GetReselectDistance(void)
{
return reselect_distance;
}
/* ================================================== */
double
CNF_GetStratumWeight(void)
{
return stratum_weight;
}
/* ================================================== */
int
CNF_GetManualEnabled(void)
{
@@ -1344,6 +1586,14 @@ CNF_GetRTCOnUTC(void)
/* ================================================== */
int
CNF_GetRTCSync(void)
{
return rtc_sync;
}
/* ================================================== */
void
CNF_GetMakeStep(int *limit, double *threshold)
{
@@ -1353,6 +1603,16 @@ CNF_GetMakeStep(int *limit, double *threshold)
/* ================================================== */
void
CNF_GetMaxChange(int *delay, int *ignore, double *offset)
{
*delay = max_offset_delay;
*ignore = max_offset_ignore;
*offset = max_offset;
}
/* ================================================== */
void
CNF_GetLogChange(int *enabled, double *threshold)
{
@@ -1419,6 +1679,15 @@ CNF_GetClientLogLimit(void)
/* ================================================== */
void
CNF_GetFallbackDrifts(int *min, int *max)
{
*min = fb_drift_min;
*max = fb_drift_max;
}
/* ================================================== */
void
CNF_GetBindAddress(int family, IPAddr *addr)
{
@@ -1453,6 +1722,14 @@ CNF_GetPidFile(void)
/* ================================================== */
char *
CNF_GetLeapSecTimezone(void)
{
return leapsec_tz;
}
/* ================================================== */
void
CNF_GetLinuxHz(int *set, int *hz)
{
@@ -1484,3 +1761,17 @@ CNF_GetLockMemory(void)
{
return lock_memory;
}
/* ================================================== */
void
CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2)
{
*file = tempcomp_file;
*interval = tempcomp_interval;
*T0 = tempcomp_T0;
*k0 = tempcomp_k0;
*k1 = tempcomp_k1;
*k2 = tempcomp_k2;
}

18
conf.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/conf.h,v 1.25 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -48,11 +44,13 @@ extern unsigned short CNF_GetNTPPort(void);
extern char *CNF_GetDriftFile(void);
extern char *CNF_GetLogDir(void);
extern char *CNF_GetDumpDir(void);
extern int CNF_GetLogBanner(void);
extern int CNF_GetLogMeasurements(void);
extern int CNF_GetLogStatistics(void);
extern int CNF_GetLogTracking(void);
extern int CNF_GetLogRtc(void);
extern int CNF_GetLogRefclocks(void);
extern int CNF_GetLogTempComp(void);
extern char *CNF_GetKeysFile(void);
extern char *CNF_GetRtcFile(void);
extern unsigned long CNF_GetCommandKey(void);
@@ -60,19 +58,29 @@ extern int CNF_GetDumpOnExit(void);
extern int CNF_GetManualEnabled(void);
extern int CNF_GetCommandPort(void);
extern int CNF_GetRTCOnUTC(void);
extern int CNF_GetRTCSync(void);
extern void CNF_GetMakeStep(int *limit, double *threshold);
extern void CNF_GetMaxChange(int *delay, int *ignore, double *offset);
extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void);
extern unsigned long CNF_GetClientLogLimit(void);
extern void CNF_GetFallbackDrifts(int *min, int *max);
extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void);
extern char *CNF_GetLeapSecTimezone(void);
extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
/* Value returned in ppm, as read from file */
extern double CNF_GetMaxUpdateSkew(void);
extern double CNF_GetMaxClockError(void);
extern double CNF_GetCorrectionTimeRatio(void);
extern double CNF_GetReselectDistance(void);
extern double CNF_GetStratumWeight(void);
extern int CNF_AllowLocalReference(int *stratum);
extern void CNF_SetupAccessRestrictions(void);
@@ -80,4 +88,6 @@ extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void);
extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2);
#endif /* GOT_CONF_H */

190
configure vendored
View File

@@ -4,9 +4,12 @@
# chronyd/chronyc - Programs for keeping computer clocks accurate.
#
# Copyright (C) Richard P. Curnow 1997-2003
# Copyright (C) Miroslav Lichvar 2009, 2012
#
# =======================================================================
rm -f config.h config.log
# This configure script determines the operating system type and version
if [ "x${CC}" = "x" ]; then
@@ -24,11 +27,11 @@ fi
MYCPPFLAGS="${CPPFLAGS}"
if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
CCWARNFLAGS=""
MYCFLAGS="${MYCFLAGS} -Wmissing-prototypes -Wall"
fi
MYLDFLAGS="${LDFLAGS}"
# ======================================================================
# FUNCTIONS
@@ -40,7 +43,7 @@ test_code () {
ldflags=$4
code=$5
printf "Checking for $name : "
echo -n "Checking for $name : "
(
for h in $headers; do
@@ -51,22 +54,29 @@ test_code () {
echo "return 0; }"
) > docheck.c
${MYCC} ${MYCFLAGS} ${MYCPPFLAGS} $cflags -o docheck docheck.c $ldflags >/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 ]
then
printf "Yes\n"
echo "Yes"
result=0
else
printf "No\n"
echo "No"
result=1
fi
rm -f docheck.c docheck
echo >> config.log
return $result
}
#}}}
#{{{ usage
usage () {
cat <<EOF;
cat <<EOF
\`configure' configures tdl to adapt to many kinds of systems.
Usage: ./configure [OPTION]...
@@ -95,10 +105,14 @@ For better control, use the options below.
--readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is
--without-nss Don't use NSS even if it is available
--without-tomcrypt Don't use libtomcrypt even if it is available
--disable-ipv6 Disable IPv6 support
--disable-pps Disable PPS API support
--disable-rtc Don't include RTC even on Linux
--disable-linuxcaps Disable Linux capabilities support
--disable-forcednsretry Don't retry on permanent DNS error
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
Fine tuning of the installation directories:
--sysconfdir=DIR chrony.conf location [/etc]
@@ -129,6 +143,15 @@ EOF
}
#}}}
#{{{
add_def () {
if [ "x$2" = "x" ]; then
echo "#define $1 1" >> config.h
else
echo "#define $1 $2" >> config.h
fi
}
#}}}
# ======================================================================
@@ -148,7 +171,10 @@ SYSDEFS=""
feat_readline=1
try_readline=1
try_editline=1
try_nss=1
try_tomcrypt=1
feat_rtc=1
try_rtc=0
feat_linuxcaps=1
try_linuxcaps=0
readline_lib=""
@@ -158,12 +184,14 @@ feat_ipv6=1
feat_pps=1
try_setsched=0
try_lockmem=0
feat_forcednsretry=1
mail_program="/usr/lib/sendmail"
for option
do
case "$option" in
--trace )
EXTRA_DEFS="-DTRACEON"
add_def TRACEON
;;
--disable-readline )
feat_readline=0
@@ -222,6 +250,18 @@ do
--disable-linuxcaps)
feat_linuxcaps=0
;;
--disable-forcednsretry)
feat_forcednsretry=0
;;
--with-sendmail=* )
mail_program=`echo $option | sed -e 's/^.*=//;'`
;;
--without-nss )
try_nss=0
;;
--without-tomcrypt )
try_tomcrypt=0
;;
--host-system=* )
OPERATINGSYSTEM=`echo $option | sed -e 's/^.*=//;'`
;;
@@ -248,17 +288,17 @@ case $SYSTEM in
4.* )
EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm"
SYSDEFS="-DSUNOS"
add_def SUNOS
echo "Configuring for SunOS (" $SYSTEM "version" $VERSION ")"
;;
5.* )
EXTRA_OBJECTS="sys_solaris.o"
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
EXTRA_CLI_LIBS="-lsocket -lnsl"
SYSDEFS="-DSOLARIS"
add_def SOLARIS
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
if [ $VERSION = "5.3" ]; then
SYSDEFS="$SYSDEFS -DHAS_NO_BZERO"
add_def HAS_NO_BZERO
echo "Using memset() instead of bzero()"
fi
;;
@@ -266,19 +306,16 @@ case $SYSTEM in
;;
Linux* )
EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o"
if [ $feat_rtc -eq 1 ] ; then
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
EXTRA_DEFS="$EXTRA_DEFS -DFEAT_RTC=1"
fi
try_linuxcaps=1
try_rtc=1
try_setsched=1
try_lockmem=1
SYSDEFS="-DLINUX"
add_def LINUX
echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then
echo "Enabling -mieee"
# FIXME: Should really test for GCC
SYSDEFS="$SYSDEFS -mieee -DALPHA"
MYCFLAGS="$MYCFLAGS -mieee"
fi
;;
@@ -287,7 +324,7 @@ case $SYSTEM in
# be supported with the SunOS 4.x driver files.
EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm"
SYSDEFS="-DSUNOS"
add_def SUNOS
echo "Configuring for $SYSTEM (using SunOS driver)"
;;
NetBSD-* )
@@ -302,13 +339,13 @@ case $SYSTEM in
EXTRA_OBJECTS="sys_solaris.o"
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
EXTRA_CLI_LIBS="-lsocket -lnsl"
SYSDEFS="-DSOLARIS"
add_def SOLARIS
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
;;
CYGWIN32_NT-i[3456]86 )
EXTRA_OBJECTS="sys_winnt.o"
EXTRA_LIBS=""
SYSDEFS="-DWINNT"
add_def WINNT
echo "Configuring for Windows NT (Cygwin32)"
;;
* )
@@ -324,17 +361,17 @@ else
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
LIBS="-lm"
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
fi
fi
if test_code '<stdint.h>' 'stdint.h' '' '' ''; then
SYSDEFS="${SYSDEFS} -DHAS_STDINT_H"
add_def HAS_STDINT_H
fi
if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then
SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H"
add_def HAS_INTTYPES_H
fi
if [ $feat_ipv6 = "1" ] && \
@@ -344,17 +381,42 @@ if [ $feat_ipv6 = "1" ] && \
n.sin6_addr = in6addr_any;
return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));'
then
SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
add_def HAVE_IPV6
if test_code 'in6_pktinfo' 'sys/socket.h netinet/in.h' '' '' '
return sizeof(struct in6_pktinfo);'
then
add_def HAVE_IN6_PKTINFO
else
if test_code 'in6_pktinfo with _GNU_SOURCE' 'sys/socket.h netinet/in.h' \
'-D_GNU_SOURCE' '' 'return sizeof(struct in6_pktinfo);'
then
add_def _GNU_SOURCE
add_def HAVE_IN6_PKTINFO
fi
fi
fi
if [ $feat_pps = "1" ] && \
test_code 'PPS API' 'timepps.h' '' '' '
timepps_h=""
if [ $feat_pps = "1" ]; then
if test_code '<sys/timepps.h>' 'sys/timepps.h' '' '' ''; then
timepps_h="sys/timepps.h"
add_def HAVE_SYS_TIMEPPS_H
else
if test_code '<timepps.h>' 'timepps.h' '' '' ''; then
timepps_h="timepps.h"
add_def HAVE_TIMEPPS_H
fi
fi
fi
if [ "x$timepps_h" != "x" ] && \
test_code 'PPSAPI' "string.h $timepps_h" '' '' '
pps_handle_t h;
pps_info_t i;
struct timespec ts;
return time_pps_fetch(&h, PPS_TSFMT_TSPEC, &i, &ts);'
return time_pps_fetch(h, PPS_TSFMT_TSPEC, &i, &ts);'
then
SYSDEFS="${SYSDEFS} -DHAVE_PPSAPI"
add_def HAVE_PPSAPI
fi
if [ $feat_linuxcaps = "1" ] && [ $try_linuxcaps = "1" ] && \
@@ -364,10 +426,18 @@ if [ $feat_linuxcaps = "1" ] && [ $try_linuxcaps = "1" ] && \
'' '-lcap' \
'prctl(PR_SET_KEEPCAPS, 1);cap_set_proc(cap_from_text("cap_sys_time=ep"));'
then
EXTRA_DEFS="${EXTRA_DEFS} -DFEAT_LINUXCAPS=1"
add_def FEAT_LINUXCAPS
EXTRA_LIBS="-lcap"
fi
if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \
test_code '<linux/rtc.h>' 'sys/ioctl.h linux/rtc.h' '' '' \
'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);'
then
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
add_def FEAT_RTC
fi
if [ $try_setsched = "1" ] && \
test_code \
'sched_setscheduler()' \
@@ -376,7 +446,7 @@ if [ $try_setsched = "1" ] && \
sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sched);'
then
SYSDEFS="${SYSDEFS} -DHAVE_SCHED_SETSCHEDULER"
add_def HAVE_SCHED_SETSCHEDULER
fi
if [ $try_lockmem = "1" ] && \
@@ -387,7 +457,12 @@ if [ $try_lockmem = "1" ] && \
setrlimit(RLIMIT_MEMLOCK, &rlim);
mlockall(MCL_CURRENT|MCL_FUTURE);'
then
SYSDEFS="${SYSDEFS} -DHAVE_MLOCKALL"
add_def HAVE_MLOCKALL
fi
if [ $feat_forcednsretry = "1" ]
then
add_def FORCE_DNSRETRY
fi
READLINE_COMPILE=""
@@ -398,7 +473,9 @@ if [ $feat_readline = "1" ]; then
"$readline_inc" "$readline_lib -ledit" \
'add_history(readline("prompt"));'
then
READLINE_COMPILE="-DFEAT_READLINE=1 -DUSE_EDITLINE=1 $readline_inc"
add_def FEAT_READLINE
add_def USE_EDITLINE
READLINE_COMPILE="$readline_inc"
READLINE_LINK="$readline_lib -ledit"
fi
fi
@@ -408,12 +485,40 @@ if [ $feat_readline = "1" ]; then
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
'add_history(readline("prompt"));'
then
READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
add_def FEAT_READLINE
READLINE_COMPILE="$readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
fi
fi
fi
HASH_OBJ="hash_intmd5.o"
HASH_COMPILE=""
HASH_LINK=""
if [ $try_nss = "1" ]; then
test_cflags="`pkg-config --cflags nss`"
test_link="`pkg-config --libs-only-L nss` -lfreebl3"
if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \
"$test_cflags" "$test_link" \
'NSSLOWHASH_Begin(NSSLOWHASH_NewContext(NSSLOW_Init(), HASH_AlgSHA512));'
then
HASH_OBJ="hash_nss.o"
HASH_COMPILE="$test_cflags"
HASH_LINK="$test_link"
fi
fi
if [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]; then
if test_code 'tomcrypt' 'tomcrypt.h' '-I/usr/include/tomcrypt' '-ltomcrypt' \
'hash_memory_multi(find_hash("md5"), NULL, NULL, NULL, 0, NULL, 0);'
then
HASH_OBJ="hash_tomcrypt.o"
HASH_COMPILE="-I/usr/include/tomcrypt"
HASH_LINK="-ltomcrypt"
fi
fi
SYSCONFDIR=/etc
if [ "x$SETSYSCONFDIR" != "x" ]; then
SYSCONFDIR=$SETSYSCONFDIR
@@ -459,19 +564,28 @@ if [ "x$SETDOCDIR" != "x" ]; then
DOCDIR=$SETDOCDIR
fi
add_def DEFAULT_CONF_DIR "\"$SYSCONFDIR\""
add_def MAIL_PROGRAM "\"$mail_program\""
if [ -f version.txt ]; then
add_def CHRONY_VERSION "\"`cat version.txt`\""
else
add_def CHRONY_VERSION "\"DEVELOPMENT\""
fi
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@CC@%${MYCC}%;\
s%@CFLAGS@%${MYCFLAGS}%;\
s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\
s%@CPPFLAGS@%${CPPFLAGS}%;\
s%@LIBS@%${LIBS}%;\
s%@LDFLAGS@%${LDFLAGS}%;\
s%@LDFLAGS@%${MYLDFLAGS}%;\
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
s%@SYSDEFS@%${SYSDEFS}%;\
s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
s%@READLINE_LINK@%${READLINE_LINK}%;\
s%@HASH_OBJ@%${HASH_OBJ}%;\
s%@HASH_LINK@%${HASH_LINK}%;\
s%@HASH_COMPILE@%${HASH_COMPILE}%;\
s%@SYSCONFDIR@%${SYSCONFDIR}%;\
s%@BINDIR@%${BINDIR}%;\
s%@SBINDIR@%${SBINDIR}%;\

View File

@@ -0,0 +1,39 @@
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst
# Ignore stratum in source selection.
stratumweight 0
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
# Enable kernel RTC synchronization.
rtcsync
# In first three updates step the system clock instead of slew
# if the adjustment is larger than 100 seconds.
makestep 100 3
# Allow client access from local network.
#allow 192.168/16
# Serve time even if not synchronized to any NTP server.
#local stratum 10
keyfile /etc/chrony.keys
# Specify the key used as password for chronyc.
commandkey 1
# Disable logging of client accesses.
noclientlog
# Send a message to syslog if a clock adjustment is larger than 0.5 seconds.
logchange 0.5
logdir /var/log/chrony
#log measurements statistics tracking

View File

@@ -1,5 +1,4 @@
#######################################################################
# $Header: /cvs/src/chrony/examples/chrony.keys.example,v 1.1 2002/01/31 00:00:08 richard Exp $
#
# 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,

41
hash.h Normal file
View File

@@ -0,0 +1,41 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Header file for crypto hashing.
*/
#ifndef GOT_HASH_H
#define GOT_HASH_H
/* length of hash values produced by SHA512 */
#define MAX_HASH_LENGTH 64
extern int HSH_GetHashId(const char *name);
extern unsigned int HSH_Hash(int id,
const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len);
#endif

64
hash_intmd5.c Normal file
View File

@@ -0,0 +1,64 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Routines implementing crypto hashing using internal MD5 implementation.
*/
#include "config.h"
#include "sysincl.h"
#include "hash.h"
#include "memory.h"
#include "md5.c"
static MD5_CTX ctx;
int
HSH_GetHashId(const char *name)
{
/* only MD5 is supported */
if (strcmp(name, "MD5"))
return -1;
return 0;
}
unsigned int
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
if (out_len < 16)
return 0;
MD5Init(&ctx);
MD5Update(&ctx, in1, in1_len);
if (in2)
MD5Update(&ctx, in2, in2_len);
MD5Final(&ctx);
memcpy(out, ctx.digest, 16);
return 16;
}

89
hash_nss.c Normal file
View File

@@ -0,0 +1,89 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Routines implementing crypto hashing using NSSLOWHASH API of the NSS library.
*/
#include <nss.h>
#include <hasht.h>
#include <nsslowhash.h>
/* #include "config.h" */
#include "hash.h"
static NSSLOWInitContext *ictx;
struct hash {
HASH_HashType type;
const char *name;
NSSLOWHASHContext *context;
};
static struct hash hashes[] = {
{ HASH_AlgMD5, "MD5", NULL },
{ HASH_AlgSHA1, "SHA1", NULL },
{ HASH_AlgSHA256, "SHA256", NULL },
{ HASH_AlgSHA384, "SHA384", NULL },
{ HASH_AlgSHA512, "SHA512", NULL },
{ 0, NULL, NULL }
};
int
HSH_GetHashId(const char *name)
{
int i;
for (i = 0; hashes[i].name; i++) {
if (!strcmp(name, hashes[i].name))
break;
}
if (!hashes[i].name)
return -1; /* not found */
if (!ictx && !(ictx = NSSLOW_Init()))
return -1; /* couldn't init NSS */
if (!hashes[i].context &&
!(hashes[i].context = NSSLOWHASH_NewContext(ictx, hashes[i].type)))
return -1; /* couldn't init hash */
return i;
}
unsigned int
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
unsigned int ret;
NSSLOWHASH_Begin(hashes[id].context);
NSSLOWHASH_Update(hashes[id].context, in1, in1_len);
if (in2)
NSSLOWHASH_Update(hashes[id].context, in2, in2_len);
NSSLOWHASH_End(hashes[id].context, out, &ret, out_len);
return ret;
}

116
hash_tomcrypt.c Normal file
View File

@@ -0,0 +1,116 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Routines implementing crypto hashing using tomcrypt library.
*/
#include <tomcrypt.h>
#include "config.h"
#include "hash.h"
struct hash {
const char *name;
const char *int_name;
const struct ltc_hash_descriptor *desc;
};
static const struct hash hashes[] = {
{ "MD5", "md5", &md5_desc },
#ifdef LTC_RIPEMD128
{ "RMD128", "rmd128", &rmd128_desc },
#endif
#ifdef LTC_RIPEMD160
{ "RMD160", "rmd160", &rmd160_desc },
#endif
#ifdef LTC_RIPEMD256
{ "RMD256", "rmd256", &rmd256_desc },
#endif
#ifdef LTC_RIPEMD320
{ "RMD320", "rmd320", &rmd320_desc },
#endif
#ifdef LTC_SHA1
{ "SHA1", "sha1", &sha1_desc },
#endif
#ifdef LTC_SHA256
{ "SHA256", "sha256", &sha256_desc },
#endif
#ifdef LTC_SHA384
{ "SHA384", "sha384", &sha384_desc },
#endif
#ifdef LTC_SHA512
{ "SHA512", "sha512", &sha512_desc },
#endif
#ifdef LTC_TIGER
{ "TIGER", "tiger", &tiger_desc },
#endif
#ifdef LTC_WHIRLPOOL
{ "WHIRLPOOL", "whirlpool", &whirlpool_desc },
#endif
{ NULL, NULL, NULL }
};
int
HSH_GetHashId(const char *name)
{
int i, h;
for (i = 0; hashes[i].name; i++) {
if (!strcmp(name, hashes[i].name))
break;
}
if (!hashes[i].name)
return -1; /* not found */
h = find_hash(hashes[i].int_name);
if (h >= 0)
return h; /* already registered */
/* register and try again */
register_hash(hashes[i].desc);
return find_hash(hashes[i].int_name);
}
unsigned int
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
unsigned long len;
int r;
len = out_len;
if (in2)
r = hash_memory_multi(id, out, &len,
in1, (unsigned long)in1_len, in2, (unsigned long)in2_len, NULL, 0);
else
r = hash_memory(id, in1, in1_len, out, &len);
if (r != CRYPT_OK)
return 0;
return len;
}

View File

@@ -1,75 +0,0 @@
/* Taken from <asm-$foo/ioctl.h> in the Linux kernel sources.
* The ioctl.h file is pretty similar from one architecture to another.
* */
#ifndef IO_LINUX_H
#define IO_LINUX_H
/* Hmm. These constants vary a bit between systems. */
/* (__sh__ includes both sh and sh64) */
/* (__s390__ includes both s390 and s390x) */
#if defined(__i386__) || defined(__sh__) || defined(__arm__) || defined(__x86_64__) || defined(__s390__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 14
#define CHRONY_IOC_DIRBITS 2
#define CHRONY_IOC_NONE 0U
#define CHRONY_IOC_WRITE 1U
#define CHRONY_IOC_READ 2U
#elif defined(__alpha__) || defined(__sparc__) || defined(__ppc__) || defined(__ppc64__) || defined(__sparc64__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 13
#define CHRONY_IOC_DIRBITS 2
#define CHRONY_IOC_NONE 1U
#define CHRONY_IOC_READ 2U
#define CHRONY_IOC_WRITE 4U
#elif defined(__mips__) || defined(__mips32__) || defined(__powerpc__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 13
#define CHRONY_IOC_DIRBITS 3
#define CHRONY_IOC_NONE 1U
#define CHRONY_IOC_READ 2U
#define CHRONY_IOC_WRITE 4U
#else
#error "I don't know the values of the _IOC_* constants for your architecture"
#endif
#define CHRONY_IOC_NRMASK ((1 << CHRONY_IOC_NRBITS)-1)
#define CHRONY_IOC_TYPEMASK ((1 << CHRONY_IOC_TYPEBITS)-1)
#define CHRONY_IOC_SIZEMASK ((1 << CHRONY_IOC_SIZEBITS)-1)
#define CHRONY_IOC_DIRMASK ((1 << CHRONY_IOC_DIRBITS)-1)
#define CHRONY_IOC_NRSHIFT 0
#define CHRONY_IOC_TYPESHIFT (CHRONY_IOC_NRSHIFT+CHRONY_IOC_NRBITS)
#define CHRONY_IOC_SIZESHIFT (CHRONY_IOC_TYPESHIFT+CHRONY_IOC_TYPEBITS)
#define CHRONY_IOC_DIRSHIFT (CHRONY_IOC_SIZESHIFT+CHRONY_IOC_SIZEBITS)
#define CHRONY_IOC(dir,type,nr,size) \
(((dir) << CHRONY_IOC_DIRSHIFT) | \
((type) << CHRONY_IOC_TYPESHIFT) | \
((nr) << CHRONY_IOC_NRSHIFT) | \
((size) << CHRONY_IOC_SIZESHIFT))
/* used to create numbers */
#define CHRONY_IO(type,nr) CHRONY_IOC(CHRONY_IOC_NONE,(type),(nr),0)
#define CHRONY_IOR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ,(type),(nr),sizeof(size))
#define CHRONY_IOW(type,nr,size) CHRONY_IOC(CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
#define CHRONY_IOWR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ|CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
#define RTC_UIE_ON CHRONY_IO('p', 0x03) /* Update int. enable on */
#define RTC_UIE_OFF CHRONY_IO('p', 0x04) /* ... off */
#define RTC_RD_TIME CHRONY_IOR('p', 0x09, struct rtc_time) /* Read RTC time */
#define RTC_SET_TIME CHRONY_IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
/* From mc146818.h */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
#endif

186
keys.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/keys.c,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012
*
* 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
@@ -29,6 +26,8 @@
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,11 +35,17 @@
#include "keys.h"
#include "conf.h"
#include "memory.h"
#include "util.h"
#include "local.h"
#include "logging.h"
typedef struct {
unsigned long id;
char *val;
int len;
int hash_id;
int auth_delay;
} Key;
#define MAX_KEYS 256
@@ -49,7 +54,7 @@ static int n_keys;
static Key keys[MAX_KEYS];
static int command_key_valid;
static int command_key_pos;
static int command_key_id;
static int cache_valid;
static unsigned long cache_key_id;
static int cache_key_pos;
@@ -77,6 +82,37 @@ KEY_Finalise(void)
/* ================================================== */
static int
determine_hash_delay(int key_id)
{
NTP_Packet pkt;
struct timeval before, after;
unsigned long usecs, min_usecs=0;
int i;
for (i = 0; i < 10; i++) {
LCL_ReadRawTime(&before);
KEY_GenerateAuth(key_id, (unsigned char *)&pkt, NTP_NORMAL_PACKET_SIZE,
(unsigned char *)&pkt.auth_data, sizeof (pkt.auth_data));
LCL_ReadRawTime(&after);
usecs = (after.tv_sec - before.tv_sec) * 1000000 + (after.tv_usec - before.tv_usec);
if (i == 0 || usecs < min_usecs) {
min_usecs = usecs;
}
}
#if 0
LOG(LOGS_INFO, LOGF_Keys, "authentication delay for key %d: %d useconds", key_id, min_usecs);
#endif
/* Add on a bit extra to allow for copying, conversions etc */
return min_usecs + (min_usecs >> 4);
}
/* ================================================== */
/* Compare two keys */
static int
@@ -104,16 +140,16 @@ compare_keys_by_id(const void *a, const void *b)
void
KEY_Reload(void)
{
int i, len1;
int i, len1, fields;
char *key_file;
FILE *in;
unsigned long key_id;
char line[KEYLEN+1], keyval[KEYLEN+1];
char line[KEYLEN+1], buf1[KEYLEN+1], buf2[KEYLEN+1];
char *keyval, *hashname;
for (i=0; i<n_keys; i++) {
Free(keys[i].val);
}
n_keys = 0;
key_file = CNF_GetKeysFile();
@@ -129,12 +165,30 @@ KEY_Reload(void)
if (line[len1] == '\n') {
line[len1] = '\0';
}
fields = sscanf(line, "%lu%" SKEYLEN "s%" SKEYLEN "s", &key_id, buf1, buf2);
if (fields >= 2 && fields <= 3) {
if (fields == 3) {
hashname = buf1;
keyval = buf2;
} else {
hashname = "MD5";
keyval = buf1;
}
keys[n_keys].hash_id = HSH_GetHashId(hashname);
if (keys[n_keys].hash_id < 0) {
LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %d", key_id);
continue;
}
keys[n_keys].len = UTI_DecodePasswordFromText(keyval);
if (!keys[n_keys].len) {
LOG(LOGS_WARN, LOGF_Keys, "Could not decode password in key %d", key_id);
continue;
}
if (sscanf(line, "%lu%" SKEYLEN "s", &key_id, keyval) == 2) {
keys[n_keys].id = key_id;
keys[n_keys].len = strlen(keyval);
keys[n_keys].val = MallocArray(char, 1 + keys[n_keys].len);
strcpy(keys[n_keys].val, keyval);
keys[n_keys].val = MallocArray(char, keys[n_keys].len);
memcpy(keys[n_keys].val, keyval, keys[n_keys].len);
n_keys++;
}
}
@@ -145,12 +199,20 @@ KEY_Reload(void)
more careful! */
qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id);
/* Erase the passwords from stack */
memset(line, 0, sizeof (line));
memset(buf1, 0, sizeof (buf1));
memset(buf2, 0, sizeof (buf2));
}
}
command_key_valid = 0;
cache_valid = 0;
for (i=0; i<n_keys; i++) {
keys[i].auth_delay = determine_hash_delay(keys[i].id);
}
return;
}
@@ -174,30 +236,8 @@ lookup_key(unsigned long id)
/* ================================================== */
void
KEY_CommandKey(char **key, int *len)
{
unsigned long command_key_id;
if (!command_key_valid) {
command_key_id = CNF_GetCommandKey();
command_key_pos = lookup_key(command_key_id);
command_key_valid = 1;
}
if (command_key_pos >= 0) {
*key = keys[command_key_pos].val;
*len = keys[command_key_pos].len;
} else {
*key = "";
*len = 0;
}
}
/* ================================================== */
int
KEY_GetKey(unsigned long key_id, char **key, int *len)
static int
get_key_pos(unsigned long key_id)
{
if (!cache_valid || key_id != cache_key_id) {
cache_valid = 1;
@@ -205,15 +245,19 @@ KEY_GetKey(unsigned long key_id, char **key, int *len)
cache_key_id = key_id;
}
if (cache_key_pos >= 0) {
*key = keys[cache_key_pos].val;
*len = keys[cache_key_pos].len;
return 1;
} else {
*key = "";
*len = 0;
return 0;
return cache_key_pos;
}
/* ================================================== */
unsigned long
KEY_GetCommandKey(void)
{
if (!command_key_valid) {
command_key_id = CNF_GetCommandKey();
}
return command_key_id;
}
/* ================================================== */
@@ -241,3 +285,57 @@ KEY_KeyKnown(unsigned long key_id)
}
}
}
/* ================================================== */
int
KEY_GetAuthDelay(unsigned long key_id)
{
int key_pos;
key_pos = get_key_pos(key_id);
if (key_pos < 0) {
return 0;
}
return keys[key_pos].auth_delay;
}
/* ================================================== */
int
KEY_GenerateAuth(unsigned long key_id, const unsigned char *data, int data_len,
unsigned char *auth, int auth_len)
{
int key_pos;
key_pos = get_key_pos(key_id);
if (key_pos < 0) {
return 0;
}
return UTI_GenerateNTPAuth(keys[key_pos].hash_id,
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
data, data_len, auth, auth_len);
}
/* ================================================== */
int
KEY_CheckAuth(unsigned long key_id, const unsigned char *data, int data_len,
const unsigned char *auth, int auth_len)
{
int key_pos;
key_pos = get_key_pos(key_id);
if (key_pos < 0) {
return 0;
}
return UTI_CheckNTPAuth(keys[key_pos].hash_id,
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
data, data_len, auth, auth_len);
}

12
keys.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/keys.h,v 1.8 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -36,9 +32,15 @@ extern void KEY_Finalise(void);
extern void KEY_Reload(void);
extern void KEY_CommandKey(char **key, int *len);
extern unsigned long KEY_GetCommandKey(void);
extern int KEY_GetKey(unsigned long key_id, char **key, int *len);
extern int KEY_KeyKnown(unsigned long key_id);
extern int KEY_GetAuthDelay(unsigned long key_id);
extern int KEY_GenerateAuth(unsigned long key_id, const unsigned char *data,
int data_len, unsigned char *auth, int auth_len);
extern int KEY_CheckAuth(unsigned long key_id, const unsigned char *data,
int data_len, const unsigned char *auth, int auth_len);
#endif /* GOT_KEYS_H */

216
local.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/local.c,v 1.21 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011
*
* 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
@@ -31,9 +28,12 @@
They interface with the system specific driver files in sys_*.c
*/
#include "config.h"
#include <assert.h>
#include <stddef.h>
#include "conf.h"
#include "local.h"
#include "localp.h"
#include "memory.h"
@@ -45,6 +45,9 @@
/* Variable to store the current frequency, in ppm */
static double current_freq_ppm;
/* Temperature compensation, in ppm */
static double temp_comp_ppm;
/* ================================================== */
/* Store the system dependent drivers */
@@ -88,6 +91,8 @@ static DispersionNotifyListEntry dispersion_notify_list;
static int precision_log;
static double precision_quantum;
static double max_clock_error;
/* ================================================== */
/* Define the number of increments of the system clock that we want
@@ -100,17 +105,15 @@ static double precision_quantum;
static void
calculate_sys_precision(void)
{
struct timeval tv, old_tv, first_tv;
struct timezone tz;
struct timeval tv, old_tv;
int dusec, best_dusec;
int iters;
gettimeofday(&old_tv, &tz);
first_tv = old_tv;
gettimeofday(&old_tv, NULL);
best_dusec = 1000000; /* Assume we must be better than a second */
iters = 0;
do {
gettimeofday(&tv, &tz);
gettimeofday(&tv, NULL);
dusec = 1000000*(tv.tv_sec - old_tv.tv_sec) + (tv.tv_usec - old_tv.tv_usec);
old_tv = tv;
if (dusec > 0) {
@@ -120,17 +123,16 @@ calculate_sys_precision(void)
iters++;
}
} while (iters < NITERS);
if (!(best_dusec > 0)) {
CROAK("best_dusec should be positive");
}
assert(best_dusec > 0);
precision_quantum = best_dusec * 1.0e-6;
precision_log = 0;
while (best_dusec < 500000) {
precision_log--;
best_dusec *= 2;
}
precision_quantum = 1.0 / (double)(1<<(-precision_log));
return;
}
@@ -153,8 +155,11 @@ LCL_Initialise(void)
/* This ought to be set from the system driver layer */
current_freq_ppm = 0.0;
temp_comp_ppm = 0.0;
calculate_sys_precision();
max_clock_error = CNF_GetMaxClockError() * 1e-6;
}
/* ================================================== */
@@ -185,6 +190,14 @@ LCL_GetSysPrecisionAsQuantum(void)
/* ================================================== */
double
LCL_GetMaxClockError(void)
{
return max_clock_error;
}
/* ================================================== */
void
LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
{
@@ -193,7 +206,7 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
/* Check that the handler is not already registered */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
if (!(ptr->handler != handler || ptr->anything != anything)) {
CROAK("a handler is already registered");
assert(0);
}
}
@@ -231,9 +244,7 @@ void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *
}
}
if (!ok) {
CROAK("did not find a matching handler");
}
assert(ok);
/* Unlink entry from the list */
ptr->next->prev = ptr->prev;
@@ -254,7 +265,7 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
/* Check that the handler is not already registered */
for (ptr = dispersion_notify_list.next; ptr != &dispersion_notify_list; ptr = ptr->next) {
if (!(ptr->handler != handler || ptr->anything != anything)) {
CROAK("a handler is already registered");
assert(0);
}
}
@@ -292,9 +303,7 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
}
}
if (!ok) {
CROAK("no matching handler found");
}
assert(ok);
/* Unlink entry from the list */
ptr->next->prev = ptr->prev;
@@ -312,13 +321,9 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
void
LCL_ReadRawTime(struct timeval *result)
{
struct timezone tz;
if (!(gettimeofday(result, &tz) >= 0)) {
CROAK("Could not get time of day");
if (gettimeofday(result, NULL) < 0) {
LOG_FATAL(LOGF_Local, "gettimeofday() failed");
}
return;
}
/* ================================================== */
@@ -327,39 +332,47 @@ void
LCL_ReadCookedTime(struct timeval *result, double *err)
{
struct timeval raw;
double correction;
LCL_ReadRawTime(&raw);
/* For now, cheat and set the error to zero in all cases.
*/
*err = 0.0;
/* Call system specific driver to get correction */
(*drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, result);
return;
LCL_CookTime(&raw, result, err);
}
/* ================================================== */
double
LCL_GetOffsetCorrection(struct timeval *raw)
void
LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err)
{
double correction;
(*drv_offset_convert)(raw, &correction);
return correction;
LCL_GetOffsetCorrection(raw, &correction, err);
UTI_AddDoubleToTimeval(raw, correction, cooked);
}
/* ================================================== */
/* This is just a simple passthrough of the system specific routine */
void
LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err)
{
/* Call system specific driver to get correction */
(*drv_offset_convert)(raw, correction, err);
}
/* ================================================== */
/* Return current frequency */
double
LCL_ReadAbsoluteFrequency(void)
{
return (*drv_read_freq)();
double freq;
freq = current_freq_ppm;
/* Undo temperature compensation */
if (temp_comp_ppm != 0.0) {
freq = (freq + temp_comp_ppm) / (1.0 - 1.0e-6 * temp_comp_ppm);
}
return freq;
}
/* ================================================== */
@@ -371,22 +384,25 @@ LCL_SetAbsoluteFrequency(double afreq_ppm)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
double correction;
double dfreq;
/* Apply temperature compensation */
if (temp_comp_ppm != 0.0) {
afreq_ppm = afreq_ppm * (1.0 - 1.0e-6 * temp_comp_ppm) - temp_comp_ppm;
}
/* Call the system-specific driver for setting the frequency */
(*drv_set_freq)(afreq_ppm);
afreq_ppm = (*drv_set_freq)(afreq_ppm);
dfreq = 1.0e-6 * (afreq_ppm - current_freq_ppm) / (1.0 - 1.0e-6 * current_freq_ppm);
dfreq = (afreq_ppm - current_freq_ppm) / (1.0e6 + current_freq_ppm);
LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
LCL_CookTime(&raw, &cooked, NULL);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, afreq_ppm, 0.0, 0, ptr->anything);
(ptr->handler)(&raw, &cooked, dfreq, 0.0, 0, ptr->anything);
}
current_freq_ppm = afreq_ppm;
@@ -400,25 +416,26 @@ LCL_AccumulateDeltaFrequency(double dfreq)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
double correction;
double old_freq_ppm;
old_freq_ppm = current_freq_ppm;
/* Work out new absolute frequency. Note that absolute frequencies
are handled in units of ppm, whereas the 'dfreq' argument is in
terms of the gradient of the (offset) v (local time) function. */
current_freq_ppm = (1.0 - dfreq) * current_freq_ppm +
(1.0e6 * dfreq);
current_freq_ppm = (1.0 + dfreq) * current_freq_ppm + 1.0e6 * dfreq;
/* Call the system-specific driver for setting the frequency */
(*drv_set_freq)(current_freq_ppm);
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm);
LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
LCL_CookTime(&raw, &cooked, NULL);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, 0.0, 0, ptr->anything);
(ptr->handler)(&raw, &cooked, dfreq, 0.0, 0, ptr->anything);
}
}
@@ -426,24 +443,22 @@ LCL_AccumulateDeltaFrequency(double dfreq)
/* ================================================== */
void
LCL_AccumulateOffset(double offset)
LCL_AccumulateOffset(double offset, double corr_rate)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
double correction;
/* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */
LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
LCL_CookTime(&raw, &cooked, NULL);
(*drv_accrue_offset)(offset);
(*drv_accrue_offset)(offset, corr_rate);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 0, ptr->anything);
(ptr->handler)(&raw, &cooked, 0.0, offset, 0, ptr->anything);
}
}
@@ -455,20 +470,18 @@ LCL_ApplyStepOffset(double offset)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
double correction;
/* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */
LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
LCL_CookTime(&raw, &cooked, NULL);
(*drv_apply_step_offset)(offset);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 1, ptr->anything);
(ptr->handler)(&raw, &cooked, 0.0, offset, 1, ptr->anything);
}
}
@@ -476,26 +489,39 @@ LCL_ApplyStepOffset(double offset)
/* ================================================== */
void
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
double offset, double dispersion)
{
ChangeListEntry *ptr;
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(raw, cooked, 0.0, offset, 1, ptr->anything);
}
lcl_InvokeDispersionNotifyHandlers(dispersion);
}
/* ================================================== */
void
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
double correction;
double old_freq_ppm;
LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
/* Due to modifying the offset, this has to be the cooked time prior
to the change we are about to make */
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
LCL_CookTime(&raw, &cooked, NULL);
old_freq_ppm = current_freq_ppm;
/* Work out new absolute frequency. Note that absolute frequencies
are handled in units of ppm, whereas the 'dfreq' argument is in
terms of the gradient of the (offset) v (local time) function. */
current_freq_ppm = (1.0 - dfreq) * old_freq_ppm +
(1.0e6 * dfreq);
current_freq_ppm = (1.0 + dfreq) * old_freq_ppm + 1.0e6 * dfreq;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
@@ -503,12 +529,14 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
#endif
/* Call the system-specific driver for setting the frequency */
(*drv_set_freq)(current_freq_ppm);
(*drv_accrue_offset)(doffset);
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm);
(*drv_accrue_offset)(doffset, corr_rate);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, doffset, 0, ptr->anything);
(ptr->handler)(&raw, &cooked, dfreq, doffset, 0, ptr->anything);
}
@@ -564,13 +592,13 @@ LCL_MakeStep(double threshold)
double correction;
LCL_ReadRawTime(&raw);
correction = LCL_GetOffsetCorrection(&raw);
LCL_GetOffsetCorrection(&raw, &correction, NULL);
if (fabs(correction) <= threshold)
return 0;
/* Cancel remaining slew and make the step */
LCL_AccumulateOffset(correction);
LCL_AccumulateOffset(correction, 0.0);
LCL_ApplyStepOffset(-correction);
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.3f seconds", correction);
@@ -591,3 +619,31 @@ LCL_SetLeap(int leap)
}
/* ================================================== */
double
LCL_SetTempComp(double comp)
{
double uncomp_freq_ppm;
if (temp_comp_ppm == comp)
return comp;
/* Undo previous compensation */
current_freq_ppm = (current_freq_ppm + temp_comp_ppm) /
(1.0 - 1.0e-6 * temp_comp_ppm);
uncomp_freq_ppm = current_freq_ppm;
/* Apply new compensation */
current_freq_ppm = current_freq_ppm * (1.0 - 1.0e-6 * comp) - comp;
/* Call the system-specific driver for setting the frequency */
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
temp_comp_ppm = (uncomp_freq_ppm - current_freq_ppm) /
(1.0e-6 * uncomp_freq_ppm + 1.0);
return temp_comp_ppm;
}
/* ================================================== */

43
local.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/local.h,v 1.16 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -50,11 +46,13 @@ extern void LCL_ReadRawTime(struct timeval *);
extern void LCL_ReadCookedTime(struct timeval *t, double *err);
/* Read the current offset between the system clock and true time
(i.e. 'cooked' - 'raw') (in seconds). Only intended for use in
status reporting, really. */
/* Convert raw time to cooked. */
extern void LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err);
extern double LCL_GetOffsetCorrection(struct timeval *raw);
/* Read the current offset between the system clock and true time
(i.e. 'cooked' - 'raw') (in seconds). */
extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err);
/* Type of routines that may be invoked as callbacks when there is a
change to the frequency or offset.
@@ -66,10 +64,6 @@ extern double LCL_GetOffsetCorrection(struct timeval *raw);
dfreq : delta frequency relative to previous value (in terms of
seconds gained by system clock per unit system clock time)
afreq : absolute frequency relative to uncompensated system (in
terms of ppm seconds gained by system clock per unit of the
uncalibrated system clock)
doffset : delta offset applied (positive => make local system fast
by that amount, negative => make it slow by that amount)
@@ -81,7 +75,7 @@ extern double LCL_GetOffsetCorrection(struct timeval *raw);
typedef void (*LCL_ParameterChangeHandler)
(struct timeval *raw, struct timeval *cooked,
double dfreq, double afreq_ppm,
double dfreq,
double doffset, int is_step_change,
void *anything
);
@@ -144,9 +138,10 @@ extern void LCL_AccumulateDeltaFrequency(double dfreq);
/* Routine to apply an offset (in seconds) to the local clock. The
argument should be positive to move the clock backwards (i.e. the
local clock is currently fast of true time), or negative to move it
forwards (i.e. it is currently slow of true time). */
forwards (i.e. it is currently slow of true time). Provided is also
a suggested correction rate (correction time * offset). */
extern void LCL_AccumulateOffset(double offset);
extern void LCL_AccumulateOffset(double offset, double corr_rate);
/* Routine to apply an immediate offset by doing a sudden step if
possible. (Intended for use after an initial estimate of offset has
@@ -157,9 +152,14 @@ extern void LCL_AccumulateOffset(double offset);
extern void LCL_ApplyStepOffset(double offset);
/* Routine to invoke notify handlers on an unexpected time jump
in system clock */
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
double offset, double dispersion);
/* Perform the combination of modifying the frequency and applying
a slew, in one easy step */
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
/* Routine to read the system precision as a log to base 2 value. */
extern int LCL_GetSysPrecisionAsLog(void);
@@ -167,6 +167,10 @@ extern int LCL_GetSysPrecisionAsLog(void);
/* Routine to read the system precision in terms of the actual time step */
extern double LCL_GetSysPrecisionAsQuantum(void);
/* Routine to read the maximum frequency error of the local clock. This
is a frequency stability, not an absolute error. */
extern double LCL_GetMaxClockError(void);
/* Routine to initialise the module (to be called once at program
start-up) */
@@ -186,4 +190,11 @@ extern int LCL_MakeStep(double threshold);
and zero cancels scheduled leap second. */
extern void LCL_SetLeap(int leap);
/* Routine to set a frequency correction (in ppm) that should be applied
to local clock to compensate for temperature changes. A positive
argument means that the clock frequency should be increased. Return the
actual compensation (may be different from the requested compensation
due to clamping or rounding). */
extern double LCL_SetTempComp(double comp);
#endif /* GOT_LOCAL_H */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/localp.h,v 1.9 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -40,12 +36,14 @@ typedef double (*lcl_ReadFrequencyDriver)(void);
/* System driver to set the current local frequency, in ppm relative
to nominal. A positive value indicates that the local clock runs
fast when uncompensated. */
typedef void (*lcl_SetFrequencyDriver)(double freq_ppm);
fast when uncompensated. Return actual frequency (may be different
from the requested frequency due to clamping or rounding). */
typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
/* System driver to accrue an offset. A positive argument means slew
the clock forwards. */
typedef void (*lcl_AccrueOffsetDriver)(double offset);
the clock forwards. The suggested correction rate of time to correct the
offset is given in 'corr_rate'. */
typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
/* System driver to apply a step offset. A positive argument means step
the clock forwards. */
@@ -54,7 +52,7 @@ typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
/* System driver to convert a raw time to an adjusted (cooked) time.
The number of seconds returned in 'corr' have to be added to the
raw time to get the corrected time */
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr, double *err);
/* System driver to schedule leap second */
typedef void (*lcl_SetLeapDriver)(int leap);

202
logging.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/logging.c,v 1.15 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012
*
* 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
@@ -28,17 +25,23 @@
Module to handle logging of diagnostic information
*/
#include "config.h"
#include "sysincl.h"
#include "main.h"
#include "conf.h"
#include "logging.h"
#include "version.h"
#include "mkdirpp.h"
#include "util.h"
/* ================================================== */
/* Flag indicating we have initialised */
static int initialised = 0;
static int is_detached = 0;
static int system_log = 0;
static int parent_fd = 0;
static time_t last_limited = 0;
@@ -46,6 +49,20 @@ static time_t last_limited = 0;
static FILE *logfile;
#endif
struct LogFile {
const char *name;
const char *banner;
FILE *file;
unsigned long writes;
};
static int n_filelogs = 0;
/* Increase this when adding a new logfile */
#define MAX_FILELOGS 6
static struct LogFile logfiles[MAX_FILELOGS];
/* ================================================== */
/* Init function */
@@ -72,11 +89,13 @@ LOG_Finalise(void)
fclose(logfile);
}
#else
if (is_detached) {
if (system_log) {
closelog();
}
#endif
LOG_CycleLogFiles();
initialised = 0;
return;
}
@@ -96,7 +115,7 @@ LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *form
fprintf(logfile, "%s\n", buf);
}
#else
if (is_detached) {
if (system_log) {
switch (severity) {
case LOGS_INFO:
syslog(LOG_INFO, "%s", buf);
@@ -132,11 +151,15 @@ LOG_Fatal_Function(LOG_Facility facility, const char *format, ...)
fprintf(logfile, "Fatal error : %s\n", buf);
}
#else
if (is_detached) {
if (system_log) {
syslog(LOG_CRIT, "Fatal error : %s", buf);
} else {
fprintf(stderr, "Fatal error : %s\n", buf);
}
if (parent_fd) {
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
; /* Not much we can do here */
}
#endif
MAI_CleanupAndExit();
@@ -154,7 +177,7 @@ LOG_Position(const char *filename, int line_number, const char *function_name)
time_t t;
struct tm stm;
char buf[64];
if (!is_detached) {
if (!system_log) {
/* Don't clutter up syslog with internal debugging info */
time(&t);
stm = *gmtime(&t);
@@ -168,55 +191,34 @@ LOG_Position(const char *filename, int line_number, const char *function_name)
/* ================================================== */
void
LOG_GoDaemon(void)
LOG_OpenSystemLog(void)
{
#ifdef WINNT
#else
int pid, fd;
/* Does this preserve existing signal handlers? */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'grandparent' */
} else {
setsid();
/* Do 2nd fork, as-per recommended practice for launching daemons. */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'parent' */
} else {
/* In the child we want to leave running as the daemon */
/* Don't keep stdin/out/err from before. */
for (fd=0; fd<1024; fd++) {
close(fd);
}
is_detached = 1;
system_log = 1;
openlog("chronyd", LOG_PID, LOG_DAEMON);
LOG(LOGS_INFO, LOGF_Logging, "chronyd version %s starting", PROGRAM_VERSION_STRING);
}
}
#endif
}
/* ================================================== */
void
LOG_SetParentFd(int fd)
{
parent_fd = fd;
}
/* ================================================== */
void
LOG_CloseParentFd()
{
if (parent_fd > 0)
close(parent_fd);
}
/* ================================================== */
int
LOG_RateLimited(void)
{
@@ -232,19 +234,97 @@ LOG_RateLimited(void)
}
/* ================================================== */
/* Force a core dump and exit without doing abort() or assert(0).
These do funny things with the call stack in the core file that is
generated, which makes diagnosis difficult. */
int
croak(const char *file, int line, const char *msg)
LOG_FileID
LOG_FileOpen(const char *name, const char *banner)
{
int a;
LOG(LOGS_ERR, LOGF_Util, "Unexpected condition [%s] at %s:%d, core dumped",
msg, file, line);
a = * (int *) 0;
return a; /* Can't happen - this stops the optimiser optimising the
line above */
assert(n_filelogs < MAX_FILELOGS);
logfiles[n_filelogs].name = name;
logfiles[n_filelogs].banner = banner;
logfiles[n_filelogs].file = NULL;
logfiles[n_filelogs].writes = 0;
return n_filelogs++;
}
/* ================================================== */
void
LOG_FileWrite(LOG_FileID id, const char *format, ...)
{
va_list other_args;
int banner;
if (id < 0 || id >= n_filelogs || !logfiles[id].name)
return;
if (!logfiles[id].file) {
char filename[512];
if (snprintf(filename, sizeof(filename), "%s/%s.log",
CNF_GetLogDir(), logfiles[id].name) >= sizeof(filename) ||
!(logfiles[id].file = fopen(filename, "a"))) {
LOG(LOGS_WARN, LOGF_Refclock, "Couldn't open logfile %s for update", filename);
logfiles[id].name = NULL;
return;
}
/* Close on exec */
UTI_FdSetCloexec(fileno(logfiles[id].file));
}
banner = CNF_GetLogBanner();
if (banner && logfiles[id].writes++ % banner == 0) {
char bannerline[256];
int i, bannerlen;
bannerlen = strlen(logfiles[id].banner);
for (i = 0; i < bannerlen; i++)
bannerline[i] = '=';
bannerline[i] = '\0';
fprintf(logfiles[id].file, "%s\n", bannerline);
fprintf(logfiles[id].file, "%s\n", logfiles[id].banner);
fprintf(logfiles[id].file, "%s\n", bannerline);
}
va_start(other_args, format);
vfprintf(logfiles[id].file, format, other_args);
va_end(other_args);
fprintf(logfiles[id].file, "\n");
fflush(logfiles[id].file);
}
/* ================================================== */
void
LOG_CreateLogFileDir(void)
{
const char *logdir;
logdir = CNF_GetLogDir();
if (!mkdir_and_parents(logdir)) {
LOG(LOGS_ERR, LOGF_Logging, "Could not create directory %s", logdir);
}
}
/* ================================================== */
void
LOG_CycleLogFiles(void)
{
LOG_FileID i;
for (i = 0; i < n_filelogs; i++) {
if (logfiles[i].file)
fclose(logfiles[i].file);
logfiles[i].file = NULL;
logfiles[i].writes = 0;
}
}
/* ================================================== */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/logging.h,v 1.15 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -58,11 +54,13 @@ typedef enum {
LOGF_CmdMon,
LOGF_Acquire,
LOGF_Manual,
LOGF_Keys,
LOGF_Logging,
LOGF_Rtc,
LOGF_Regress,
LOGF_Sys,
LOGF_SysLinux,
LOGF_SysNetBSD,
LOGF_SysSolaris,
LOGF_SysSunOS,
LOGF_SysWinnt,
@@ -85,7 +83,14 @@ extern void LOG_Fatal_Function(LOG_Facility facility, const char *format, ...);
/* Position in code reporting function */
extern void LOG_Position(const char *filename, int line_number, const char *function_name);
extern void LOG_GoDaemon(void);
/* Log messages to syslog instead of stderr */
extern void LOG_OpenSystemLog(void);
/* Send fatal message also to the foreground process */
extern void LOG_SetParentFd(int fd);
/* Close the pipe to the foreground process so it can exit */
extern void LOG_CloseParentFd(void);
/* Return zero once per 10 seconds */
extern int LOG_RateLimited(void);
@@ -100,13 +105,14 @@ extern int LOG_RateLimited(void);
#define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function
#endif /* defined (__GNUC__) */
/* Like assert(0) */
/* File logging functions */
#if defined(LINUX) && defined(__alpha__)
#define CROAK(message) assert(0) /* Added JGH Feb 24 2001 FIXME */
#else
extern int croak(const char *file, int line, const char *msg);
#define CROAK(message) croak(__FILE__, __LINE__, message);
#endif
typedef int LOG_FileID;
extern LOG_FileID LOG_FileOpen(const char *name, const char *banner);
extern void LOG_FileWrite(LOG_FileID id, const char *format, ...);
extern void LOG_CreateLogFileDir(void);
extern void LOG_CycleLogFiles(void);
#endif /* GOT_LOGGING_H */

119
main.c
View File

@@ -1,13 +1,10 @@
/*
$Header: /cvs/src/chrony/main.c,v 1.31 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
* Copyright (C) Miroslav Lichvar 2012
*
* 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
@@ -29,6 +26,8 @@
The main program
*/
#include "config.h"
#include "sysincl.h"
#include "main.h"
@@ -47,12 +46,12 @@
#include "keys.h"
#include "acquire.h"
#include "manual.h"
#include "version.h"
#include "rtc.h"
#include "refclock.h"
#include "clientlog.h"
#include "broadcast.h"
#include "nameserv.h"
#include "tempcomp.h"
/* ================================================== */
@@ -86,6 +85,7 @@ MAI_CleanupAndExit(void)
SRC_DumpSources();
}
TMC_Finalise();
MNL_Finalise();
ACQ_Finalise();
KEY_Finalise();
@@ -93,10 +93,10 @@ MAI_CleanupAndExit(void)
NSR_Finalise();
NCR_Finalise();
BRD_Finalise();
SRC_Finalise();
SST_Finalise();
REF_Finalise();
RCL_Finalise();
SRC_Finalise();
RTC_Finalise();
CAM_Finalise();
NIO_Finalise();
@@ -116,7 +116,6 @@ MAI_CleanupAndExit(void)
static void
signal_cleanup(int x)
{
LOG(LOGS_WARN, LOGF_Main, "chronyd exiting on signal");
if (!initialised) exit(0);
SCH_QuitProgram();
}
@@ -126,6 +125,8 @@ signal_cleanup(int x)
static void
post_acquire_hook(void *anything)
{
/* Close the pipe to the foreground process so it can exit */
LOG_CloseParentFd();
CNF_AddSources();
CNF_AddBroadcasts();
@@ -208,12 +209,84 @@ write_lockfile(void)
/* ================================================== */
static void
go_daemon(void)
{
#ifdef WINNT
#else
int pid, fd, pipefd[2];
/* Create pipe which will the daemon use to notify the grandparent
when it's initialised or send an error message */
if (pipe(pipefd)) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, pipe failed : %s", strerror(errno));
}
/* Does this preserve existing signal handlers? */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
/* In the 'grandparent' */
char message[1024];
int r;
close(pipefd[1]);
r = read(pipefd[0], message, sizeof (message));
if (r) {
if (r > 0) {
/* Print the error message from the child */
fprintf(stderr, "%.1024s\n", message);
}
exit(1);
} else
exit(0);
} else {
close(pipefd[0]);
setsid();
/* Do 2nd fork, as-per recommended practice for launching daemons. */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'parent' */
} else {
/* In the child we want to leave running as the daemon */
/* Change current directory to / */
if (chdir("/") < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not chdir to / : %s", strerror(errno));
}
/* Don't keep stdin/out/err from before. But don't close
the parent pipe yet. */
for (fd=0; fd<1024; fd++) {
if (fd != pipefd[1])
close(fd);
}
LOG_SetParentFd(pipefd[1]);
}
}
#endif
}
/* ================================================== */
int main
(int argc, char **argv)
{
char *conf_file = NULL;
char *user = NULL;
int debug = 0;
int debug = 0, nofork = 0;
int do_init_rtc = 0;
int other_pid;
int lock_memory = 0, sched_priority = 0;
@@ -246,10 +319,13 @@ int main
do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
/* This write to the terminal is OK, it comes before we turn into a daemon */
printf("chronyd (chrony) version %s\n", PROGRAM_VERSION_STRING);
printf("chronyd (chrony) version %s\n", CHRONY_VERSION);
exit(0);
} else if (!strcmp("-n", *argv)) {
nofork = 1;
} else if (!strcmp("-d", *argv)) {
debug = 1;
nofork = 1;
} else if (!strcmp("-4", *argv)) {
DNS_SetAddressFamily(IPADDR_INET4);
} else if (!strcmp("-6", *argv)) {
@@ -259,34 +335,36 @@ int main
}
}
#ifndef SYS_WINNT
if (getuid() != 0) {
/* This write to the terminal is OK, it comes before we turn into a daemon */
fprintf(stderr,"Not superuser\n");
exit(1);
}
/* Turn into a daemon */
if (!debug) {
LOG_GoDaemon();
if (!nofork) {
go_daemon();
}
if (!debug) {
LOG_OpenSystemLog();
}
LOG(LOGS_INFO, LOGF_Main, "chronyd version %s starting", CHRONY_VERSION);
CNF_ReadFile(conf_file);
/* Check whether another chronyd may already be running. Do this after
* forking, so that message logging goes to the right place (i.e. syslog), in
* case this chronyd is being run from a boot script. */
if (maybe_another_chronyd_running(&other_pid)) {
LOG_FATAL(LOGF_Main, "Another chronyd may already be running (pid=%d), check lockfile (%s)",
other_pid, CNF_GetPidFile());
exit(1);
}
/* Write our lockfile to prevent other chronyds running. This has *GOT* to
* be done *AFTER* the daemon-creation fork() */
write_lockfile();
#endif
CNF_ReadFile(conf_file);
if (do_init_rtc) {
RTC_TimePreInit();
@@ -298,6 +376,7 @@ int main
NIO_Initialise();
CAM_Initialise();
RTC_Initialise();
SRC_Initialise();
RCL_Initialise();
/* Command-line switch must have priority */
@@ -316,9 +395,10 @@ int main
SYS_DropRoot(user);
}
LOG_CreateLogFileDir();
REF_Initialise();
SST_Initialise();
SRC_Initialise();
BRD_Initialise();
NCR_Initialise();
NSR_Initialise();
@@ -326,6 +406,7 @@ int main
KEY_Initialise();
ACQ_Initialise();
MNL_Initialise();
TMC_Initialise();
/* From now on, it is safe to do finalisation on exit */
initialised = 1;
@@ -347,6 +428,8 @@ int main
the scheduler. */
SCH_MainLoop();
LOG(LOGS_INFO, LOGF_Main, "chronyd exiting");
MAI_CleanupAndExit();
return 0;

4
main.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/main.h,v 1.8 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,52 +1,51 @@
#!/usr/bin/env perl
#!/bin/sh
$tool = "chrony";
LANG=C
export LANG
$version = shift || die "Usage : $0 <version>\n";
$subdir = "${tool}-${version}";
if [ $# -ne 1 ]; then
echo "Usage : $0 <version>"
exit 2
fi
unless (-d ".git") {
die "No .git subdirectory?"
}
version=$1
subdir=chrony-${version}
mandate=$(date +'%B %Y')
unless (-d "RELEASES") {
mkdir "RELEASES", 0755;
}
umask 022
system ("git tag -s $version");
die "git-tag failed" if ($? != 0);
if (-d "RELEASES/$subdir") {
system ("rm -rf RELEASES/$subdir");
}
if [ ! -d .git ]; then
echo "No .git subdirectory?"
exit 3
fi
system ("git archive --format=tar --prefix=RELEASES/${subdir}/ $version | tar xf -");
die "git-tar-tree failed" if ($? != 0);
[ -d RELEASES ] || mkdir RELEASES
chdir "RELEASES";
$here = qx/pwd/;
chomp $here;
chdir $subdir;
git tag -s $version || exit 1
open (OUT, ">version.txt");
print OUT $version."\n";
close OUT;
rm -rf RELEASES/$subdir
open (IN, "<${tool}.spec.sample");
open (OUT, ">${tool}.spec");
while (<IN>) {
s/\@\@VERSION\@\@/$version/;
print OUT;
}
close (IN);
close (OUT);
git archive --format=tar --prefix=RELEASES/${subdir}/ $version | \
tar xf - || exit 1
system("makeinfo --no-headers --number-sections -o chrony.txt chrony.texi");
unlink "make_release";
unlink "${tool}.spec.sample";
unlink ".gitignore";
cd RELEASES/$subdir || exit 1
chdir $here;
system ("tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz");
system ("gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz");
echo $version > version.txt
sed -e "s%@@VERSION@@%${version}%" < chrony.spec.sample > chrony.spec
for m in chrony.1 chronyc.1 chrony.conf.5 chronyd.8; do
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
< $m > ${m}_
mv -f ${m}_ $m
done
makeinfo --no-headers --number-sections -o chrony.txt chrony.texi
rm -f make_release chrony.spec.sample .gitignore
cd ..
tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz
gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/manual.c,v 1.21 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -34,6 +30,8 @@
*/
#include "config.h"
#include <stddef.h>
#include "manual.h"
@@ -74,7 +72,6 @@ static void
slew_samples(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *not_used);
@@ -148,6 +145,8 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
}
b1 = freq = 0.0;
found_freq = 0;
agos[0] = 0.0;
offsets[0] = b0;
}
if (offset_provided) {
@@ -188,14 +187,13 @@ int
MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
{
struct timeval now;
double local_clock_err;
double offset;
int i;
if (enabled) {
/* Check whether timestamp is within margin of old one */
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, NULL);
UTI_DiffTimevalsToDouble(&offset, &now, ts);
@@ -230,17 +228,15 @@ static void
slew_samples(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *not_used)
{
double elapsed, delta_time;
double delta_time;
int i;
for (i=0; i<n_samples; i++) {
UTI_DiffTimevalsToDouble(&elapsed, cooked, &samples[i].when);
delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(&samples[i].when, delta_time, &samples[i].when);
UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time,
dfreq, doffset);
samples[i].offset += delta_time;
}
return;
@@ -303,7 +299,6 @@ MNL_DeleteSample(int index)
{
int i;
struct timeval now;
double local_clock_err;
if ((index < 0) || (index >= n_samples)) {
return 0;
@@ -319,7 +314,7 @@ MNL_DeleteSample(int index)
/* Now re-estimate. NULLs because we don't want the parameters back
in this case. */
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, NULL);
estimate_and_set_system(&now, 0, 0.0, NULL, NULL, NULL);
return 1;

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/manual.h,v 1.12 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/memory.h,v 1.7 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/mkdirpp.c,v 1.10 2002/11/03 22:49:17 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -30,6 +26,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "mkdirpp.h"
@@ -86,6 +84,7 @@ mkdir_and_parents(const char *path)
p[i] = 0;
if (do_dir(p) < 0) {
free(p);
return 0;
}

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/mkdirpp.h,v 1.6 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,15 +0,0 @@
#!/bin/sh
rm -f version.h
echo "#ifndef VERSION_H" > version.h
echo "#define VERSION_H 1" >> version.h
if [ -f version.txt ]; then
ver=`cat version.txt`
echo "#define PROGRAM_VERSION_STRING \"$ver\"" >> version.h
else
echo "#define PROGRAM_VERSION_STRING \"DEVELOPMENT\"" >> version.h
fi
echo "#endif /* VERSION_H */" >> version.h

View File

@@ -1,13 +1,9 @@
/*
$Header: /cvs/src/chrony/nameserv.c,v 1.15 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009-2011
*
* 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
@@ -30,6 +26,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "nameserv.h"
@@ -38,9 +36,6 @@
/* ================================================== */
#define MAXRETRIES 10
static unsigned int retries = 0;
static int address_family = IPADDR_UNSPEC;
void
@@ -49,8 +44,8 @@ DNS_SetAddressFamily(int family)
address_family = family;
}
int
DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
DNS_Status
DNS_Name2IPAddress(const char *name, IPAddr *addr)
{
#ifdef HAVE_IPV6
struct addrinfo hints, *res, *ai;
@@ -59,21 +54,15 @@ DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
#endif
try_again:
result = getaddrinfo(name, NULL, &hints, &res);
if (result) {
if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
return 0;
#ifdef FORCE_DNSRETRY
return DNS_TryAgain;
#else
return result == EAI_AGAIN ? DNS_TryAgain : DNS_Failure;
#endif
}
for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
@@ -96,32 +85,27 @@ try_again:
}
freeaddrinfo(res);
return result;
return result ? DNS_Success : DNS_Failure;
#else
struct hostent *host;
char *address0;
try_again:
host = gethostbyname(name);
if (host == NULL) {
if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
if (h_errno == TRY_AGAIN)
return DNS_TryAgain;
} else {
addr->family = IPADDR_INET4;
address0 = host->h_addr_list[0];
addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
return 1;
addr->addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[0]);
return DNS_Success;
}
return 0;
#ifdef FORCE_DNSRETRY
return DNS_TryAgain;
#else
return DNS_Failure;
#endif
#endif
}
@@ -190,3 +174,11 @@ DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
/* ================================================== */
void
DNS_Reload(void)
{
res_init();
}
/* ================================================== */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/nameserv.h,v 1.8 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -34,12 +30,20 @@
#include "addressing.h"
typedef enum {
DNS_Success,
DNS_TryAgain,
DNS_Failure
} DNS_Status;
/* Resolve names only to selected address family */
extern void DNS_SetAddressFamily(int family);
extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *addr);
extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
extern void DNS_Reload(void);
#endif /* GOT_NAMESERV_H */

12
ntp.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/ntp.h,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -37,6 +33,8 @@
#include <inttypes.h>
#endif
#include "hash.h"
typedef struct {
uint32_t hi;
uint32_t lo;
@@ -44,7 +42,7 @@ typedef struct {
typedef uint32_t NTP_int32;
#define AUTH_DATA_LEN 16
#define MAX_NTP_AUTH_DATA_LEN MAX_HASH_LENGTH
/* Type definition for leap bits */
typedef enum {
@@ -76,7 +74,7 @@ typedef struct {
NTP_int64 receive_ts;
NTP_int64 transmit_ts;
NTP_int32 auth_keyid;
uint8_t auth_data[AUTH_DATA_LEN];
uint8_t auth_data[MAX_NTP_AUTH_DATA_LEN];
} NTP_Packet;
/* We have to declare a buffer type to hold a datagram read from the
@@ -93,7 +91,7 @@ typedef union {
uint8_t arbitrary[MAX_NTP_MESSAGE_SIZE];
} ReceiveBuffer;
#define NTP_NORMAL_PACKET_SIZE (sizeof(NTP_Packet) - (sizeof(NTP_int32) + AUTH_DATA_LEN))
#define NTP_NORMAL_PACKET_SIZE offsetof(NTP_Packet, auth_keyid)
/* ================================================== */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/ntp_core.h,v 1.16 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -38,6 +34,10 @@
#include "ntp.h"
#include "reports.h"
typedef enum {
NTP_SERVER, NTP_PEER
} NTP_Source_Type;
/* This is a private data type used for storing the instance record for
each source that we are chiming with */
typedef struct NCR_Instance_Record *NCR_Instance;
@@ -46,31 +46,19 @@ typedef struct NCR_Instance_Record *NCR_Instance;
extern void NCR_Initialise(void);
extern void NCR_Finalise(void);
/* Get a new instance for a server */
extern NCR_Instance NCR_GetServerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Get a new instance for a peer */
extern NCR_Instance NCR_GetPeerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Get a new instance for a server or peer */
extern NCR_Instance NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params);
/* Destroy an instance */
extern void NCR_DestroyInstance(NCR_Instance instance);
/* This routine is called when a new packet arrives off the network,
and it relates to a source we have an ongoing protocol exchange with */
extern void NCR_ProcessNoauthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
extern void NCR_ProcessKnown(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance data, int length);
/* This routine is called when a new packet arrives off the network,
and we do not recognize its source */
extern void NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* This routine is called when a new authenticated packet arrives off
the network, and it relates to a source we have an ongoing protocol
exchange with */
extern void NCR_ProcessAuthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
/* This routine is called when a new authenticated packet arrives off
the network, and we do not recognize its source */
extern void NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
extern void NCR_ProcessUnknown(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, int length);
/* Slew receive and transmit times in instance records */
extern void NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset);
@@ -90,6 +78,12 @@ extern void NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay);
extern void NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio);
extern void NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio);
extern void NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum);
extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
@@ -97,11 +91,11 @@ extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void);
extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
int *burst_online, int *burst_offline);
extern NTP_Remote_Address *NCR_GetRemoteAddress(NCR_Instance instance);
extern int NCR_IsSyncPeer(NCR_Instance instance);
#endif /* GOT_NTP_CORE_H */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/ntp_io.c,v 1.24 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -30,6 +26,8 @@
This file deals with the IO aspects of reading and writing NTP packets
*/
#include "config.h"
#include "sysincl.h"
#include "ntp_io.h"
@@ -121,6 +119,9 @@ prepare_socket(int family)
return -1;
}
/* Close on exec */
UTI_FdSetCloexec(sock_fd);
/* Make the socket capable of re-using an old address */
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set reuseaddr socket options");
@@ -158,6 +159,16 @@ prepare_socket(int family)
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
}
#endif
#ifdef IPV6_RECVPKTINFO
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPv6 packet info socket option");
}
#elif defined(IPV6_PKTINFO)
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPv6 packet info socket option");
}
#endif
}
#endif
@@ -281,6 +292,7 @@ read_from_socket(void *anything)
union sockaddr_in46 where_from;
unsigned int flags = 0;
struct timeval now;
double now_err;
NTP_Remote_Address remote_addr;
char cmsgbuf[256];
struct msghdr msg;
@@ -289,7 +301,7 @@ read_from_socket(void *anything)
assert(initialised);
SCH_GetFileReadyTime(&now);
SCH_GetFileReadyTime(&now, &now_err);
iov.iov_base = message.arbitrary;
iov.iov_len = sizeof(message);
@@ -343,30 +355,30 @@ read_from_socket(void *anything)
}
#endif
#if defined(IPV6_PKTINFO) && defined(HAVE_IN6_PKTINFO)
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
struct in6_pktinfo ipi;
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
memcpy(&remote_addr.local_ip_addr.addr.in6, &ipi.ipi6_addr.s6_addr,
sizeof (remote_addr.local_ip_addr.addr.in6));
remote_addr.local_ip_addr.family = IPADDR_INET6;
}
#endif
#ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
double correction;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
correction = LCL_GetOffsetCorrection(&tv);
UTI_AddDoubleToTimeval(&tv, correction, &tv);
#if 0
UTI_DiffTimevalsToDouble(&correction, &now, &tv);
LOG(LOGS_INFO, LOGF_NtpIO, "timestamp diff: %f", correction);
#endif
now = tv;
LCL_CookTime(&tv, &now, &now_err);
}
#endif
}
if (status == NTP_NORMAL_PACKET_SIZE) {
if (status >= NTP_NORMAL_PACKET_SIZE && status <= sizeof(NTP_Packet)) {
NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
} else if (status == sizeof(NTP_Packet)) {
NSR_ProcessAuthenticatedReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, now_err, &remote_addr, status);
} else {
@@ -450,6 +462,25 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
}
#endif
#if defined(IPV6_PKTINFO) && defined(HAVE_IN6_PKTINFO)
if (remote_addr->local_ip_addr.family == IPADDR_INET6) {
struct cmsghdr *cmsg;
struct in6_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg);
memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
cmsglen += CMSG_SPACE(sizeof(struct in6_pktinfo));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
ipi = (struct in6_pktinfo *) CMSG_DATA(cmsg);
memcpy(&ipi->ipi6_addr.s6_addr, &remote_addr->local_ip_addr.addr.in6,
sizeof(ipi->ipi6_addr.s6_addr));
}
#endif
#if 0
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
@@ -460,7 +491,14 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
if (!cmsglen)
msg.msg_control = NULL;
if (sendmsg(sock_fd, &msg, 0) < 0 && !LOG_RateLimited()) {
if (sendmsg(sock_fd, &msg, 0) < 0 &&
#ifdef ENETUNREACH
errno != ENETUNREACH &&
#endif
#ifdef ENETDOWN
errno != ENETDOWN &&
#endif
!LOG_RateLimited()) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
@@ -481,9 +519,9 @@ NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
/* Send an authenticated packet to a given address */
void
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, int auth_len)
{
send_packet((void *) packet, sizeof(NTP_Packet), remote_addr);
send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE + auth_len, remote_addr);
}
/* ================================================== */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/ntp_io.h,v 1.9 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -45,7 +41,7 @@ extern void NIO_Finalise(void);
extern void NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
/* Function to transmit an authenticated packet */
extern void NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
extern void NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, int auth_len);
/* Function to send a datagram to a remote machine's UDP echo port. */
extern void NIO_SendEcho(NTP_Remote_Address *remote_addr);

View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/ntp_sources.c,v 1.18 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012
*
* 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
@@ -30,6 +27,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "ntp_sources.h"
@@ -37,6 +36,9 @@
#include "util.h"
#include "logging.h"
#include "local.h"
#include "memory.h"
#include "nameserv.h"
#include "sched.h"
/* ================================================== */
@@ -60,13 +62,25 @@ static int n_sources;
/* The largest number of sources we want to have stored in the hash table */
#define MAX_SOURCES 64
/* Source with unknown address (which may be resolved later) */
struct UnresolvedSource {
char *name;
int port;
NTP_Source_Type type;
SourceParameters params;
struct UnresolvedSource *next;
};
static struct UnresolvedSource *unresolved_sources = NULL;
static int resolving_interval = 0;
static SCH_TimeoutID resolving_id;
/* ================================================== */
/* Forward prototypes */
static void
slew_sources(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *anything);
@@ -171,10 +185,9 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
/* ================================================== */
/* Procedure to add a new server source (to which this machine will be
a client) */
/* Procedure to add a new source */
NSR_Status
NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params)
{
int slot, found;
@@ -196,7 +209,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
return NSR_InvalidAF;
} else {
n_sources++;
records[slot].data = NCR_GetServerInstance(remote_addr, params); /* Will need params passing through */
records[slot].data = NCR_GetInstance(remote_addr, type, params); /* Will need params passing through */
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success;
}
@@ -205,34 +218,83 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
/* ================================================== */
/* Procedure to add a new peer. */
NSR_Status
NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
static void
resolve_sources(void *arg)
{
int slot, found;
NTP_Remote_Address address;
struct UnresolvedSource *us, **i;
DNS_Status s;
assert(initialised);
memset(&address.local_ip_addr, 0, sizeof (address.local_ip_addr));
#if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif
DNS_Reload();
/* Find empty bin & check that we don't have the address already */
find_slot(remote_addr, &slot, &found);
if (found) {
return NSR_AlreadyInUse;
for (i = &unresolved_sources; *i; ) {
us = *i;
s = DNS_Name2IPAddress(us->name, &address.ip_addr);
if (s == DNS_TryAgain) {
i = &(*i)->next;
continue;
} else if (s == DNS_Success) {
address.port = us->port;
NSR_AddSource(&address, us->type, &us->params);
} else {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else {
n_sources++;
records[slot].data = NCR_GetPeerInstance(remote_addr, params); /* Will need params passing through */
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success;
LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name);
}
*i = us->next;
Free(us->name);
Free(us);
}
if (unresolved_sources) {
/* Try again later */
if (resolving_interval < 9)
resolving_interval++;
resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
} else {
resolving_interval = 0;
}
}
/* ================================================== */
/* Procedure to add a new server or peer source, but instead of an IP address
only a name is provided */
void
NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params)
{
struct UnresolvedSource *us, **i;
us = MallocNew(struct UnresolvedSource);
us->name = name;
us->port = port;
us->type = type;
us->params = *params;
us->next = NULL;
for (i = &unresolved_sources; *i; i = &(*i)->next)
;
*i = us;
if (!resolving_interval) {
resolving_interval = 2;
resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
}
}
/* ================================================== */
void
NSR_ResolveSources(void)
{
/* Try to resolve unresolved sources now */
if (resolving_interval) {
SCH_RemoveTimeout(resolving_id);
resolving_interval--;
resolve_sources(NULL);
}
}
@@ -245,26 +307,49 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
NSR_Status
NSR_RemoveSource(NTP_Remote_Address *remote_addr)
{
int slot, found;
int i, slot, found;
SourceRecord temp_records[N_RECORDS];
assert(initialised);
find_slot(remote_addr, &slot, &found);
if (!found) {
return NSR_NoSuchSource;
} else {
}
n_sources--;
records[slot].remote_addr = NULL;
NCR_DestroyInstance(records[slot].data);
return NSR_Success;
/* Rehash the table to make sure there are no broken probe sequences.
This is costly, but it's not expected to happen frequently. */
memcpy(temp_records, records, sizeof (records));
for (i = 0; i < N_RECORDS; i++) {
records[i].remote_addr = NULL;
}
for (i = 0; i < N_RECORDS; i++) {
if (!temp_records[i].remote_addr)
continue;
find_slot(temp_records[i].remote_addr, &slot, &found);
assert(!found);
records[slot].remote_addr = temp_records[i].remote_addr;
records[slot].data = temp_records[i].data;
}
return NSR_Success;
}
/* ================================================== */
/* This routine is called by ntp_io when a new packet arrives off the network.*/
/* This routine is called by ntp_io when a new packet arrives off the network,
possibly with an authentication tail */
void
NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr)
NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, int length)
{
int slot, found;
@@ -278,27 +363,9 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
find_slot(remote_addr, &slot, &found);
if (found == 2) { /* Must match IP address AND port number */
NCR_ProcessNoauthKnown(message, now, records[slot].data);
NCR_ProcessKnown(message, now, now_err, records[slot].data, length);
} else {
NCR_ProcessNoauthUnknown(message, now, remote_addr);
}
}
/* ================================================== */
/* This routine is called by ntp_io when a new packet with an authentication tail arrives off the network */
void
NSR_ProcessAuthenticatedReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr)
{
int slot, found;
assert(initialised);
find_slot(remote_addr, &slot, &found);
if (found == 2) {
NCR_ProcessAuthKnown(message, now, records[slot].data);
} else {
NCR_ProcessAuthUnknown(message, now, remote_addr);
NCR_ProcessUnknown(message, now, now_err, remote_addr, length);
}
}
@@ -308,7 +375,6 @@ static void
slew_sources(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *anything)
@@ -336,6 +402,8 @@ NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
int i;
int any;
NSR_ResolveSources();
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) {
@@ -347,6 +415,15 @@ NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
}
}
if (address->family == IPADDR_UNSPEC) {
struct UnresolvedSource *us;
for (us = unresolved_sources; us; us = us->next) {
any = 1;
us->params.online = 1;
}
}
return any;
}
@@ -355,20 +432,38 @@ NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
int
NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
int i, any, syncpeer;
any = 0;
syncpeer = -1;
for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1;
if (NCR_IsSyncPeer(records[i].data)) {
syncpeer = i;
continue;
}
NCR_TakeSourceOffline(records[i].data);
}
}
}
/* Take sync peer offline as last to avoid reference switching */
if (syncpeer >= 0) {
NCR_TakeSourceOffline(records[syncpeer].data);
}
if (address->family == IPADDR_UNSPEC) {
struct UnresolvedSource *us;
for (us = unresolved_sources; us; us = us->next) {
any = 1;
us->params.online = 0;
}
}
return any;
}
@@ -450,6 +545,63 @@ NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
/* ================================================== */
int
NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_dev_ratio)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyMaxdelaydevratio(records[slot].data, new_max_delay_dev_ratio);
return 1;
}
}
/* ================================================== */
int
NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyMinstratum(records[slot].data, new_min_stratum);
return 1;
}
}
/* ================================================== */
int
NSR_ModifyPolltarget(IPAddr *address, int new_poll_target)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyPolltarget(records[slot].data, new_poll_target);
return 1;
}
}
/* ================================================== */
int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
IPAddr *mask, IPAddr *address)
@@ -499,6 +651,7 @@ void
NSR_GetActivityReport(RPT_ActivityReport *report)
{
int i;
struct UnresolvedSource *us;
report->online = 0;
report->offline = 0;
@@ -511,6 +664,13 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
&report->burst_online, &report->burst_offline);
}
}
report->unresolved = 0;
for (us = unresolved_sources; us; us = us->next) {
report->unresolved++;
}
return;
}

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/ntp_sources.h,v 1.12 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -45,27 +41,27 @@
typedef enum {
NSR_Success, /* Operation successful */
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
NSR_AlreadyInUse, /* AddSource - attempt to add a source that is already known */
NSR_TooManySources, /* AddSource - too many sources already present */
NSR_InvalidAF /* AddSource - attempt to add a source with invalid address family */
} NSR_Status;
/* Procedure to add a new server source (to which this machine will be
a client) */
extern NSR_Status NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Procedure to add a new server or peer source. */
extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params);
/* Procedure to add a new peer source. We will use symmetric active
mode packets when communicating with this source */
extern NSR_Status NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Procedure to add a new server or peer source with currently unknown address.
The name will be periodically resolved in exponentially increasing intervals
until it succeeds or fails with a non-temporary error. */
extern void NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params);
/* Procedure to try resolve unresolved sources immediately. */
extern void NSR_ResolveSources(void);
/* Procedure to remove a source */
extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr);
/* This routine is called by ntp_io when a new packet arrives off the network */
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* This routine is called by ntp_io when a new packet with an authentication tail arrives off the network */
extern void NSR_ProcessAuthenticatedReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, int length);
/* Initialisation function */
extern void NSR_Initialise(void);
@@ -91,6 +87,12 @@ extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
extern int NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_ratio);
extern int NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum);
extern int NSR_ModifyPolltarget(IPAddr *address, int new_poll_target);
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/pktlength.c,v 1.12 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -30,6 +26,8 @@
integer endianness within the structures.
*/
#include "config.h"
#include "sysincl.h"
#include "util.h"
@@ -65,6 +63,8 @@ PKL_CommandLength(CMD_Request *r)
return offsetof(CMD_Request, data.modify_maxdelay.EOR);
case REQ_MODIFY_MAXDELAYRATIO:
return offsetof(CMD_Request, data.modify_maxdelayratio.EOR);
case REQ_MODIFY_MAXDELAYDEVRATIO:
return offsetof(CMD_Request, data.modify_maxdelaydevratio.EOR);
case REQ_MODIFY_MAXUPDATESKEW:
return offsetof(CMD_Request, data.modify_maxupdateskew.EOR);
case REQ_LOGON :
@@ -147,6 +147,14 @@ PKL_CommandLength(CMD_Request *r)
return offsetof(CMD_Request, data.make_step.EOR);
case REQ_ACTIVITY:
return offsetof(CMD_Request, data.activity.EOR);
case REQ_RESELECT:
return offsetof(CMD_Request, data.reselect.EOR);
case REQ_RESELECTDISTANCE:
return offsetof(CMD_Request, data.reselect_distance.EOR);
case REQ_MODIFY_MINSTRATUM:
return offsetof(CMD_Request, data.modify_minstratum.EOR);
case REQ_MODIFY_POLLTARGET:
return offsetof(CMD_Request, data.modify_polltarget.EOR);
default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0);

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/pktlength.h,v 1.4 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -2,7 +2,7 @@
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009-2011
*
* 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
@@ -25,6 +25,8 @@
*/
#include "config.h"
#include "refclock.h"
#include "reference.h"
#include "conf.h"
@@ -33,8 +35,8 @@
#include "util.h"
#include "sources.h"
#include "logging.h"
#include "regress.h"
#include "sched.h"
#include "mkdirpp.h"
/* list of refclock drivers */
extern RefclockDriver RCL_SHM_driver;
@@ -43,6 +45,7 @@ extern RefclockDriver RCL_PPS_driver;
struct FilterSample {
double offset;
double dispersion;
struct timeval sample_time;
};
@@ -51,7 +54,13 @@ struct MedianFilter {
int index;
int used;
int last;
int avg_var_n;
double avg_var;
struct FilterSample *samples;
int *selected;
double *x_data;
double *y_data;
double *w_data;
};
struct RCL_Instance_Record {
@@ -62,14 +71,14 @@ struct RCL_Instance_Record {
int driver_poll;
int driver_polled;
int poll;
int missed_samples;
int leap_status;
int pps_rate;
struct MedianFilter filter;
unsigned long ref_id;
unsigned long lock_ref;
uint32_t ref_id;
uint32_t lock_ref;
double offset;
double delay;
double precision;
SCH_TimeoutID timeout_id;
SRC_Instance source;
};
@@ -79,42 +88,40 @@ struct RCL_Instance_Record {
static struct RCL_Instance_Record refclocks[MAX_RCL_SOURCES];
static int n_sources = 0;
#define REFCLOCKS_LOG "refclocks.log"
static FILE *logfile = NULL;
static char *logfilename = NULL;
static unsigned long logwrites = 0;
static LOG_FileID logfileid;
static int valid_sample_time(RCL_Instance instance, struct timeval *tv);
static int pps_stratum(RCL_Instance instance, struct timeval *tv);
static void poll_timeout(void *arg);
static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
double doffset, int is_step_change, void *anything);
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int pulse, double raw_offset, double cooked_offset);
static void add_dispersion(double dispersion, void *anything);
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
static void filter_init(struct MedianFilter *filter, int length);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset);
static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset);
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion);
static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
static int filter_select_samples(struct MedianFilter *filter);
static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
static void filter_add_dispersion(struct MedianFilter *filter, double dispersion);
void
RCL_Initialise(void)
{
CNF_AddRefclocks();
if (CNF_GetLogRefclocks()) {
char *logdir = CNF_GetLogDir();
if (!mkdir_and_parents(logdir)) {
LOG(LOGS_ERR, LOGF_Refclock, "Could not create directory %s", logdir);
} else {
logfilename = MallocArray(char, 2 + strlen(logdir) + strlen(REFCLOCKS_LOG));
strcpy(logfilename, logdir);
strcat(logfilename, "/");
strcat(logfilename, REFCLOCKS_LOG);
}
if (n_sources > 0) {
LCL_AddParameterChangeHandler(slew_samples, NULL);
LCL_AddDispersionNotifyHandler(add_dispersion, NULL);
}
logfileid = CNF_GetLogRefclocks() ? LOG_FileOpen("refclocks",
" Date (UTC) Time Refid DP L P Raw offset Cooked offset Disp.")
: -1;
}
void
@@ -132,12 +139,10 @@ RCL_Finalise(void)
Free(inst->driver_parameter);
}
if (n_sources > 0)
if (n_sources > 0) {
LCL_RemoveParameterChangeHandler(slew_samples, NULL);
if (logfile)
fclose(logfile);
Free(logfilename);
LCL_RemoveDispersionNotifyHandler(add_dispersion, NULL);
}
}
int
@@ -150,13 +155,16 @@ RCL_AddRefclock(RefclockParameters *params)
if (n_sources == MAX_RCL_SOURCES)
return 0;
if (strncmp(params->driver_name, "SHM", 4) == 0) {
if (strcmp(params->driver_name, "SHM") == 0) {
inst->driver = &RCL_SHM_driver;
} else if (strncmp(params->driver_name, "SOCK", 4) == 0) {
inst->precision = 1e-6;
} else if (strcmp(params->driver_name, "SOCK") == 0) {
inst->driver = &RCL_SOCK_driver;
inst->precision = 1e-9;
pps_source = 1;
} else if (strncmp(params->driver_name, "PPS", 4) == 0) {
} else if (strcmp(params->driver_name, "PPS") == 0) {
inst->driver = &RCL_PPS_driver;
inst->precision = 1e-9;
pps_source = 1;
} else {
LOG_FATAL(LOGF_Refclock, "unknown refclock driver %s", params->driver_name);
@@ -173,13 +181,14 @@ RCL_AddRefclock(RefclockParameters *params)
inst->driver_parameter_length = 0;
inst->driver_poll = params->driver_poll;
inst->poll = params->poll;
inst->missed_samples = 0;
inst->driver_polled = 0;
inst->leap_status = 0;
inst->leap_status = LEAP_Normal;
inst->pps_rate = params->pps_rate;
inst->lock_ref = params->lock_ref_id;
inst->offset = params->offset;
inst->delay = params->delay;
if (params->precision > 0.0)
inst->precision = params->precision;
inst->timeout_id = -1;
inst->source = NULL;
@@ -199,18 +208,31 @@ RCL_AddRefclock(RefclockParameters *params)
inst->pps_rate = 0;
}
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
if (params->ref_id)
inst->ref_id = params->ref_id;
else {
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
snprintf((char *)ref, 5, "%3s%d", params->driver_name, n_sources % 10);
snprintf((char *)ref, 5, "%3.3s%d", params->driver_name, n_sources % 10);
inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
}
if (inst->driver->poll) {
int max_samples;
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
max_samples = 1 << (inst->poll - inst->driver_poll);
if (max_samples < params->filter_length) {
if (max_samples < 4) {
LOG(LOGS_WARN, LOGF_Refclock, "Setting filter length for %s to %d",
UTI_RefidToString(inst->ref_id), max_samples);
}
params->filter_length = max_samples;
}
}
if (inst->driver->init)
if (!inst->driver->init(inst)) {
LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
@@ -219,12 +241,16 @@ RCL_AddRefclock(RefclockParameters *params)
filter_init(&inst->filter, params->filter_length);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock added poll=%d dpoll=%d filter=%d",
inst->poll, inst->driver_poll, params->filter_length);
#endif
n_sources++;
Free(params->driver_name);
return 1;
}
@@ -236,7 +262,7 @@ RCL_StartRefclocks(void)
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
SRC_SetSelectable(inst->source);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
if (inst->lock_ref) {
@@ -247,16 +273,13 @@ RCL_StartRefclocks(void)
} else
inst->lock_ref = -1;
}
if (n_sources > 0)
LCL_AddParameterChangeHandler(slew_samples, NULL);
}
void
RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
{
int i;
unsigned long ref_id;
uint32_t ref_id;
assert(report->ip_addr.family == IPADDR_INET4);
ref_id = report->ip_addr.addr.in4;
@@ -315,26 +338,36 @@ RCL_GetDriverOption(RCL_Instance instance, char *name)
}
int
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap)
{
double correction;
double correction, dispersion;
struct timeval cooked_time;
correction = LCL_GetOffsetCorrection(sample_time);
LCL_GetOffsetCorrection(sample_time, &correction, &dispersion);
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
dispersion += instance->precision + filter_get_avg_sample_dispersion(&instance->filter);
if (!valid_sample_time(instance, sample_time))
return 0;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock sample offset=%.9f cooked=%.9f",
offset, offset - correction + instance->offset);
#endif
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset);
instance->leap_status = leap_status;
switch (leap) {
case LEAP_Normal:
case LEAP_InsertSecond:
case LEAP_DeleteSecond:
instance->leap_status = leap;
break;
default:
instance->leap_status = LEAP_Unsynchronised;
break;
}
log_sample(instance, &cooked_time, 0, offset, offset - correction + instance->offset);
log_sample(instance, &cooked_time, 0, 0, offset, offset - correction + instance->offset, dispersion);
/* for logging purposes */
if (!instance->driver->poll)
instance->driver_polled++;
return 1;
}
@@ -342,18 +375,13 @@ RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset,
int
RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
{
double correction, offset;
double correction, dispersion, offset;
struct timeval cooked_time;
int rate;
struct timeval ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
NTP_Leap leap;
unsigned long ref_id;
correction = LCL_GetOffsetCorrection(pulse_time);
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
dispersion += instance->precision + filter_get_avg_sample_dispersion(&instance->filter);
if (!valid_sample_time(instance, pulse_time))
return 0;
@@ -372,10 +400,10 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
if (instance->lock_ref != -1) {
struct timeval ref_sample_time;
double sample_diff, ref_offset, shift;
double sample_diff, ref_offset, ref_dispersion, shift;
if (!filter_get_last_sample(&refclocks[instance->lock_ref].filter,
&ref_sample_time, &ref_offset))
&ref_sample_time, &ref_offset, &ref_dispersion))
return 0;
UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
@@ -390,7 +418,7 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
offset += shift;
if (fabs(ref_offset - offset) >= 0.2 / rate)
if (fabs(ref_offset - offset) + ref_dispersion + dispersion >= 0.2 / rate)
return 0;
#if 0
@@ -398,6 +426,12 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
second, offset, ref_offset - offset, sample_diff);
#endif
} else {
struct timeval ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
NTP_Leap leap;
uint32_t ref_id;
/* Ignore the pulse if we are not well synchronized */
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
@@ -415,29 +449,18 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
}
}
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f",
second, offset);
#endif
filter_add_sample(&instance->filter, &cooked_time, offset);
filter_add_sample(&instance->filter, &cooked_time, offset, dispersion);
instance->leap_status = LEAP_Normal;
log_sample(instance, &cooked_time, 1, second, offset);
log_sample(instance, &cooked_time, 0, 1, offset + correction - instance->offset, offset, dispersion);
/* for logging purposes */
if (!instance->driver->poll)
instance->driver_polled++;
return 1;
}
void
RCL_CycleLogFile(void)
{
if (logfile) {
fclose(logfile);
logfile = NULL;
logwrites = 0;
}
}
static int
valid_sample_time(RCL_Instance instance, struct timeval *tv)
{
@@ -458,7 +481,7 @@ pps_stratum(RCL_Instance instance, struct timeval *tv)
int is_synchronised, stratum, i;
double root_delay, root_dispersion;
NTP_Leap leap;
unsigned long ref_id;
uint32_t ref_id;
REF_GetReferenceParams(tv, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
@@ -470,7 +493,8 @@ pps_stratum(RCL_Instance instance, struct timeval *tv)
/* Or the current source is another PPS refclock */
for (i = 0; i < n_sources; i++) {
if (refclocks[i].ref_id == ref_id && refclocks[i].pps_rate)
if (refclocks[i].ref_id == ref_id &&
refclocks[i].pps_rate && refclocks[i].lock_ref == -1)
return stratum - 1;
}
@@ -499,29 +523,22 @@ poll_timeout(void *arg)
int sample_ok, stratum;
sample_ok = filter_get_sample(&inst->filter, &sample_time, &offset, &dispersion);
filter_reset(&inst->filter);
inst->driver_polled = 0;
if (sample_ok) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock filtered sample: offset=%.9f dispersion=%.9f [%s]",
offset, dispersion, UTI_TimevalToString(&sample_time));
#endif
if (inst->pps_rate)
if (inst->pps_rate && inst->lock_ref == -1)
/* Handle special case when PPS is used with local stratum */
stratum = pps_stratum(inst, &sample_time);
else
stratum = 0;
SRC_SetReachable(inst->source);
SRC_UpdateReachability(inst->source, 1);
SRC_AccumulateSample(inst->source, &sample_time, offset,
inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
inst->missed_samples = 0;
log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
} else {
inst->missed_samples++;
if (inst->missed_samples > 9)
SRC_UnsetReachable(inst->source);
SRC_UpdateReachability(inst->source, 0);
}
}
@@ -534,7 +551,7 @@ poll_timeout(void *arg)
}
static void
slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
double doffset, int is_step_change, void *anything)
{
int i;
@@ -544,30 +561,24 @@ slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, double a
}
static void
log_sample(RCL_Instance instance, struct timeval *sample_time, int pulse, double raw_offset, double cooked_offset)
add_dispersion(double dispersion, void *anything)
{
int i;
for (i = 0; i < n_sources; i++)
filter_add_dispersion(&refclocks[i].filter, dispersion);
}
static void
log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
{
char sync_stats[4] = {'N', '+', '-', '?'};
if (!logfilename)
if (logfileid == -1)
return;
if (!logfile) {
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_Refclock, "Couldn't open logfile %s for update", logfilename);
Free(logfilename);
logfilename = NULL;
return;
}
}
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"====================================================================\n"
" Date (UTC) Time Refid DP L P Raw offset Cooked offset\n"
"====================================================================\n");
}
fprintf(logfile, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e\n",
if (!filtered) {
LOG_FileWrite(logfileid, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
(int)sample_time->tv_usec,
UTI_RefidToString(instance->ref_id),
@@ -575,8 +586,17 @@ log_sample(RCL_Instance instance, struct timeval *sample_time, int pulse, double
sync_stats[instance->leap_status],
pulse,
raw_offset,
cooked_offset);
fflush(logfile);
cooked_offset,
dispersion);
} else {
LOG_FileWrite(logfileid, "%s.%06d %-5s - %1c - - %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
(int)sample_time->tv_usec,
UTI_RefidToString(instance->ref_id),
sync_stats[instance->leap_status],
cooked_offset,
dispersion);
}
}
static void
@@ -589,13 +609,24 @@ filter_init(struct MedianFilter *filter, int length)
filter->index = -1;
filter->used = 0;
filter->last = -1;
/* set first estimate to system precision */
filter->avg_var_n = 0;
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
filter->samples = MallocArray(struct FilterSample, filter->length);
filter->selected = MallocArray(int, filter->length);
filter->x_data = MallocArray(double, filter->length);
filter->y_data = MallocArray(double, filter->length);
filter->w_data = MallocArray(double, filter->length);
}
static void
filter_fini(struct MedianFilter *filter)
{
Free(filter->samples);
Free(filter->selected);
Free(filter->x_data);
Free(filter->y_data);
Free(filter->w_data);
}
static void
@@ -605,8 +636,14 @@ filter_reset(struct MedianFilter *filter)
filter->used = 0;
}
static double
filter_get_avg_sample_dispersion(struct MedianFilter *filter)
{
return sqrt(filter->avg_var);
}
static void
filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset)
filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion)
{
filter->index++;
filter->index %= filter->length;
@@ -616,23 +653,30 @@ filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
filter->samples[filter->index].sample_time = *sample_time;
filter->samples[filter->index].offset = offset;
filter->samples[filter->index].dispersion = dispersion;
}
static int
filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset)
filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
{
if (filter->last < 0)
return 0;
*sample_time = filter->samples[filter->last].sample_time;
*offset = filter->samples[filter->last].offset;
*dispersion = filter->samples[filter->last].dispersion;
return 1;
}
static const struct FilterSample *tmp_sorted_array;
static int
sample_compare(const void *a, const void *b)
{
const struct FilterSample *s1 = a, *s2 = b;
const struct FilterSample *s1, *s2;
s1 = &tmp_sorted_array[*(int *)a];
s2 = &tmp_sorted_array[*(int *)b];
if (s1->offset < s2->offset)
return -1;
@@ -641,54 +685,183 @@ sample_compare(const void *a, const void *b)
return 0;
}
int
filter_select_samples(struct MedianFilter *filter)
{
int i, j, k, o, from, to, *selected;
double min_dispersion;
if (filter->used < 1)
return 0;
/* for lengths below 4 require full filter,
for 4 and above require at least 4 samples */
if ((filter->length < 4 && filter->used != filter->length) ||
(filter->length >= 4 && filter->used < 4))
return 0;
selected = filter->selected;
if (filter->used > 4) {
/* select samples with dispersion better than 1.5 * minimum */
for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
if (min_dispersion > filter->samples[i].dispersion)
min_dispersion = filter->samples[i].dispersion;
}
for (i = j = 0; i < filter->used; i++) {
if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
selected[j++] = i;
}
} else {
j = 0;
}
if (j < 4) {
/* select all samples */
for (j = 0; j < filter->used; j++)
selected[j] = j;
}
/* and sort their indices by offset */
tmp_sorted_array = filter->samples;
qsort(selected, j, sizeof (int), sample_compare);
/* select 60 percent of the samples closest to the median */
if (j > 2) {
from = j / 5;
if (from < 1)
from = 1;
to = j - from;
} else {
from = 0;
to = j;
}
/* mark unused samples and sort the rest from oldest to newest */
o = filter->used - filter->index - 1;
for (i = 0; i < from; i++)
selected[i] = -1;
for (; i < to; i++)
selected[i] = (selected[i] + o) % filter->used;
for (; i < filter->used; i++)
selected[i] = -1;
for (i = from; i < to; i++) {
j = selected[i];
selected[i] = -1;
while (j != -1 && selected[j] != j) {
k = selected[j];
selected[j] = j;
j = k;
}
}
for (i = j = 0, k = -1; i < filter->used; i++) {
if (selected[i] != -1)
selected[j++] = (selected[i] + filter->used - o) % filter->used;
}
return j;
}
static int
filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
{
if (filter->used == 0)
struct FilterSample *s, *ls;
int i, n, dof;
double x, y, d, e, var, prev_avg_var;
n = filter_select_samples(filter);
if (n < 1)
return 0;
if (filter->used == 1) {
*sample_time = filter->samples[filter->index].sample_time;
*offset = filter->samples[filter->index].offset;
*dispersion = 0.0;
} else {
int i, from, to;
double x, x1, y, d;
ls = &filter->samples[filter->selected[n - 1]];
/* sort samples by offset */
qsort(filter->samples, filter->used, sizeof (struct FilterSample), sample_compare);
/* prepare data */
for (i = 0; i < n; i++) {
s = &filter->samples[filter->selected[i]];
/* average the half of the samples closest to the median */
if (filter->used > 2) {
from = (filter->used + 2) / 4;
to = filter->used - from;
} else {
from = 0;
to = filter->used;
UTI_DiffTimevalsToDouble(&filter->x_data[i], &s->sample_time, &ls->sample_time);
filter->y_data[i] = s->offset;
filter->w_data[i] = s->dispersion;
}
for (i = from, x = y = 0.0; i < to; i++) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock averaging offset %.9f [%s]",
filter->samples[i].offset, UTI_TimevalToString(&filter->samples[i].sample_time));
#endif
UTI_DiffTimevalsToDouble(&x1, &filter->samples[i].sample_time, &filter->samples[0].sample_time);
x += x1;
y += filter->samples[i].offset;
/* mean offset, sample time and sample dispersion */
for (i = 0, x = y = e = 0.0; i < n; i++) {
x += filter->x_data[i];
y += filter->y_data[i];
e += filter->w_data[i];
}
x /= n;
y /= n;
e /= n;
e -= sqrt(filter->avg_var);
if (n >= 4) {
double b0, b1, s2, sb0, sb1;
/* set y axis to the mean sample time */
for (i = 0; i < n; i++)
filter->x_data[i] -= x;
/* make a linear fit and use the estimated standard deviation of intercept
as dispersion */
RGR_WeightedRegression(filter->x_data, filter->y_data, filter->w_data, n,
&b0, &b1, &s2, &sb0, &sb1);
var = s2;
d = sb0;
dof = n - 2;
} else if (n >= 2) {
for (i = 0, d = 0.0; i < n; i++)
d += (filter->y_data[i] - y) * (filter->y_data[i] - y);
var = d / (n - 1);
d = sqrt(var);
dof = n - 1;
} else {
var = filter->avg_var;
d = sqrt(var);
dof = 1;
}
x /= to - from;
y /= to - from;
/* avoid having zero dispersion */
if (var < 1e-20) {
var = 1e-20;
d = sqrt(var);
}
for (i = from, d = 0.0; i < to; i++)
d += (filter->samples[i].offset - y) * (filter->samples[i].offset - y);
prev_avg_var = filter->avg_var;
d = sqrt(d / (to - from));
/* update exponential moving average of the variance */
if (filter->avg_var_n > 50) {
filter->avg_var += dof / (dof + 50.0) * (var - filter->avg_var);
} else {
filter->avg_var = (filter->avg_var * filter->avg_var_n + var * dof) /
(dof + filter->avg_var_n);
if (filter->avg_var_n == 0)
prev_avg_var = filter->avg_var;
filter->avg_var_n += dof;
}
UTI_AddDoubleToTimeval(&filter->samples[0].sample_time, x, sample_time);
/* reduce noise in sourcestats weights by using the long-term average
instead of the estimated variance if it's not significantly lower */
if (var * dof / RGR_GetChi2Coef(dof) < prev_avg_var)
d = sqrt(filter->avg_var) * d / sqrt(var);
if (d < e)
d = e;
UTI_AddDoubleToTimeval(&ls->sample_time, x, sample_time);
*offset = y;
*dispersion = d;
}
filter_reset(filter);
return 1;
}
@@ -697,21 +870,29 @@ static void
filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset)
{
int i;
double elapsed, delta_time, prev_offset;
double delta_time, prev_offset;
struct timeval *sample;
for (i = 0; i < filter->used; i++) {
sample = &filter->samples[i].sample_time;
UTI_DiffTimevalsToDouble(&elapsed, when, sample);
delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(sample, delta_time, sample);
UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
prev_offset = filter->samples[i].offset;
filter->samples[i].offset -= delta_time;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "i=%d old_off=%.9f new_off=%.9f",
i, prev_offset, filter->samples[i].offset);
#else
(void)prev_offset;
#endif
}
}
static void
filter_add_dispersion(struct MedianFilter *filter, double dispersion)
{
int i;
for (i = 0; i < filter->used; i++) {
filter->samples[i].dispersion += dispersion;
}
}

View File

@@ -32,16 +32,18 @@
#include "sources.h"
typedef struct {
char driver_name[4];
char *driver_name;
char *driver_parameter;
int driver_poll;
int poll;
int filter_length;
int pps_rate;
unsigned long ref_id;
unsigned long lock_ref_id;
uint32_t ref_id;
uint32_t lock_ref_id;
double offset;
double delay;
double precision;
SRC_SelectOption sel_option;
} RefclockParameters;
typedef struct RCL_Instance_Record *RCL_Instance;
@@ -58,14 +60,13 @@ extern int RCL_AddRefclock(RefclockParameters *params);
extern void RCL_StartRefclocks(void);
extern void RCL_StartRefclocks(void);
extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
extern void RCL_CycleLogFile(void);
/* functions used by drivers */
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
extern void *RCL_GetDriverData(RCL_Instance instance);
extern char *RCL_GetDriverParameter(RCL_Instance instance);
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap);
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
#endif

View File

@@ -25,11 +25,17 @@
*/
#include "config.h"
#include "refclock.h"
#if HAVE_PPSAPI
#if defined(HAVE_SYS_TIMEPPS_H)
#include <sys/timepps.h>
#elif defined(HAVE_TIMEPPS_H)
#include <timepps.h>
#endif
#include "logging.h"
#include "memory.h"
@@ -57,6 +63,8 @@ static int pps_initialise(RCL_Instance instance) {
return 0;
}
UTI_FdSetCloexec(fd);
if (time_pps_create(fd, &handle) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_create() failed on %s", path);
return 0;
@@ -93,6 +101,7 @@ static int pps_initialise(RCL_Instance instance) {
return 0;
}
pps = MallocNew(struct pps_instance);
pps->handle = handle;
pps->last_seq = 0;

View File

@@ -25,6 +25,8 @@
*/
#include "config.h"
#include "refclock.h"
#include "logging.h"
#include "util.h"
@@ -43,7 +45,7 @@ struct shmTime {
* use values
* clear valid
*/
int count;
volatile int count;
time_t clockTimeStampSec;
int clockTimeStampUSec;
time_t receiveTimeStampSec;
@@ -51,8 +53,10 @@ struct shmTime {
int leap;
int precision;
int nsamples;
int valid;
int dummy[10];
volatile int valid;
int clockTimeStampNSec;
int receiveTimeStampNSec;
int dummy[8];
};
static int shm_initialise(RCL_Instance instance) {
@@ -87,7 +91,7 @@ static void shm_finalise(RCL_Instance instance)
static int shm_poll(RCL_Instance instance)
{
struct timeval tv1, tv2;
struct timeval tv;
struct shmTime t, *shm;
double offset;
@@ -105,13 +109,17 @@ static int shm_poll(RCL_Instance instance)
shm->valid = 0;
tv1.tv_sec = t.receiveTimeStampSec;
tv1.tv_usec = t.receiveTimeStampUSec;
tv2.tv_sec = t.clockTimeStampSec;
tv2.tv_usec = t.clockTimeStampUSec;
tv.tv_sec = t.receiveTimeStampSec;
tv.tv_usec = t.receiveTimeStampUSec;
UTI_DiffTimevalsToDouble(&offset, &tv2, &tv1);
return RCL_AddSample(instance, &tv1, offset, t.leap);
offset = t.clockTimeStampSec - t.receiveTimeStampSec;
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 = {

View File

@@ -25,6 +25,8 @@
*/
#include "config.h"
#include "refclock.h"
#include "logging.h"
#include "util.h"
@@ -105,6 +107,8 @@ static int sock_initialise(RCL_Instance instance)
return 0;
}
UTI_FdSetCloexec(sockfd);
unlink(path);
if (bind(sockfd, (struct sockaddr *)&s, sizeof (s)) < 0) {
LOG_FATAL(LOGF_Refclock, "bind() failed");

View File

@@ -1,13 +1,9 @@
/*
$Header: /cvs/src/chrony/reference.c,v 1.42 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009-2012
*
* 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
@@ -29,6 +25,8 @@
This module keeps track of the source which we are claiming to be
our reference, for the purposes of generating outgoing NTP packets */
#include "config.h"
#include "sysincl.h"
#include "memory.h"
@@ -37,7 +35,7 @@
#include "conf.h"
#include "logging.h"
#include "local.h"
#include "mkdirpp.h"
#include "sched.h"
/* ================================================== */
@@ -47,10 +45,9 @@ static int local_stratum;
static NTP_Leap our_leap_status;
static int our_leap_sec;
static int our_stratum;
static unsigned long our_ref_id;
static uint32_t our_ref_id;
static IPAddr our_ref_ip;
struct timeval our_ref_time; /* Stored relative to reference, NOT local time */
static double our_offset;
static double our_skew;
static double our_residual_freq;
static double our_root_delay;
@@ -58,6 +55,12 @@ static double our_root_dispersion;
static double max_update_skew;
static double last_offset;
static double avg2_offset;
static int avg2_moving;
static double correction_time_ratio;
/* Flag indicating that we are initialised */
static int initialised = 0;
@@ -65,6 +68,12 @@ static int initialised = 0;
static int make_step_limit;
static double make_step_threshold;
/* Number of updates before offset checking, number of ignored updates
before exiting and the maximum allowed offset */
static int max_offset_delay;
static int max_offset_ignore;
static double max_offset;
/* Flag and threshold for logging clock changes to syslog */
static int do_log_change;
static double log_change_threshold;
@@ -76,18 +85,18 @@ static char *mail_change_user;
/* Filename of the drift file. */
static char *drift_file=NULL;
static double drift_file_age;
static void update_drift_file(double, double);
#define MAIL_PROGRAM "/usr/lib/sendmail"
/* Name of a system timezone containing leap seconds occuring at midnight */
static char *leap_tzname;
static time_t last_tz_leap_check;
static NTP_Leap tz_leap;
/* ================================================== */
/* File to which statistics are logged, NULL if none */
static FILE *logfile = NULL;
static char *logfilename = NULL;
static unsigned long logwrites = 0;
#define TRACKING_LOG "tracking.log"
static LOG_FileID logfileid;
/* ================================================== */
@@ -96,10 +105,49 @@ static unsigned long logwrites = 0;
/* ================================================== */
/* Exponential moving averages of absolute clock frequencies
used as a fallback when synchronisation is lost. */
struct fb_drift {
double freq;
double secs;
};
static int fb_drift_min;
static int fb_drift_max;
static struct fb_drift *fb_drifts = NULL;
static int next_fb_drift;
static SCH_TimeoutID fb_drift_timeout_id;
/* Timestamp of last reference update */
static struct timeval last_ref_update;
static double last_ref_update_interval;
/* ================================================== */
static NTP_Leap get_tz_leap(time_t when);
/* ================================================== */
static void
handle_slew(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double doffset,
int is_step_change,
void *anything)
{
if (is_step_change) {
UTI_AddDoubleToTimeval(&last_ref_update, -doffset, &last_ref_update);
}
}
/* ================================================== */
void
REF_Initialise(void)
{
char *direc;
FILE *in;
char line[1024];
double file_freq_ppm, file_skew_ppm;
@@ -114,6 +162,7 @@ REF_Initialise(void)
our_frequency_ppm = 0.0;
our_skew = 1.0; /* i.e. rather bad */
our_residual_freq = 0.0;
drift_file_age = 0.0;
/* Now see if we can get the drift file opened */
drift_file = CNF_GetDriftFile();
@@ -125,6 +174,8 @@ REF_Initialise(void)
/* We have read valid data */
our_frequency_ppm = file_freq_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);
LCL_SetAbsoluteFrequency(our_frequency_ppm);
} else {
LOG(LOGS_WARN, LOGF_Reference, "Could not parse valid frequency and skew from driftfile %s",
drift_file);
@@ -134,46 +185,66 @@ REF_Initialise(void)
drift_file);
}
fclose(in);
} else {
LOG(LOGS_WARN, LOGF_Reference, "Could not open driftfile %s for reading",
drift_file);
}
}
update_drift_file(our_frequency_ppm,our_skew);
if (our_frequency_ppm == 0.0) {
our_frequency_ppm = LCL_ReadAbsoluteFrequency();
if (our_frequency_ppm != 0.0) {
LOG(LOGS_INFO, LOGF_Reference, "Initial frequency %.3f ppm", our_frequency_ppm);
}
}
LCL_SetAbsoluteFrequency(our_frequency_ppm);
if (CNF_GetLogTracking()) {
direc = CNF_GetLogDir();
if (!mkdir_and_parents(direc)) {
LOG(LOGS_ERR, LOGF_Reference, "Could not create directory %s", direc);
logfile = NULL;
} else {
logfilename = MallocArray(char, 2 + strlen(direc) + strlen(TRACKING_LOG));
strcpy(logfilename, direc);
strcat(logfilename, "/");
strcat(logfilename, TRACKING_LOG);
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_Reference, "Couldn't open logfile %s for update", logfilename);
}
}
}
logfileid = CNF_GetLogTracking() ? LOG_FileOpen("tracking",
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset L")
: -1;
max_update_skew = fabs(CNF_GetMaxUpdateSkew()) * 1.0e-6;
correction_time_ratio = CNF_GetCorrectionTimeRatio();
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
leap_tzname = CNF_GetLeapSecTimezone();
if (leap_tzname) {
/* Check that the timezone has good data for Jun 30 2008 and Dec 31 2008 */
if (get_tz_leap(1214784000) == LEAP_Normal &&
get_tz_leap(1230681600) == LEAP_InsertSecond) {
LOG(LOGS_INFO, LOGF_Reference, "Using %s timezone to obtain leap second data", leap_tzname);
} else {
LOG(LOGS_WARN, LOGF_Reference, "Timezone %s failed leap second check, ignoring", leap_tzname);
leap_tzname = NULL;
}
}
CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
CNF_GetMaxChange(&max_offset_delay, &max_offset_ignore, &max_offset);
CNF_GetLogChange(&do_log_change, &log_change_threshold);
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
CNF_GetFallbackDrifts(&fb_drift_min, &fb_drift_max);
if (fb_drift_max >= fb_drift_min && fb_drift_min > 0) {
fb_drifts = MallocArray(struct fb_drift, fb_drift_max - fb_drift_min + 1);
memset(fb_drifts, 0, sizeof (struct fb_drift) * (fb_drift_max - fb_drift_min + 1));
next_fb_drift = 0;
fb_drift_timeout_id = -1;
}
last_ref_update.tv_sec = 0;
last_ref_update.tv_usec = 0;
last_ref_update_interval = 0.0;
LCL_AddParameterChangeHandler(handle_slew, NULL);
/* And just to prevent anything wierd ... */
if (do_log_change) {
log_change_threshold = fabs(log_change_threshold);
}
/* Make first entry in tracking log */
REF_SetUnsynchronised();
return;
}
@@ -186,10 +257,12 @@ REF_Finalise(void)
LCL_SetLeap(0);
}
if (logfile) {
fclose(logfile);
if (drift_file && drift_file_age > 0.0) {
update_drift_file(LCL_ReadAbsoluteFrequency(), our_skew);
}
Free(fb_drifts);
initialised = 0;
return;
}
@@ -241,9 +314,12 @@ update_drift_file(double freq_ppm, double skew)
}
/* Write the frequency and skew parameters in ppm */
fprintf(out, "%20.4f %20.4f\n", freq_ppm, 1.0e6 * skew);
fclose(out);
if ((fprintf(out, "%20.4f %20.4f\n", freq_ppm, 1.0e6 * skew) < 0) |
fclose(out)) {
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. */
@@ -269,6 +345,117 @@ update_drift_file(double freq_ppm, double skew)
/* ================================================== */
static void
update_fb_drifts(double freq_ppm, double update_interval)
{
int i, secs;
assert(are_we_synchronised);
if (next_fb_drift > 0) {
#if 0
/* Reset drifts that were used when we were unsynchronised */
for (i = 0; i < next_fb_drift - fb_drift_min; i++)
fb_drifts[i].secs = 0.0;
#endif
next_fb_drift = 0;
}
if (fb_drift_timeout_id != -1) {
SCH_RemoveTimeout(fb_drift_timeout_id);
fb_drift_timeout_id = -1;
}
if (update_interval < 0.0 || update_interval > last_ref_update_interval * 4.0)
return;
for (i = 0; i < fb_drift_max - fb_drift_min + 1; i++) {
/* Don't allow differences larger than 10 ppm */
if (fabs(freq_ppm - fb_drifts[i].freq) > 10.0)
fb_drifts[i].secs = 0.0;
secs = 1 << (i + fb_drift_min);
if (fb_drifts[i].secs < secs) {
/* Calculate average over 2 * secs interval before switching to
exponential updating */
fb_drifts[i].freq = (fb_drifts[i].freq * fb_drifts[i].secs +
update_interval * 0.5 * freq_ppm) / (update_interval * 0.5 + fb_drifts[i].secs);
fb_drifts[i].secs += update_interval * 0.5;
} else {
/* Update exponential moving average. The smoothing factor for update
interval equal to secs is about 0.63, for half interval about 0.39,
for double interval about 0.86. */
fb_drifts[i].freq += (1 - 1.0 / exp(update_interval / secs)) *
(freq_ppm - fb_drifts[i].freq);
}
#if 0
LOG(LOGS_INFO, LOGF_Reference, "Fallback drift %d updated: %f ppm %f seconds",
i + fb_drift_min, fb_drifts[i].freq, fb_drifts[i].secs);
#endif
}
}
/* ================================================== */
static void
fb_drift_timeout(void *arg)
{
assert(are_we_synchronised == 0);
assert(next_fb_drift >= fb_drift_min && next_fb_drift <= fb_drift_max);
fb_drift_timeout_id = -1;
LCL_SetAbsoluteFrequency(fb_drifts[next_fb_drift - fb_drift_min].freq);
REF_SetUnsynchronised();
}
/* ================================================== */
static void
schedule_fb_drift(struct timeval *now)
{
int i, c, secs;
double unsynchronised;
struct timeval when;
if (fb_drift_timeout_id != -1)
return; /* already scheduled */
UTI_DiffTimevalsToDouble(&unsynchronised, now, &last_ref_update);
for (c = secs = 0, i = fb_drift_min; i <= fb_drift_max; i++) {
secs = 1 << i;
if (fb_drifts[i - fb_drift_min].secs < secs)
continue;
if (unsynchronised < secs && i > next_fb_drift)
break;
c = i;
}
if (c > next_fb_drift) {
LCL_SetAbsoluteFrequency(fb_drifts[c - fb_drift_min].freq);
next_fb_drift = c;
#if 0
LOG(LOGS_INFO, LOGF_Reference, "Fallback drift %d set", c);
#endif
}
if (i <= fb_drift_max) {
next_fb_drift = i;
UTI_AddDoubleToTimeval(now, secs - unsynchronised, &when);
fb_drift_timeout_id = SCH_AddTimeout(&when, fb_drift_timeout, NULL);
#if 0
LOG(LOGS_INFO, LOGF_Reference, "Fallback drift %d scheduled", i);
#endif
}
}
/* ================================================== */
#define BUFLEN 255
#define S_MAX_USER_LEN "128"
@@ -336,20 +523,109 @@ maybe_make_step()
/* ================================================== */
static void
update_leap_status(NTP_Leap leap)
static int
is_offset_ok(double offset)
{
if (max_offset_delay < 0)
return 1;
if (max_offset_delay > 0) {
max_offset_delay--;
return 1;
}
offset = fabs(offset);
if (offset > max_offset) {
LOG(LOGS_WARN, LOGF_Reference,
"Adjustment of %.3f seconds exceeds the allowed maximum of %.3f seconds (%s) ",
offset, max_offset, !max_offset_ignore ? "exiting" : "ignored");
if (!max_offset_ignore)
SCH_QuitProgram();
else if (max_offset_ignore > 0)
max_offset_ignore--;
return 0;
}
return 1;
}
/* ================================================== */
static NTP_Leap
get_tz_leap(time_t when)
{
struct tm stm;
time_t t;
char *tz_env, tz_orig[128];
/* Do this check at most twice a day */
when = when / (12 * 3600) * (12 * 3600);
if (last_tz_leap_check == when)
return tz_leap;
last_tz_leap_check = when;
tz_leap = LEAP_Normal;
stm = *gmtime(&when);
/* Check for leap second only in the latter half of June and December */
if (stm.tm_mon == 5 && stm.tm_mday > 14)
stm.tm_mday = 30;
else if (stm.tm_mon == 11 && stm.tm_mday > 14)
stm.tm_mday = 31;
else
return tz_leap;
/* Temporarily switch to the timezone containing leap seconds */
tz_env = getenv("TZ");
if (tz_env) {
if (strlen(tz_env) >= sizeof (tz_orig))
return tz_leap;
strcpy(tz_orig, tz_env);
}
setenv("TZ", leap_tzname, 1);
tzset();
/* Set the time to 23:59:60 and see how it overflows in mktime() */
stm.tm_sec = 60;
stm.tm_min = 59;
stm.tm_hour = 23;
t = mktime(&stm);
if (tz_env)
setenv("TZ", tz_orig, 1);
else
unsetenv("TZ");
tzset();
if (t == -1)
return tz_leap;
if (stm.tm_sec == 60)
tz_leap = LEAP_InsertSecond;
else if (stm.tm_sec == 1)
tz_leap = LEAP_DeleteSecond;
return tz_leap;
}
/* ================================================== */
static void
update_leap_status(NTP_Leap leap, time_t now)
{
time_t now;
struct tm stm;
int leap_sec;
leap_sec = 0;
if (leap_tzname && now && leap == LEAP_Normal)
leap = get_tz_leap(now);
if (leap == LEAP_InsertSecond || leap == LEAP_DeleteSecond) {
/* Insert/delete leap second only on June 30 or December 31
and in other months ignore the leap status completely */
now = time(NULL);
stm = *gmtime(&now);
if (stm.tm_mon != 5 && stm.tm_mon != 11) {
@@ -375,21 +651,12 @@ update_leap_status(NTP_Leap leap)
/* ================================================== */
static void
write_log(struct timeval *ref_time, char *ref, int stratum, 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)
{
if (logfile) {
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"=======================================================================\n"
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset\n"
"=======================================================================\n");
}
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew, offset);
fflush(logfile);
const char leap_codes[4] = {'N', '+', '-', '?'};
if (logfileid != -1) {
LOG_FileWrite(logfileid, "%s %-15s %2d %10.3f %10.3f %10.3e %1c",
UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew, offset, leap_codes[leap]);
}
}
@@ -398,10 +665,11 @@ write_log(struct timeval *ref_time, char *ref, int stratum, double freq, double
void
REF_SetReference(int stratum,
NTP_Leap leap,
unsigned long ref_id,
uint32_t ref_id,
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
double offset_sd,
double frequency,
double skew,
double root_delay,
@@ -413,17 +681,21 @@ REF_SetReference(int stratum,
double old_weight, new_weight, sum_weight;
double delta_freq1, delta_freq2;
double skew1, skew2;
double our_offset;
double our_frequency;
double abs_freq_ppm;
double update_interval;
double elapsed;
double correction_rate;
struct timeval now, raw_now;
assert(initialised);
/* Avoid getting NaNs */
if (skew == 0.0)
skew = 1e-10;
if (our_skew == 0.0)
our_skew = 1e-10;
if (skew < 1e-12)
skew = 1e-12;
if (our_skew < 1e-12)
our_skew = 1e-12;
/* If we get a serious rounding error in the source stats regression
processing, there is a remote chance that the skew argument is a
@@ -443,6 +715,14 @@ REF_SetReference(int stratum,
}
}
LCL_ReadRawTime(&raw_now);
LCL_CookTime(&raw_now, &now, NULL);
UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time);
our_offset = offset + elapsed * frequency;
if (!is_offset_ok(offset))
return;
are_we_synchronised = 1;
our_stratum = stratum + 1;
@@ -452,11 +732,34 @@ REF_SetReference(int stratum,
else
our_ref_ip.family = IPADDR_UNSPEC;
our_ref_time = *ref_time;
our_offset = offset;
our_root_delay = root_delay;
our_root_dispersion = root_dispersion;
update_leap_status(leap);
update_leap_status(leap, raw_now.tv_sec);
if (last_ref_update.tv_sec) {
UTI_DiffTimevalsToDouble(&update_interval, &now, &last_ref_update);
if (update_interval < 0.0)
update_interval = 0.0;
} else {
update_interval = 0.0;
}
last_ref_update = now;
/* We want to correct the offset quickly, but we also want to keep the
frequency error caused by the correction itself low.
Define correction rate as the area of the region bounded by the graph of
offset corrected in time. Set the rate so that the time needed to correct
an offset equal to the current sourcestats stddev will be equal to the
update interval multiplied by the correction time ratio (assuming linear
adjustment). The offset and the time needed to make the correction are
inversely proportional.
This is only a suggestion and it's up to the system driver how the
adjustment will be executed. */
correction_rate = correction_time_ratio * 0.5 * offset_sd * update_interval;
/* Eliminate updates that are based on totally unreliable frequency
information */
@@ -492,7 +795,7 @@ REF_SetReference(int stratum,
our_residual_freq = new_freq - our_frequency;
maybe_log_offset(our_offset);
LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset);
LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset, correction_rate);
} else {
@@ -500,7 +803,7 @@ REF_SetReference(int stratum,
LOG(LOGS_INFO, LOGF_Reference, "Skew %f too large to track, offset=%f", skew, our_offset);
#endif
maybe_log_offset(our_offset);
LCL_AccumulateOffset(our_offset);
LCL_AccumulateOffset(our_offset, correction_rate);
our_residual_freq = frequency;
}
@@ -509,15 +812,38 @@ REF_SetReference(int stratum,
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
write_log(ref_time,
write_log(&now,
our_ref_ip.family != IPADDR_UNSPEC ? UTI_IPToString(&our_ref_ip) : UTI_RefidToString(our_ref_id),
our_stratum,
our_leap_status,
abs_freq_ppm,
1.0e6*our_skew,
our_offset);
if (drift_file) {
/* Update drift file at most once per hour */
drift_file_age += update_interval;
if (drift_file_age < 0.0 || drift_file_age > 3600.0) {
update_drift_file(abs_freq_ppm, our_skew);
drift_file_age = 0.0;
}
}
/* Update fallback drifts */
if (fb_drifts) {
update_fb_drifts(abs_freq_ppm, update_interval);
}
last_ref_update_interval = update_interval;
last_offset = our_offset;
/* Update the moving average of squares of offset, quickly on start */
if (avg2_moving) {
avg2_offset += 0.1 * (our_offset * our_offset - avg2_offset);
} else {
if (avg2_offset > 0.0 && avg2_offset < our_offset * our_offset)
avg2_moving = 1;
avg2_offset = our_offset * our_offset;
}
/* And now set the freq and offset to zero */
@@ -549,7 +875,7 @@ REF_SetManualReference
our_residual_freq = 0.0;
maybe_log_offset(offset);
LCL_AccumulateFrequencyAndOffset(frequency, offset);
LCL_AccumulateFrequencyAndOffset(frequency, offset, 0.0);
maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
@@ -557,9 +883,10 @@ REF_SetManualReference
write_log(ref_time,
"127.127.1.1",
our_stratum,
our_leap_status,
abs_freq_ppm,
1.0e6*our_skew,
our_offset);
offset);
if (drift_file) {
update_drift_file(abs_freq_ppm, our_skew);
@@ -573,22 +900,25 @@ REF_SetUnsynchronised(void)
{
/* Variables required for logging to statistics log */
struct timeval now;
double local_clock_err;
assert(initialised);
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, NULL);
if (fb_drifts) {
schedule_fb_drift(&now);
}
update_leap_status(LEAP_Unsynchronised, 0);
are_we_synchronised = 0;
write_log(&now,
"0.0.0.0",
0,
our_leap_status,
LCL_ReadAbsoluteFrequency(),
1.0e6*our_skew,
0.0);
are_we_synchronised = 0;
update_leap_status(LEAP_Unsynchronised);
}
/* ================================================== */
@@ -600,7 +930,7 @@ REF_GetReferenceParams
int *is_synchronised,
NTP_Leap *leap_status,
int *stratum,
unsigned long *ref_id,
uint32_t *ref_id,
struct timeval *ref_time,
double *root_delay,
double *root_dispersion
@@ -618,7 +948,7 @@ REF_GetReferenceParams
*stratum = our_stratum;
UTI_DiffTimevalsToDouble(&elapsed, local_time, &our_ref_time);
extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed;
extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed;
*leap_status = our_leap_status;
*ref_id = our_ref_id;
@@ -653,7 +983,7 @@ REF_GetReferenceParams
*leap_status = LEAP_Unsynchronised;
*stratum = 0;
*ref_id = 0UL;
*ref_id = 0;
ref_time->tv_sec = ref_time->tv_usec = 0;
/* These values seem to be standard for a client, and
any peer or client of ours will ignore them anyway because
@@ -725,20 +1055,34 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
double correction;
LCL_ReadRawTime(&now_raw);
correction = LCL_GetOffsetCorrection(&now_raw);
LCL_GetOffsetCorrection(&now_raw, &correction, NULL);
UTI_AddDoubleToTimeval(&now_raw, correction, &now_cooked);
rep->ref_id = 0;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = 0;
rep->leap_status = our_leap_status;
rep->ref_time.tv_sec = 0;
rep->ref_time.tv_usec = 0;
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0;
rep->root_delay = 0.0;
rep->root_dispersion = 0.0;
rep->last_update_interval = last_ref_update_interval;
rep->last_offset = last_offset;
rep->rms_offset = sqrt(avg2_offset);
if (are_we_synchronised) {
UTI_DiffTimevalsToDouble(&elapsed, &now_cooked, &our_ref_time);
extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed;
extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed;
rep->ref_id = our_ref_id;
rep->ip_addr = our_ref_ip;
rep->stratum = our_stratum;
rep->ref_time = our_ref_time;
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 1.0e6 * our_residual_freq;
rep->skew_ppm = 1.0e6 * our_skew;
rep->root_delay = our_root_delay;
@@ -750,43 +1094,9 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = local_stratum;
rep->ref_time = now_cooked;
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0;
rep->root_delay = 0.0;
rep->root_dispersion = LCL_GetSysPrecisionAsQuantum();
} else {
rep->ref_id = 0UL;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = 0;
rep->ref_time.tv_sec = 0;
rep->ref_time.tv_usec = 0;
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0;
rep->root_delay = 0.0;
rep->root_dispersion = 0.0;
}
}
/* ================================================== */
void
REF_CycleLogFile(void)
{
if (logfile && logfilename) {
fclose(logfile);
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_Reference, "Could not reopen logfile %s", logfilename);
}
logwrites = 0;
}
}
/* ================================================== */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/reference.h,v 1.13 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -75,7 +71,7 @@ extern void REF_GetReferenceParams
int *is_synchronised,
NTP_Leap *leap,
int *stratum,
unsigned long *ref_id,
uint32_t *ref_id,
struct timeval *ref_time,
double *root_delay,
double *root_dispersion
@@ -109,10 +105,11 @@ extern void REF_SetReference
(
int stratum,
NTP_Leap leap,
unsigned long ref_id,
uint32_t ref_id,
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
double offset_sd,
double frequency,
double skew,
double root_delay,
@@ -144,6 +141,4 @@ extern int REF_IsLocalActive(void);
extern void REF_GetTrackingReport(RPT_TrackingReport *rep);
extern void REF_CycleLogFile(void);
#endif /* GOT_REFERENCE_H */

125
regress.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/regress.c,v 1.32 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011
*
* 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
@@ -29,6 +26,8 @@
*/
#include "config.h"
#include <assert.h>
#include <math.h>
@@ -69,9 +68,7 @@ RGR_WeightedRegression
double u, ui, aa;
int i;
if (n<3) {
CROAK("Insufficient points");
}
assert(n >= 3);
W = U = 0;
for (i=0; i<n; i++) {
@@ -135,6 +132,30 @@ RGR_GetTCoef(int dof)
}
}
/* ================================================== */
/* Get 90% quantile of chi-square distribution */
double
RGR_GetChi2Coef(int dof)
{
static double coefs[] = {
2.706, 4.605, 6.251, 7.779, 9.236, 10.645, 12.017, 13.362,
14.684, 15.987, 17.275, 18.549, 19.812, 21.064, 22.307, 23.542,
24.769, 25.989, 27.204, 28.412, 29.615, 30.813, 32.007, 33.196,
34.382, 35.563, 36.741, 37.916, 39.087, 40.256, 41.422, 42.585,
43.745, 44.903, 46.059, 47.212, 48.363, 49.513, 50.660, 51.805,
52.949, 54.090, 55.230, 56.369, 57.505, 58.641, 59.774, 60.907,
62.038, 63.167, 64.295, 65.422, 66.548, 67.673, 68.796, 69.919,
71.040, 72.160, 73.279, 74.397, 75.514, 76.630, 77.745, 78.860
};
if (dof <= 64) {
return coefs[dof-1];
} else {
return 1.2 * dof; /* Until I can be bothered to do something better */
}
}
/* ================================================== */
/* Structure used for holding results of each regression */
@@ -150,23 +171,23 @@ typedef struct {
} RegressionResult;
/* ================================================== */
/* Critical value for number of runs of residuals with same sign. 10%
critical region for now */
/* Critical value for number of runs of residuals with same sign.
5% critical region for now. */
static int critical_runs10[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 3,
4, 4, 4, 4, 5, 5, 6, 6, 7, 7,
7, 8, 8, 9, 9, 10, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 14, 15, 15, 16,
16, 17, 17, 18, 18, 18, 19, 19, 20, 20,
/* Note that 66 onwards are bogus - I haven't worked out the
critical values */
21, 21, 22, 22, 23, 23, 23, 24, 24, 25,
25, 26, 26, 27, 27, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28
static char critical_runs[] = {
0, 0, 0, 0, 0, 0, 0, 0, 2, 3,
3, 3, 4, 4, 5, 5, 5, 6, 6, 7,
7, 7, 8, 8, 9, 9, 9, 10, 10, 11,
11, 11, 12, 12, 13, 13, 14, 14, 14, 15,
15, 16, 16, 17, 17, 18, 18, 18, 19, 19,
20, 20, 21, 21, 21, 22, 22, 23, 23, 24,
24, 25, 25, 26, 26, 26, 27, 27, 28, 28,
29, 29, 30, 30, 30, 31, 31, 32, 32, 33,
33, 34, 34, 35, 35, 35, 36, 36, 37, 37,
38, 38, 39, 39, 40, 40, 40, 41, 41, 42,
42, 43, 43, 44, 44, 45, 45, 46, 46, 46,
47, 47, 48, 48, 49, 49, 50, 50, 51, 51,
52, 52, 52, 53, 53, 54, 54, 55, 55, 56
};
/* ================================================== */
@@ -194,7 +215,6 @@ n_runs_from_residuals(double *resid, int n)
/* Return a boolean indicating whether we had enough points for
regression */
#define RESID_SIZE 1024
#define MIN_SAMPLES_FOR_REGRESS 3
int
@@ -205,6 +225,9 @@ RGR_FindBestRegression
less reliable) */
int n, /* number of data points */
int m, /* number of extra samples in x and y arrays
(negative index) which can be used to
extend runs test */
/* And now the results */
@@ -228,13 +251,16 @@ RGR_FindBestRegression
)
{
double P, Q, U, V, W; /* total */
double resid[RESID_SIZE];
double resid[MAX_POINTS * REGRESS_RUNS_RATIO];
double ss;
double a, b, u, ui, aa;
int start, nruns, npoints, npoints_left;
int start, resid_start, nruns, npoints;
int i;
assert(n <= MAX_POINTS);
assert(n * REGRESS_RUNS_RATIO < sizeof (critical_runs) / sizeof (critical_runs[0]));
if (n < MIN_SAMPLES_FOR_REGRESS) {
return 0;
}
@@ -258,20 +284,26 @@ RGR_FindBestRegression
V += ui * ui / w[i];
}
npoints = n - start;
b = Q / V;
a = (P / W) - (b * u);
for (i=start; i<n; i++) {
resid[i] = y[i] - a - b*x[i];
/* Get residuals also for the extra samples before start */
resid_start = n - (n - start) * REGRESS_RUNS_RATIO;
if (resid_start < -m)
resid_start = -m;
for (i=resid_start; i<n; i++) {
resid[i - resid_start] = y[i] - a - b*x[i];
}
/* Count number of runs */
nruns = n_runs_from_residuals(resid + start, npoints);
nruns = n_runs_from_residuals(resid, n - resid_start);
npoints_left = n - start - 1;
if ((nruns > critical_runs10[npoints]) || (npoints_left < MIN_SAMPLES_FOR_REGRESS)) {
if (nruns > critical_runs[n - resid_start] || n - start <= MIN_SAMPLES_FOR_REGRESS) {
if (start != resid_start) {
/* Ignore extra samples in returned nruns */
nruns = n_runs_from_residuals(resid - resid_start + start, n - start);
}
break;
} else {
/* Try dropping one sample at a time until the runs test passes. */
@@ -286,7 +318,7 @@ RGR_FindBestRegression
ss = 0.0;
for (i=start; i<n; i++) {
ss += resid[i]*resid[i] / w[i];
ss += resid[i - resid_start]*resid[i - resid_start] / w[i];
}
npoints = n - start;
@@ -332,9 +364,7 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
double piv;
int pivind;
if (index < 0) {
CROAK("Negative index");
}
assert(index >= 0);
/* If this bit of the array is already sorted, simple! */
if (flags[index]) {
@@ -378,8 +408,6 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
v = r - 1;
} else if (index > r) {
u = l;
} else {
CROAK("Impossible");
}
}
} while (1);
@@ -498,6 +526,8 @@ RGR_FindBestRobustRegression
double mx, dx, my, dy;
int nruns = 0;
assert(n < MAX_POINTS);
if (n < 2) {
return 0;
} else if (n == 2) {
@@ -558,7 +588,7 @@ RGR_FindBestRobustRegression
Estimate standard deviation of b and expand range about b based
on that. */
sb = sqrt(s2 * W/V);
if (sb > 0.0) {
if (sb > tol) {
incr = 3.0 * sb;
} else {
incr = 3.0 * tol;
@@ -568,6 +598,11 @@ RGR_FindBestRobustRegression
bhi = b;
do {
/* Make sure incr is significant to blo and bhi */
while (bhi + incr == bhi || blo - incr == blo) {
incr *= 2;
}
blo -= incr;
bhi += incr;
@@ -575,8 +610,8 @@ RGR_FindBestRobustRegression
eval_robust_residual(x + start, y + start, n_points, blo, &a, &rlo);
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
in interval. */
} while (rlo * rhi >= 0.0); /* fn vals have same sign or one is zero,
i.e. root not in interval (rlo, rhi). */
/* OK, so the root for b lies in (blo, bhi). Start bisecting */
do {
@@ -591,9 +626,9 @@ RGR_FindBestRobustRegression
bhi = bmid;
rhi = rmid;
} else {
CROAK("Impossible");
assert(0);
}
} while ((bhi - blo) > tol);
} while ((bhi - blo) > tol && (bmid - blo) * (bhi - bmid) > 0.0);
*b0 = a;
*b1 = bmid;
@@ -610,7 +645,7 @@ RGR_FindBestRobustRegression
nruns = n_runs_from_residuals(resids + start, n_points);
if (nruns > critical_runs10[n_points]) {
if (nruns > critical_runs[n_points]) {
break;
} else {
start++;

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/regress.h,v 1.13 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -61,6 +57,15 @@ RGR_WeightedRegression
extern double RGR_GetTCoef(int dof);
/* Return the value to apply to the variance to make an upper one-sided
test assuming a chi-square distribution. */
extern double RGR_GetChi2Coef(int dof);
/* Maximum ratio of number of points used for runs test to number of regression
points */
#define REGRESS_RUNS_RATIO 2
/* Return a status indicating whether there were enough points to
carry out the regression */
@@ -72,6 +77,9 @@ RGR_FindBestRegression
less reliable) */
int n, /* number of data points */
int m, /* number of extra samples in x and y arrays
(negative index) which can be used to
extend runs test */
/* And now the results */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/reports.h,v 1.17 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -41,8 +37,10 @@ typedef struct {
int stratum;
int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_OTHER} state;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE} state;
enum {RPT_NORMAL, RPT_PREFER, RPT_NOSELECT} sel_option;
int reachability;
unsigned long latest_meas_ago; /* seconds */
double orig_latest_meas; /* seconds */
double latest_meas; /* seconds */
@@ -50,20 +48,24 @@ typedef struct {
} RPT_SourceReport ;
typedef struct {
unsigned long ref_id;
uint32_t ref_id;
IPAddr ip_addr;
unsigned long stratum;
unsigned long leap_status;
struct timeval ref_time;
double current_correction;
double last_offset;
double rms_offset;
double freq_ppm;
double resid_freq_ppm;
double skew_ppm;
double root_delay;
double root_dispersion;
double last_update_interval;
} RPT_TrackingReport;
typedef struct {
unsigned long ref_id;
uint32_t ref_id;
IPAddr ip_addr;
unsigned long n_samples;
unsigned long n_runs;
@@ -117,6 +119,7 @@ typedef struct {
int offline;
int burst_online;
int burst_offline;
int unresolved;
} RPT_ActivityReport;
#endif /* GOT_REPORTS_H */

25
rtc.c
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/rtc.c,v 1.14 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -27,6 +23,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "rtc.h"
@@ -50,7 +48,6 @@ static struct {
int (*write_parameters)(void);
int (*get_report)(RPT_RTC_Report *report);
int (*trim)(void);
void (*cycle_logfile)(void);
} driver =
{
#if defined LINUX && defined FEAT_RTC
@@ -61,8 +58,7 @@ static struct {
RTC_Linux_StartMeasurements,
RTC_Linux_WriteParameters,
RTC_Linux_GetReport,
RTC_Linux_Trim,
RTC_Linux_CycleLogFile
RTC_Linux_Trim
#else
NULL,
NULL,
@@ -71,7 +67,6 @@ static struct {
NULL,
NULL,
NULL,
NULL,
NULL
#endif
};
@@ -89,6 +84,10 @@ RTC_Initialise(void)
file_name = CNF_GetRtcFile();
if (file_name) {
if (CNF_GetRTCSync()) {
LOG_FATAL(LOGF_Rtc, "rtcfile directive cannot be used with rtcsync");
}
if (driver.init) {
if ((driver.init)()) {
ok = 1;
@@ -210,13 +209,3 @@ RTC_Trim(void)
/* ================================================== */
void
RTC_CycleLogFile(void)
{
if (driver_initialised) {
(driver.cycle_logfile)();
}
}
/* ================================================== */

6
rtc.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/rtc.h,v 1.9 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -47,6 +43,4 @@ extern int RTC_WriteParameters(void);
extern int RTC_Trim(void);
extern void RTC_CycleLogFile(void);
#endif /* GOT_RTC_H */

View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/rtc_linux.c,v 1.32 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012
*
* 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
@@ -30,6 +27,8 @@
*/
#include "config.h"
#if defined LINUX
#ifdef sparc
@@ -49,6 +48,7 @@
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <linux/rtc.h>
#include "logging.h"
#include "sched.h"
@@ -58,22 +58,8 @@
#include "regress.h"
#include "rtc.h"
#include "rtc_linux.h"
#include "io_linux.h"
#include "conf.h"
#include "memory.h"
#include "mkdirpp.h"
struct rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
/* ================================================== */
/* Forward prototypes */
@@ -180,11 +166,7 @@ static int rtc_on_utc = 1;
/* ================================================== */
static FILE *logfile=NULL;
static char *logfilename = NULL;
static unsigned long logwrites=0;
#define RTC_LOG "rtc.log"
static LOG_FileID logfileid;
/* ================================================== */
@@ -198,12 +180,7 @@ discard_samples(int new_first)
{
int n_to_save;
if (!(new_first < n_samples)) {
CROAK("new_first should be < n_samples");
}
if (!(new_first >= 0)) {
CROAK("new_first should be non-negative");
}
assert(new_first >= 0 && new_first < n_samples);
n_to_save = n_samples - new_first;
@@ -258,14 +235,12 @@ run_regression(int new_sample,
{
double rtc_rel[MAX_SAMPLES]; /* Relative times on RTC axis */
double offsets[MAX_SAMPLES]; /* How much the RTC is fast of the system clock */
int i, n;
int i;
double est_intercept, est_slope;
int best_new_start;
if (n_samples > 0) {
n = n_samples - 1;
for (i=0; i<n_samples; i++) {
rtc_rel[i] = rtc_trim[i] + (double)(rtc_sec[i] - rtc_ref);
offsets[i] = ((double) (rtc_ref - system_times[i].tv_sec) -
@@ -307,27 +282,17 @@ run_regression(int new_sample,
static void
slew_samples
(struct timeval *raw, struct timeval *cooked,
double dfreq, double afreq_ppm,
double dfreq,
double doffset, int is_step_change,
void *anything)
{
int i;
double elapsed;
double new_freq;
double old_freq;
double delta_time;
double old_seconds_fast, old_gain_rate;
new_freq = 1.0e-6 * afreq_ppm;
old_freq = (new_freq - dfreq) / (1.0 - dfreq);
for (i=0; i<n_samples; i++) {
UTI_DiffTimevalsToDouble(&elapsed, cooked, system_times + i);
delta_time = -(elapsed * dfreq) - doffset;
UTI_AddDoubleToTimeval(system_times + i, delta_time, system_times + i);
UTI_AdjustTimeval(system_times + i, cooked, system_times + i, &delta_time,
dfreq, doffset);
}
old_seconds_fast = coef_seconds_fast;
@@ -335,14 +300,16 @@ slew_samples
if (coefs_valid) {
coef_seconds_fast += doffset;
coef_gain_rate = 1.0 - ((1.0 + new_freq) / (1.0 + old_freq)) * (1.0 - coef_gain_rate);
coef_gain_rate = (1.0 + dfreq) * (1.0 + coef_gain_rate) - 1.0;
}
#if 0
LOG(LOGS_INFO, LOGF_RtcLinux, "dfreq=%.8f doffset=%.6f new_freq=%.3f old_freq=%.3f old_fast=%.6f old_rate=%.3f new_fast=%.6f new_rate=%.3f",
dfreq, doffset, 1.0e6*new_freq, 1.0e6*old_freq,
LOG(LOGS_INFO, LOGF_RtcLinux, "dfreq=%.8f doffset=%.6f old_fast=%.6f old_rate=%.3f new_fast=%.6f new_rate=%.3f",
dfreq, doffset,
old_seconds_fast, 1.0e6 * old_gain_rate,
coef_seconds_fast, 1.0e6 * coef_gain_rate);
#else
(void)old_seconds_fast; (void)old_gain_rate;
#endif
}
@@ -503,10 +470,13 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
}
/* Gain rate is written out in ppm */
fprintf(out, "%1d %ld %.6f %.3f\n",
valid,ref_time, offset, 1.0e6 * rate);
fclose(out);
if ((fprintf(out, "%1d %ld %.6f %.3f\n",
valid,ref_time, offset, 1.0e6 * rate) < 0) |
fclose(out)) {
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. */
@@ -541,63 +511,6 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
int
RTC_Linux_Initialise(void)
{
int major, minor, patch;
char *direc;
/* Check whether we can support the real time clock.
Linux 1.2.x - haven't checked yet
Linux 1.3.x - don't know, haven't got a system to look at
Linux 2.0.x - For x<=31, using any variant of the adjtimex() call
sets the kernel into a mode where the RTC was updated every 11
minutes. The only way to escape this is to use settimeofday().
Since we need to have sole control over the RTC to be able to
measure its drift rate, and there is no 'notify' callback to warn
you that the kernel is going to do this, I can't see a way to
support this.
Linux 2.0.x - For x>=32 the adjtimex()/RTC behaviour was
modified, so that as long as the STA_UNSYNC flag is set the RTC
is left alone. This is the mode we exploit here, so that the RTC
continues to go its own sweet way, unless we make updates to it
from this module.
Linux 2.1.x - don't know, haven't got a system to look at.
Linux 2.2.x, 2.3.x and 2.4.x are believed to be OK for all
patch levels
*/
SYS_Linux_GetKernelVersion(&major, &minor, &patch);
/* Obviously this test can get more elaborate when we know about
more system types. */
if (major != 2) {
return 0;
} else {
switch (minor) {
case 0:
if (patch <= 31) {
return 0;
}
break;
case 1:
return 0;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
break; /* OK for all patch levels */
}
}
/* Setup details depending on configuration options */
setup_config();
@@ -612,6 +525,9 @@ RTC_Linux_Initialise(void)
return 0;
}
/* Close on exec */
UTI_FdSetCloexec(fd);
n_samples = 0;
n_samples_since_regression = 0;
n_runs = 0;
@@ -627,18 +543,9 @@ RTC_Linux_Initialise(void)
/* Register slew handler */
LCL_AddParameterChangeHandler(slew_samples, NULL);
if (CNF_GetLogRtc()) {
direc = CNF_GetLogDir();
if (!mkdir_and_parents(direc)) {
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not create directory %s", direc);
} else {
logfilename = MallocArray(char, 2 + strlen(direc) + strlen(RTC_LOG));
strcpy(logfilename, direc);
strcat(logfilename, "/");
strcat(logfilename, RTC_LOG);
}
}
logfileid = CNF_GetLogRtc() ? LOG_FileOpen("rtc",
" Date (UTC) Time RTC fast (s) Val Est fast (s) Slope (ppm) Ns Nr Meas")
: -1;
return 1;
}
@@ -661,11 +568,6 @@ RTC_Linux_Finalise(void)
(void) RTC_Linux_WriteParameters();
}
if (logfile) {
fclose(logfile);
}
Free(logfilename);
}
/* ================================================== */
@@ -717,6 +619,9 @@ set_rtc(time_t new_rtc_time)
rtc_raw.tm_mday = rtc_tm.tm_mday;
rtc_raw.tm_mon = rtc_tm.tm_mon;
rtc_raw.tm_year = rtc_tm.tm_year;
rtc_raw.tm_wday = rtc_tm.tm_wday;
rtc_raw.tm_yday = rtc_tm.tm_yday;
rtc_raw.tm_isdst = rtc_tm.tm_isdst;
status = ioctl(fd, RTC_SET_TIME, &rtc_raw);
if (status < 0) {
@@ -763,7 +668,7 @@ handle_initial_trim(void)
sys_error_now = rtc_error_now - coef_seconds_fast;
LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now);
LCL_AccumulateOffset(sys_error_now);
LCL_AccumulateOffset(sys_error_now, 0.0);
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time");
}
@@ -794,6 +699,7 @@ handle_relock_after_trim(void)
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not do regression after trim");
}
coefs_valid = 0;
n_samples = 0;
n_samples_since_regression = 0;
operating_mode = OM_NORMAL;
@@ -832,38 +738,19 @@ process_reading(time_t rtc_time, struct timeval *system_time)
}
break;
default:
CROAK("Impossible");
assert(0);
break;
}
if (logfilename) {
if (!logfile) {
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Couldn't open logfile %s for update", logfilename);
Free(logfilename);
logfilename = NULL;
return;
}
}
if (logfileid != -1) {
rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec;
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"===============================================================================\n"
" Date (UTC) Time RTC fast (s) Val Est fast (s) Slope (ppm) Ns Nr Meas\n"
"===============================================================================\n");
}
fprintf(logfile, "%s %14.6f %1d %14.6f %12.3f %2d %2d %4d\n",
LOG_FileWrite(logfileid, "%s %14.6f %1d %14.6f %12.3f %2d %2d %4d",
UTI_TimeToLogForm(system_time->tv_sec),
rtc_fast,
coefs_valid,
coef_seconds_fast, coef_gain_rate * 1.0e6, n_samples, n_runs, measurement_period);
fflush(logfile);
}
}
@@ -892,10 +779,6 @@ read_from_device(void *any)
switch_interrupts(0); /* Likely to raise error too, but just to be sure... */
close(fd);
fd = -1;
if (logfile) {
fclose(logfile);
logfile = NULL;
}
return;
}
@@ -905,13 +788,13 @@ read_from_device(void *any)
return;
}
if ((data & RTC_UIE) == RTC_UIE) {
if ((data & RTC_UF) == RTC_UF) {
/* Update interrupt detected */
/* Read RTC time, sandwiched between two polls of the system clock
so we can bound any error. */
SCH_GetFileReadyTime(&sys_time);
SCH_GetFileReadyTime(&sys_time, NULL);
status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status < 0) {
@@ -990,7 +873,7 @@ turn_off_interrupt:
break;
default:
CROAK("Impossible");
assert(0);
break;
}
@@ -1056,7 +939,7 @@ RTC_Linux_TimePreInit(void)
time_t rtc_t, estimated_correct_rtc_t;
long interval;
double accumulated_error = 0.0;
struct timeval new_sys_time;
struct timeval new_sys_time, old_sys_time;
coefs_file_name = CNF_GetRtcFile();
@@ -1091,8 +974,6 @@ RTC_Linux_TimePreInit(void)
accumulated_error = file_ref_offset + (double)(interval) * 1.0e-6 * file_rate_ppm;
/* Correct time */
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
accumulated_error);
estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
} else {
estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
@@ -1101,10 +982,19 @@ RTC_Linux_TimePreInit(void)
new_sys_time.tv_sec = estimated_correct_rtc_t;
new_sys_time.tv_usec = 0;
/* Set system time only if the step is larger than 1 second */
if (!(gettimeofday(&old_sys_time, NULL) < 0) &&
(old_sys_time.tv_sec - new_sys_time.tv_sec > 1 ||
old_sys_time.tv_sec - new_sys_time.tv_sec < -1)) {
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
accumulated_error);
/* Tough luck if this fails */
if (settimeofday(&new_sys_time, NULL) < 0) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not settimeofday");
}
}
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
}
@@ -1139,7 +1029,6 @@ int
RTC_Linux_Trim(void)
{
struct timeval now;
double local_clock_err;
/* Remember the slope coefficient - we won't be able to determine a
@@ -1158,7 +1047,7 @@ RTC_Linux_Trim(void)
want |E| <= 0.5, which implies R <= S <= R+1, i.e. R is just
the rounded down part of S, i.e. the seconds part. */
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, NULL);
set_rtc(now.tv_sec);
@@ -1167,6 +1056,11 @@ RTC_Linux_Trim(void)
n_samples = 0;
operating_mode = OM_AFTERTRIM;
/* Estimate the offset in case writertc is called or chronyd
is terminated during rapid sampling */
coef_seconds_fast = -now.tv_usec / 1e6 + 0.5;
coef_ref_time = now.tv_sec;
/* And start rapid sampling, interrupts on now */
if (timeout_running) {
SCH_RemoveTimeout(timeout_id);
@@ -1181,16 +1075,4 @@ RTC_Linux_Trim(void)
/* ================================================== */
void
RTC_Linux_CycleLogFile(void)
{
if (logfile) {
fclose(logfile);
logfile = NULL;
logwrites = 0;
}
}
/* ================================================== */
#endif /* defined LINUX */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/rtc_linux.h,v 1.13 2002/02/28 23:27:13 richard Exp $
======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

223
sched.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/sched.c,v 1.17 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011
*
* 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
@@ -29,6 +26,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "sched.h"
@@ -71,8 +70,9 @@ typedef struct {
static FileHandlerEntry file_handlers[FD_SET_SIZE];
/* Last timestamp when a file descriptor became readable */
static struct timeval last_fdready;
/* Timestamp when last select() returned */
static struct timeval last_select_ts, last_select_ts_raw;
static double last_select_ts_err;
/* ================================================== */
@@ -109,6 +109,9 @@ static SCH_TimeoutID next_tqe_id;
/* Pointer to head of free list */
static TimerQueueEntry *tqe_free_list = NULL;
/* Timestamp when was last timeout dispatched for each class */
static struct timeval last_class_dispatch[SCH_NumberOfClasses];
/* ================================================== */
static int need_to_exit;
@@ -119,7 +122,6 @@ static void
handle_slew(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *anything);
@@ -129,6 +131,7 @@ handle_slew(struct timeval *raw,
void
SCH_Initialise(void)
{
struct timeval tv;
FD_ZERO(&read_fds);
n_read_fds = 0;
@@ -143,6 +146,9 @@ SCH_Initialise(void)
LCL_AddParameterChangeHandler(handle_slew, NULL);
LCL_ReadRawTime(&tv);
srandom(tv.tv_sec << 16 ^ tv.tv_usec);
initialised = 1;
return;
@@ -164,16 +170,12 @@ SCH_AddInputFileHandler
(int fd, SCH_FileHandler handler, SCH_ArbitraryArgument arg)
{
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
/* Don't want to allow the same fd to register a handler more than
once without deleting a previous association - this suggests
a bug somewhere else in the program. */
if (FD_ISSET(fd, &read_fds)) {
CROAK("File handler already registered");
}
assert(!FD_ISSET(fd, &read_fds));
++n_read_fds;
@@ -197,14 +199,10 @@ SCH_RemoveInputFileHandler(int fd)
{
int fds_left, fd_to_check;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
/* Check that a handler was registered for the fd in question */
if (!FD_ISSET(fd, &read_fds)) {
CROAK("File handler not registered");
}
assert(FD_ISSET(fd, &read_fds));
--n_read_fds;
@@ -229,9 +227,11 @@ SCH_RemoveInputFileHandler(int fd)
/* ================================================== */
void
SCH_GetFileReadyTime(struct timeval *tv)
SCH_GetFileReadyTime(struct timeval *tv, double *err)
{
*tv = last_fdready;
*tv = last_select_ts;
if (err)
*err = last_select_ts_err;
}
/* ================================================== */
@@ -276,9 +276,7 @@ SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler handler, SCH_ArbitraryArgu
TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
new_tqe = allocate_tqe();
@@ -319,9 +317,8 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
{
struct timeval now, then;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
assert(delay >= 0.0);
LCL_ReadRawTime(&now);
UTI_AddDoubleToTimeval(&now, delay, &then);
@@ -332,23 +329,35 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
/* ================================================== */
SCH_TimeoutID
SCH_AddTimeoutInClass(double min_delay, double separation,
SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
{
TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr;
struct timeval now;
double diff;
double diff, r;
double new_min_delay;
if (!initialised) {
CROAK("Should be initialised");
assert(initialised);
assert(min_delay >= 0.0);
assert(class < SCH_NumberOfClasses);
if (randomness > 0.0) {
r = random() % 0xffff / (0xffff - 1.0) * randomness + 1.0;
min_delay *= r;
separation *= r;
}
LCL_ReadRawTime(&now);
new_min_delay = min_delay;
/* Check the separation from the last dispatched timeout */
UTI_DiffTimevalsToDouble(&diff, &now, &last_class_dispatch[class]);
if (diff < separation && diff >= 0.0 && diff + new_min_delay < separation) {
new_min_delay = separation - diff;
}
/* Scan through list for entries in the same class and increase min_delay
if necessary to keep at least the separation away */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
@@ -358,8 +367,7 @@ SCH_AddTimeoutInClass(double min_delay, double separation,
if (new_min_delay - diff < separation) {
new_min_delay = diff + separation;
}
}
if (new_min_delay < diff) {
} else {
if (diff - new_min_delay < separation) {
new_min_delay = diff + separation;
}
@@ -398,13 +406,8 @@ void
SCH_RemoveTimeout(SCH_TimeoutID id)
{
TimerQueueEntry *ptr;
int ok;
if (!initialised) {
CROAK("Should be initialised");
}
ok = 0;
assert(initialised);
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
@@ -421,48 +424,57 @@ SCH_RemoveTimeout(SCH_TimeoutID id)
/* Release memory back to the operating system */
release_tqe(ptr);
ok = 1;
break;
}
}
assert(ok);
}
/* ================================================== */
/* The current time (now) has to be passed in from the
caller to avoid race conditions */
/* Try to dispatch any timeouts that have already gone by, and
keep going until all are done. (The earlier ones may take so
long to do that the later ones come around by the time they are
completed). */
static int
static void
dispatch_timeouts(struct timeval *now) {
TimerQueueEntry *ptr;
int n_done = 0;
SCH_TimeoutHandler handler;
SCH_ArbitraryArgument arg;
int n_done = 0, n_entries_on_start = n_timer_queue_entries;
while (1) {
LCL_ReadRawTime(now);
if (!(n_timer_queue_entries > 0 &&
UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
break;
}
if ((n_timer_queue_entries > 0) &&
(UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
ptr = timer_queue.next;
last_class_dispatch[ptr->class] = *now;
handler = ptr->handler;
arg = ptr->arg;
SCH_RemoveTimeout(ptr->id);
/* Dispatch the handler */
(ptr->handler)(ptr->arg);
(handler)(arg);
/* Increment count of timeouts handled */
++n_done;
/* Unlink entry from the queue */
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
/* Decrement count of entries in queue */
--n_timer_queue_entries;
/* Delete entry */
release_tqe(ptr);
/* If more timeouts were handled than there were in the timer queue on
start and there are now, assume some code is scheduling timeouts with
negative delays and abort. Make the actual limit higher in case the
machine is temporarily overloaded and dispatching the handlers takes
more time than was delay of a scheduled timeout. */
if (n_done > n_timer_queue_entries * 4 &&
n_done > n_entries_on_start * 4) {
LOG_FATAL(LOGF_Scheduler, "Possible infinite loop in scheduling");
}
}
return n_done;
}
/* ================================================== */
@@ -495,13 +507,12 @@ static void
handle_slew(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *anything)
{
TimerQueueEntry *ptr;
struct timeval T1;
int i;
if (is_step_change) {
/* We're not interested in anything else - it won't affect the
@@ -509,11 +520,44 @@ handle_slew(struct timeval *raw,
occurs, just shift all the timeouts by the offset */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &T1);
ptr->tv = T1;
UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &ptr->tv);
}
for (i = 0; i < SCH_NumberOfClasses; i++) {
UTI_AddDoubleToTimeval(&last_class_dispatch[i], -doffset, &last_class_dispatch[i]);
}
UTI_AddDoubleToTimeval(&last_select_ts_raw, -doffset, &last_select_ts_raw);
UTI_AddDoubleToTimeval(&last_select_ts, -doffset, &last_select_ts);
}
}
/* ================================================== */
/* Try to handle unexpected backward time jump */
static void
recover_backjump(struct timeval *raw, struct timeval *cooked, int timeout)
{
double diff, err;
UTI_DiffTimevalsToDouble(&diff, &last_select_ts_raw, raw);
if (n_timer_queue_entries > 0) {
UTI_DiffTimevalsToDouble(&err, &(timer_queue.next->tv), &last_select_ts_raw);
} else {
err = 0.0;
}
diff += err;
if (timeout) {
err = 1.0;
}
LOG(LOGS_WARN, LOGF_Scheduler, "Backward time jump detected! (correction %.1f +- %.1f seconds)", diff, err);
LCL_NotifyExternalTimeStep(raw, cooked, diff, err);
}
/* ================================================== */
@@ -524,32 +568,25 @@ SCH_MainLoop(void)
fd_set rd;
int status;
struct timeval tv, *ptv;
struct timeval now;
struct timeval now, cooked;
double err;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
while (!need_to_exit) {
/* Copy current set of read file descriptors */
memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
/* Try to dispatch any timeouts that have already gone by, and
keep going until all are done. (The earlier ones may take so
long to do that the later ones come around by the time they are
completed). */
do {
LCL_ReadRawTime(&now);
} while (dispatch_timeouts(&now) > 0);
/* Dispatch timeouts and fill now with current raw time */
dispatch_timeouts(&now);
/* Check whether there is a timeout and set it up */
if (n_timer_queue_entries > 0) {
UTI_DiffTimevals(&tv, &(timer_queue.next->tv), &now);
ptv = &tv;
assert(tv.tv_sec > 0 || tv.tv_usec > 0);
} else {
ptv = NULL;
@@ -564,25 +601,31 @@ SCH_MainLoop(void)
status = select(one_highest_fd, &rd, NULL, NULL, ptv);
LCL_ReadRawTime(&now);
LCL_CookTime(&now, &cooked, &err);
/* Check if time didn't jump backwards */
if (last_select_ts_raw.tv_sec > now.tv_sec + 1) {
recover_backjump(&now, &cooked, status == 0);
}
last_select_ts_raw = now;
last_select_ts = cooked;
last_select_ts_err = err;
if (status < 0) {
if (!need_to_exit)
CROAK("Status < 0 after select");
assert(need_to_exit);
} else if (status > 0) {
/* A file descriptor is ready to read */
LCL_ReadCookedTime(&last_fdready, &err);
dispatch_filehandlers(status, &rd);
} else {
if (status != 0) {
CROAK("Unexpected value from select");
}
assert(status == 0);
/* No descriptors readable, timeout must have elapsed.
Therefore, tv must be non-null */
if (!ptv) {
CROAK("No descriptors or timeout?");
}
assert(ptv);
/* There's nothing to do here, since the timeouts
will be dispatched at the top of the next loop
@@ -600,9 +643,7 @@ SCH_MainLoop(void)
void
SCH_QuitProgram(void)
{
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
need_to_exit = 1;
}

21
sched.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sched.h,v 1.10 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -35,10 +31,12 @@
typedef unsigned long SCH_TimeoutID;
typedef unsigned long SCH_TimeoutClass;
static const SCH_TimeoutClass SCH_ReservedTimeoutValue = 0;
static const SCH_TimeoutClass SCH_NtpSamplingClass = 1;
static const SCH_TimeoutClass SCH_NtpBroadcastClass = 2;
typedef enum {
SCH_ReservedTimeoutValue = 0,
SCH_NtpSamplingClass,
SCH_NtpBroadcastClass,
SCH_NumberOfClasses /* needs to be last */
} SCH_TimeoutClass;
typedef void* SCH_ArbitraryArgument;
typedef void (*SCH_FileHandler)(SCH_ArbitraryArgument);
@@ -62,7 +60,7 @@ extern void SCH_RemoveInputFileHandler(int fd);
/* Get the time (cooked) when file descriptor became ready, intended for use
in file handlers */
extern void SCH_GetFileReadyTime(struct timeval *tv);
extern void SCH_GetFileReadyTime(struct timeval *tv, double *err);
/* This queues a timeout to elapse at a given (raw) local time */
extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);
@@ -72,8 +70,9 @@ extern SCH_TimeoutID SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler, SCH
/* This queues a timeout in a particular class, ensuring that the
expiry time is at least a given separation away from any other
timeout in the same class */
extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation,
timeout in the same class, given randomness is added to the delay
and separation */
extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument);

480
sources.c
View File

@@ -1,12 +1,9 @@
/*
$Header: /cvs/src/chrony/sources.c,v 1.33 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012
*
* 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
@@ -31,6 +28,8 @@
*/
#include "config.h"
#include "sysincl.h"
#include "sources.h"
@@ -85,14 +84,16 @@ struct SRC_Instance_Record {
SST_Stats stats;
NTP_Leap leap_status; /* Leap status */
int index; /* Index back into the array of source */
unsigned long ref_id; /* The reference ID of this source
(i.e. its IP address, NOT the
uint32_t ref_id; /* The reference ID of this source
(i.e. from its IP address, NOT the
reference _it_ is sync'd to) */
IPAddr *ip_addr; /* Its IP address if NTP source */
/* Flag indicating that we are receiving packets with valid headers
from this source and can use it as a reference */
int reachable;
/* Flag indicating that we can use this source as a reference */
int selectable;
/* Reachability register */
int reachability;
/* Flag indicating the status of the source */
SRC_Status status;
@@ -100,6 +101,12 @@ struct SRC_Instance_Record {
/* Type of the source */
SRC_Type type;
/* Options used when selecting sources */
SRC_SelectOption sel_option;
/* Score against currently selected source */
double sel_score;
struct SelectInfo sel_info;
};
@@ -124,12 +131,23 @@ static int selected_source_index; /* Which source index is currently
selected (set to INVALID_SOURCE
if no current valid reference) */
/* Keep reachability status for last 8 samples */
#define REACH_BITS 8
/* Score needed to replace the currently selected source */
#define SCORE_LIMIT 10.0
static double reselect_distance;
static double stratum_weight;
/* ================================================== */
/* Forward prototype */
static void
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq,
double doffset, int is_step_change, void *anything);
static void
add_dispersion(double dispersion, void *anything);
static char *
source_to_string(SRC_Instance inst);
@@ -141,9 +159,12 @@ void SRC_Initialise(void) {
n_sources = 0;
max_n_sources = 0;
selected_source_index = INVALID_SOURCE;
reselect_distance = CNF_GetReselectDistance();
stratum_weight = CNF_GetStratumWeight();
initialised = 1;
LCL_AddParameterChangeHandler(slew_sources, NULL);
LCL_AddDispersionNotifyHandler(add_dispersion, NULL);
return;
}
@@ -153,6 +174,7 @@ void SRC_Initialise(void) {
void SRC_Finalise(void)
{
LCL_RemoveParameterChangeHandler(slew_sources, NULL);
LCL_RemoveDispersionNotifyHandler(add_dispersion, NULL);
initialised = 0;
return;
}
@@ -161,13 +183,11 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr)
{
SRC_Instance result;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
result = MallocNew(struct SRC_Instance_Record);
result->stats = SST_CreateInstance(ref_id, addr);
@@ -191,9 +211,12 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *
result->leap_status = LEAP_Normal;
result->ref_id = ref_id;
result->ip_addr = addr;
result->reachable = 0;
result->selectable = 0;
result->reachability = 0;
result->status = SRC_BAD_STATS;
result->type = type;
result->sel_score = 1.0;
result->sel_option = sel_option;
n_sources++;
@@ -210,14 +233,9 @@ void SRC_DestroyInstance(SRC_Instance instance)
{
int dead_index, i;
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
if (instance->index == selected_source_index) {
instance->reachable = 0;
SRC_SelectSource(0);
}
SRC_UnsetSelectable(instance);
SST_DeleteInstance(instance->stats);
dead_index = instance->index;
@@ -247,9 +265,7 @@ void SRC_DestroyInstance(SRC_Instance instance)
void SRC_GetFrequencyRange(SRC_Instance instance, double *lo, double *hi)
{
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
SST_GetFrequencyRange(instance->stats, lo, hi);
return;
@@ -280,9 +296,7 @@ void SRC_AccumulateSample
NTP_Leap leap_status)
{
if (!initialised) {
CROAK("Should be initialised");
}
assert(initialised);
inst->leap_status = leap_status;
@@ -304,9 +318,9 @@ void SRC_AccumulateSample
/* ================================================== */
void
SRC_SetReachable(SRC_Instance inst)
SRC_SetSelectable(SRC_Instance inst)
{
inst->reachable = 1;
inst->selectable = 1;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
@@ -319,9 +333,9 @@ SRC_SetReachable(SRC_Instance inst)
/* ================================================== */
void
SRC_UnsetReachable(SRC_Instance inst)
SRC_UnsetSelectable(SRC_Instance inst)
{
inst->reachable = 0;
inst->selectable = 0;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
@@ -338,6 +352,34 @@ SRC_UnsetReachable(SRC_Instance inst)
/* ================================================== */
void
SRC_UpdateReachability(SRC_Instance inst, int reachable)
{
inst->reachability <<= 1;
inst->reachability |= !!reachable;
inst->reachability &= ~(-1 << REACH_BITS);
if (!reachable && inst->index == selected_source_index) {
/* Try to select a better source */
SRC_SelectSource(0);
}
}
/* ================================================== */
void
SRC_ResetReachability(SRC_Instance inst)
{
/* This should be disabled until source selection is modified to keep
a peer selected even when not reachable */
#if 0
inst->reachability = 0;
SRC_UpdateReachability(inst, 0);
#endif
}
/* ================================================== */
static int
compare_sort_elements(const void *a, const void *b)
{
@@ -368,7 +410,7 @@ source_to_string(SRC_Instance inst)
case SRC_REFCLOCK:
return UTI_RefidToString(inst->ref_id);
default:
CROAK("Unknown source type");
assert(0);
}
return NULL;
}
@@ -377,51 +419,52 @@ source_to_string(SRC_Instance inst)
/* This function selects the current reference from amongst the pool
of sources we are holding.
Updates are only made to the local reference if match_addr is zero or is
equal to the selected reference source address */
Updates are only made to the local reference if a new source is selected
or match_refid is equal to the selected reference source refid */
void
SRC_SelectSource(unsigned long match_addr)
SRC_SelectSource(uint32_t match_refid)
{
int i, j, index;
struct timeval now;
double local_clock_err;
int src_select_ok;
int i, j, index, old_selected_index;
struct timeval now, ref_time;
double src_offset, src_offset_sd, src_frequency, src_skew;
double src_accrued_dispersion;
double src_root_delay, src_root_dispersion;
int n_endpoints, j1, j2;
double best_lo, best_hi;
int depth, best_depth;
int n_sel_sources;
double distance, min_distance;
double distance, sel_src_distance;
int stratum, min_stratum;
int min_distance_index;
struct SelectInfo *si;
double total_root_dispersion;
int n_reachable_sources;
int n_badstats_sources;
int max_sel_reach, max_badstat_reach;
int max_score_index;
double max_score;
NTP_Leap leap_status = LEAP_Normal;
old_selected_index = selected_source_index;
if (n_sources == 0) {
/* In this case, we clearly cannot synchronise to anything */
if (selected_source_index != INVALID_SOURCE) {
LOG(LOGS_INFO, LOGF_Sources, "Can't synchronise: no sources");
}
selected_source_index = INVALID_SOURCE;
REF_SetUnsynchronised();
}
return;
}
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, NULL);
/* Step 1 - build intervals about each source */
n_endpoints = 0;
n_reachable_sources = 0;
n_sel_sources = 0;
n_badstats_sources = 0;
max_sel_reach = max_badstat_reach = 0;
for (i=0; i<n_sources; i++) {
if (sources[i]->reachable) {
++n_reachable_sources;
if (sources[i]->selectable && sources[i]->reachability &&
sources[i]->sel_option != SRC_SelectNoselect) {
si = &(sources[i]->sel_info);
SST_GetSelectionData(sources[i]->stats, &now,
@@ -432,10 +475,6 @@ SRC_SelectSource(unsigned long match_addr)
&(si->variance),
&(si->select_ok));
/* Eventually this might be a flag indicating whether the get
selection data call was successful. For now it always is. */
src_select_ok = 1;
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;
@@ -447,7 +486,8 @@ SRC_SelectSource(unsigned long match_addr)
si->lo_limit, si->hi_limit);
#endif
if (src_select_ok) {
if (si->select_ok) {
++n_sel_sources;
sources[i]->status = SRC_OK; /* For now */
@@ -466,8 +506,16 @@ SRC_SelectSource(unsigned long match_addr)
n_endpoints += 2;
if (max_sel_reach < sources[i]->reachability) {
max_sel_reach = sources[i]->reachability;
}
} else {
++n_badstats_sources;
sources[i]->status = SRC_BAD_STATS;
if (max_badstat_reach < sources[i]->reachability) {
max_badstat_reach = sources[i]->reachability;
}
}
} else {
/* If the source is not reachable, there is no way we will pick
@@ -476,6 +524,23 @@ SRC_SelectSource(unsigned long match_addr)
}
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "badstat_sources=%d sel_sources=%d badstat_reach=%x sel_reach=%x",
n_badstats_sources, n_sel_sources, max_badstat_reach, max_sel_reach);
#endif
/* Wait for the next call if we have no source selected and there is
a source with bad stats (has less than 3 samples) with reachability
equal to shifted maximum reachability of sources with valid stats.
This delays selecting source on start with servers using the same
polling interval until they all have valid stats. */
if (n_badstats_sources && n_sel_sources &&
selected_source_index == INVALID_SOURCE &&
max_sel_reach >> 1 == max_badstat_reach) {
return;
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "n_endpoints=%d", n_endpoints);
#endif
@@ -527,7 +592,7 @@ SRC_SelectSource(unsigned long match_addr)
break;
case CENTRE:
CROAK("CENTRE cannot occur");
assert(0);
break;
case HIGH:
@@ -545,7 +610,7 @@ SRC_SelectSource(unsigned long match_addr)
best_depth, best_lo, best_hi);
#endif
if (best_depth <= n_reachable_sources/2) {
if (best_depth <= n_sel_sources/2) {
/* Could not even get half the reachable sources to agree -
clearly we can't synchronise.
@@ -561,7 +626,6 @@ SRC_SelectSource(unsigned long match_addr)
LOG(LOGS_INFO, LOGF_Sources, "Can't synchronise: no majority");
}
selected_source_index = INVALID_SOURCE;
REF_SetUnsynchronised();
/* .. and mark all sources as falsetickers (so they appear thus
on the outputs from the command client) */
@@ -600,6 +664,7 @@ SRC_SelectSource(unsigned long match_addr)
}
}
#if 0
/* We now have a list of indices for the sources which pass the
false-ticker test. Now go on to reject those whose variance is
greater than the minimum distance of any other */
@@ -619,11 +684,12 @@ SRC_SelectSource(unsigned long match_addr)
LOG(LOGS_INFO, LOGF_Sources, "min_distance=%f", min_distance);
#endif
/* Now go through and prune any sources that have excessive
/* Now go through and prune any NTP sources that have excessive
variance */
for (i=0; i<n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->sel_info.variance > min_distance) {
if (sources[index]->type == SRC_NTP &&
sqrt(sources[index]->sel_info.variance) > min_distance) {
sel_sources[i] = INVALID_SOURCE;
sources[index]->status = SRC_JITTERY;
#if 0
@@ -631,6 +697,7 @@ SRC_SelectSource(unsigned long match_addr)
#endif
}
}
#endif
/* Now crunch the list and mark all sources as selectable */
for (i=j=0; i<n_sel_sources; i++) {
@@ -643,77 +710,7 @@ SRC_SelectSource(unsigned long match_addr)
}
n_sel_sources = j;
/* Now find minimum stratum. If none are left now,
tough. RFC1305 is not so harsh on pruning sources due to
excess variance, which prevents this from happening */
if (n_sel_sources > 0) {
index = sel_sources[0];
min_stratum = sources[index]->sel_info.stratum;
for (i=1; i<n_sel_sources; i++) {
index = sel_sources[i];
stratum = sources[index]->sel_info.stratum;
if (stratum < min_stratum) min_stratum = stratum;
}
/* Find the best source with minimum stratum */
min_distance_index = INVALID_SOURCE;
for (i=0; i<n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->sel_info.stratum == min_stratum) {
if ((min_distance_index == INVALID_SOURCE) ||
(sources[index]->sel_info.root_distance < min_distance)) {
min_distance = sources[index]->sel_info.root_distance;
min_distance_index = index;
}
}
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "min_stratum=%d", min_stratum);
#endif
/* Does the current source have this stratum, doesn't have distance
much worse than the best source and is it still a survivor? */
if ((selected_source_index == INVALID_SOURCE) ||
(sources[selected_source_index]->status != SRC_SELECTABLE) ||
(sources[selected_source_index]->sel_info.stratum > min_stratum) ||
(sources[selected_source_index]->sel_info.root_distance > 10 * min_distance)) {
/* We have to elect a new synchronisation source */
selected_source_index = min_distance_index;
LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
source_to_string(sources[selected_source_index]));
#if 0
LOG(LOGS_INFO, LOGF_Sources, "new_sel_index=%d", min_distance_index);
#endif
} else {
/* We retain the existing sync source, see p40 of RFC1305b.ps */
#if 0
LOG(LOGS_INFO, LOGF_Sources, "existing reference retained", min_distance_index);
#endif
}
sources[selected_source_index]->status = SRC_SYNC;
/* Now just use the statistics of the selected source for
trimming the local clock */
LCL_ReadCookedTime(&now, &local_clock_err);
SST_GetTrackingData(sources[selected_source_index]->stats, &now,
&src_offset, &src_offset_sd,
&src_accrued_dispersion,
&src_frequency, &src_skew);
total_root_dispersion = (src_accrued_dispersion +
sources[selected_source_index]->sel_info.root_dispersion);
/* Accept leap second status if more than half of selectable sources agree */
for (i=j1=j2=0; i<n_sel_sources; i++) {
@@ -731,18 +728,140 @@ SRC_SelectSource(unsigned long match_addr)
leap_status = LEAP_DeleteSecond;
}
if ((match_addr == 0) ||
(match_addr == sources[selected_source_index]->ref_id)) {
/* If there are any sources with prefer option, reduce the list again
only to the prefer sources */
for (i=j=0; i<n_sel_sources; i++) {
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer) {
sel_sources[j++] = sel_sources[i];
}
}
if (j > 0) {
n_sel_sources = j;
}
/* Now find minimum stratum. If none are left now,
tough. RFC1305 is not so harsh on pruning sources due to
excess variance, which prevents this from happening */
index = sel_sources[0];
min_stratum = sources[index]->sel_info.stratum;
for (i=1; i<n_sel_sources; i++) {
index = sel_sources[i];
stratum = sources[index]->sel_info.stratum;
if (stratum < min_stratum) min_stratum = stratum;
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "min_stratum=%d", min_stratum);
#endif
/* Update scores and find source with maximum score */
max_score_index = INVALID_SOURCE;
max_score = 0.0;
sel_src_distance = 0.0;
if (selected_source_index != INVALID_SOURCE) {
sel_src_distance = sources[selected_source_index]->sel_info.root_distance +
(sources[selected_source_index]->sel_info.stratum - min_stratum) * stratum_weight;
}
for (i = 0; i < n_sources; i++) {
/* Reset score for non-selectable sources */
if (sources[i]->status != SRC_SELECTABLE) {
sources[i]->sel_score = 1.0;
continue;
}
distance = sources[i]->sel_info.root_distance +
(sources[i]->sel_info.stratum - min_stratum) * stratum_weight;
if (sources[i]->type == SRC_NTP)
distance += reselect_distance;
if (selected_source_index != INVALID_SOURCE) {
/* Update score, but only for source pairs where one source
has a new sample */
if (sources[i]->ref_id == match_refid ||
sources[selected_source_index]->ref_id == match_refid) {
sources[i]->sel_score *= sel_src_distance / distance;
if (sources[i]->sel_score < 1.0)
sources[i]->sel_score = 1.0;
}
} else {
/* When there is no selected source yet, assign scores so the
source with minimum distance will have maximum score. The scores
will be immediately reset. */
sources[i]->sel_score = 1.0 / distance;
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "select score=%f refid=%lx match_refid=%lx status=%d dist=%f",
sources[i]->sel_score, sources[i]->ref_id, match_refid, sources[i]->status, distance);
#endif
if (max_score < sources[i]->sel_score) {
max_score = sources[i]->sel_score;
max_score_index = i;
}
}
assert(max_score_index != INVALID_SOURCE);
/* Is the current source still a survivor
and no other source has reached the score limit? */
if ((selected_source_index == INVALID_SOURCE) ||
(sources[selected_source_index]->status != SRC_SELECTABLE) ||
(max_score_index != selected_source_index && max_score > SCORE_LIMIT)) {
/* We have to elect a new synchronisation source */
selected_source_index = max_score_index;
LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
source_to_string(sources[selected_source_index]));
#if 0
LOG(LOGS_INFO, LOGF_Sources, "new_sel_index=%d", selected_source_index);
#endif
/* New source has been selected, reset all scores */
for (i=0; i < n_sources; i++) {
sources[i]->sel_score = 1.0;
}
}
sources[selected_source_index]->status = SRC_SYNC;
/* Update local reference only when a new source was selected or a new
sample was received (i.e. match_refid is equal to selected refid) */
if (selected_source_index != old_selected_index ||
match_refid == sources[selected_source_index]->ref_id) {
/* Now just use the statistics of the selected source for
trimming the local clock */
SST_GetTrackingData(sources[selected_source_index]->stats, &ref_time,
&src_offset, &src_offset_sd,
&src_frequency, &src_skew,
&src_root_delay, &src_root_dispersion);
REF_SetReference(min_stratum, leap_status,
sources[selected_source_index]->ref_id,
sources[selected_source_index]->ip_addr,
&now,
&ref_time,
src_offset,
src_offset_sd,
src_frequency,
src_skew,
sources[selected_source_index]->sel_info.root_delay,
total_root_dispersion);
src_root_delay,
src_root_dispersion);
}
} else {
@@ -750,11 +869,7 @@ SRC_SelectSource(unsigned long match_addr)
LOG(LOGS_INFO, LOGF_Sources, "Can't synchronise: no selectable sources");
}
selected_source_index = INVALID_SOURCE;
REF_SetUnsynchronised();
}
}
} else {
@@ -763,9 +878,33 @@ SRC_SelectSource(unsigned long match_addr)
LOG(LOGS_INFO, LOGF_Sources, "Can't synchronise: no reachable sources");
}
selected_source_index = INVALID_SOURCE;
REF_SetUnsynchronised();
}
if (selected_source_index == INVALID_SOURCE &&
selected_source_index != old_selected_index) {
REF_SetUnsynchronised();
}
}
/* ================================================== */
/* Force reselecting the best source */
void
SRC_ReselectSource(void)
{
selected_source_index = INVALID_SOURCE;
SRC_SelectSource(0);
}
/* ================================================== */
void
SRC_SetReselectDistance(double distance)
{
if (reselect_distance != distance) {
reselect_distance = distance;
LOG(LOGS_INFO, LOGF_Sources, "New reselect distance %f", distance);
}
}
/* ================================================== */
@@ -784,6 +923,16 @@ SRC_MinRoundTripDelay(SRC_Instance inst)
return SST_MinRoundTripDelay(inst->stats);
}
/* ================================================== */
int
SRC_IsGoodSample(SRC_Instance inst, double offset, double delay,
double max_delay_dev_ratio, double clock_error, struct timeval *when)
{
return SST_IsGoodSample(inst->stats, offset, delay, max_delay_dev_ratio,
clock_error, when);
}
/* ================================================== */
/* This routine is registered as a callback with the local clock
module, to be called whenever the local clock changes frequency or
@@ -795,7 +944,6 @@ static void
slew_sources(struct timeval *raw,
struct timeval *cooked,
double dfreq,
double afreq,
double doffset,
int is_step_change,
void *anything)
@@ -808,6 +956,20 @@ slew_sources(struct timeval *raw,
}
/* ================================================== */
/* This routine is called when an indeterminate offset is introduced
into the local time. */
static void
add_dispersion(double dispersion, void *anything)
{
int i;
for (i = 0; i < n_sources; i++) {
SST_AddDispersion(sources[i]->stats, dispersion);
}
}
/* ================================================== */
/* This is called to dump out the source measurement registers */
@@ -875,8 +1037,6 @@ SRC_ReloadSources(void)
LOG(LOGS_WARN, LOGF_Sources, "Could not open dump file %s", filename);
} else {
if (SST_LoadFromFile(sources[i]->stats, in)) {
/* We might want to use SST_DoUpdateRegression here, but we
need to check it has the same functionality */
SST_DoNewRegression(sources[i]->stats);
} else {
LOG(LOGS_WARN, LOGF_Sources, "Problem loading from file %s", filename);
@@ -935,16 +1095,38 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
case SRC_JITTERY:
report->state = RPT_JITTERY;
break;
case SRC_OK:
case SRC_BAD_STATS:
case SRC_UNREACHABLE:
report->state = RPT_UNREACH;
break;
case SRC_FALSETICKER:
report->state = RPT_FALSETICKER;
break;
case SRC_SELECTABLE:
report->state = RPT_CANDIDATE;
break;
default:
report->state = RPT_OTHER;
assert(0);
break;
}
switch (src->sel_option) {
case SRC_SelectNormal:
report->sel_option = RPT_NOSELECT;
break;
case SRC_SelectPrefer:
report->sel_option = RPT_PREFER;
break;
case SRC_SelectNoselect:
report->sel_option = RPT_NOSELECT;
break;
default:
assert(0);
}
report->reachability = src->reachability;
/* Call stats module to fill out estimates */
SST_DoSourceReport(src->stats, report, now);
@@ -1006,3 +1188,11 @@ SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
}
/* ================================================== */
int
SRC_Samples(SRC_Instance inst)
{
return SST_Samples(inst->stats);
}
/* ================================================== */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sources.h,v 1.15 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -55,10 +51,17 @@ typedef enum {
SRC_REFCLOCK /* Rerefence clock */
} SRC_Type;
/* Options used when selecting sources */
typedef enum {
SRC_SelectNormal,
SRC_SelectNoselect,
SRC_SelectPrefer
} SRC_SelectOption;
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr);
extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr);
/* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this
@@ -113,21 +116,32 @@ extern void SRC_AccumulateSample(SRC_Instance instance, struct timeval *sample_t
/* This routine indicates that packets with valid headers are being
received from the designated source */
extern void SRC_SetReachable(SRC_Instance instance);
extern void SRC_SetSelectable(SRC_Instance instance);
/* This routine indicates that we are no longer receiving packets with
valid headers from the designated source */
extern void SRC_UnsetReachable(SRC_Instance instance);
extern void SRC_UnsetSelectable(SRC_Instance instance);
/* This routine updates the reachability register */
extern void SRC_UpdateReachability(SRC_Instance inst, int reachable);
/* This routine marks the source unreachable */
extern void SRC_ResetReachability(SRC_Instance inst);
/* This routine is used to select the best source from amongst those
we currently have valid data on, and use it as the tracking base
for the local time. If match_addr is zero it means we must start
tracking the (newly) selected reference unconditionally, otherwise
it is equal to the address we should track if it turns out to be
the best reference. (This avoids updating the frequency tracking
for every sample from other sources - only the ones from the
selected reference make a difference) */
extern void SRC_SelectSource(unsigned long match_addr);
for the local time. Updates are only made to the local reference
if a new source is selected or match_addr is equal to the selected
reference source address. (This avoids updating the frequency
tracking for every sample from other sources - only the ones from
the selected reference make a difference) */
extern void SRC_SelectSource(uint32_t match_refid);
/* Force reselecting the best source */
extern void SRC_ReselectSource(void);
/* Set reselect distance */
extern void SRC_SetReselectDistance(double distance);
/* Predict the offset of the local clock relative to a given source at
a given local cooked time. Positive indicates local clock is FAST
@@ -138,6 +152,10 @@ extern double SRC_PredictOffset(SRC_Instance inst, struct timeval *when);
currently held in the register */
extern double SRC_MinRoundTripDelay(SRC_Instance inst);
/* This routine determines if a new sample is good enough that it should be
accumulated */
extern int SRC_IsGoodSample(SRC_Instance inst, double offset, double delay, double max_delay_dev_ratio, double clock_error, struct timeval *when);
extern void SRC_DumpSources(void);
extern void SRC_ReloadSources(void);
@@ -158,5 +176,7 @@ typedef enum {
extern SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst);
extern int SRC_Samples(SRC_Instance inst);
#endif /* GOT_SOURCES_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sourcestats.h,v 1.13 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -42,7 +38,7 @@ extern void SST_Initialise(void);
extern void SST_Finalise(void);
/* This function creates a new instance of the statistics handler */
extern SST_Stats SST_CreateInstance(unsigned long refid, IPAddr *addr);
extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr);
/* This function deletes an instance of the statistics handler. */
extern void SST_DeleteInstance(SST_Stats inst);
@@ -89,14 +85,14 @@ SST_GetSelectionData(SST_Stats inst, struct timeval *now,
double *best_offset, double *best_root_delay,
double *best_root_dispersion,
double *variance,
int *average_ok);
int *select_ok);
/* Get data needed when setting up tracking on this source */
extern void
SST_GetTrackingData(SST_Stats inst, struct timeval *now,
SST_GetTrackingData(SST_Stats inst, struct timeval *ref_time,
double *average_offset, double *offset_sd,
double *accrued_dispersion,
double *frequency, double *skew);
double *frequency, double *skew,
double *root_delay, double *root_dispersion);
/* Get parameters for using this source as the reference */
extern void
@@ -125,6 +121,9 @@ SST_GetReferenceData(SST_Stats inst, struct timeval *now,
extern void SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffset);
/* This routine is called when an indeterminate offset is introduced
into the local time. */
extern void SST_AddDispersion(SST_Stats inst, double dispersion);
/* Predict the offset of the local clock relative to a given source at
a given local cooked time. Positive indicates local clock is FAST
@@ -134,6 +133,11 @@ extern double SST_PredictOffset(SST_Stats inst, struct timeval *when);
/* Find the minimum round trip delay in the register */
extern double SST_MinRoundTripDelay(SST_Stats inst);
/* This routine determines if a new sample is good enough that it should be
accumulated */
extern int SST_IsGoodSample(SST_Stats inst, double offset, double delay,
double max_delay_dev_ratio, double clock_error, struct timeval *when);
extern void SST_SaveToFile(SST_Stats inst, FILE *out);
extern int SST_LoadFromFile(SST_Stats inst, FILE *in);
@@ -150,7 +154,7 @@ typedef enum {
extern SST_Skew_Direction SST_LastSkewChange(SST_Stats inst);
extern void SST_CycleLogFile(void);
extern int SST_Samples(SST_Stats inst);
#endif /* GOT_SOURCESTATS_H */

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/srcparams.h,v 1.10 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -31,17 +27,33 @@
#ifndef GOT_SRCPARAMS_H
#define GOT_SRCPARAMS_H
#include "sources.h"
typedef struct {
int minpoll;
int maxpoll;
int online;
int auto_offline;
int presend_minpoll;
int iburst;
int min_stratum;
int poll_target;
unsigned long authkey;
double max_delay;
double max_delay_ratio;
double max_delay_dev_ratio;
SRC_SelectOption sel_option;
} SourceParameters;
#define SRC_DEFAULT_PORT 123
#define SRC_DEFAULT_MINPOLL 6
#define SRC_DEFAULT_MAXPOLL 10
#define SRC_DEFAULT_PRESEND_MINPOLL 0
#define SRC_DEFAULT_MAXDELAY 16.0
#define SRC_DEFAULT_MAXDELAYRATIO 0.0
#define SRC_DEFAULT_MAXDELAYDEVRATIO 10.0
#define SRC_DEFAULT_MINSTRATUM 0
#define SRC_DEFAULT_POLLTARGET 6
#define INACTIVE_AUTHKEY 0UL
#endif /* GOT_SRCPARAMS_H */

View File

@@ -1,9 +1,4 @@
/*
$Header: /cvs/src/chrony/strerror.c,v 1.8 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -29,6 +24,8 @@
Replacement strerror function for systems that don't have it
*/
#include "config.h"
#ifdef SUNOS
#include <errno.h>

6
sys.c
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys.c,v 1.11 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -29,6 +25,8 @@
in the various operating-system specific modules
*/
#include "config.h"
#include "sys.h"
#include "logging.h"

4
sys.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys.h,v 1.7 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_linux.h,v 1.8 2002/02/28 23:27:15 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -35,8 +31,6 @@ extern void SYS_Linux_Initialise(void);
extern void SYS_Linux_Finalise(void);
extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel);
extern void SYS_Linux_DropRoot(char *user);
extern void SYS_Linux_MemLockAll(int LockAll);

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_netbsd.c,v 1.2 2002/02/17 22:13:49 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -29,6 +25,8 @@
Driver file for the NetBSD operating system.
*/
#include "config.h"
#ifdef __NetBSD__
#include <kvm.h>
@@ -78,21 +76,20 @@ static void
clock_initialise(void)
{
struct timeval newadj, oldadj;
struct timezone tz;
offset_register = 0.0;
adjustment_requested = 0.0;
current_freq = 0.0;
if (gettimeofday(&T0, &tz) < 0) {
CROAK("gettimeofday() failed in clock_initialise()");
if (gettimeofday(&T0, NULL) < 0) {
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
}
newadj.tv_sec = 0;
newadj.tv_usec = 0;
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in clock_initialise");
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
}
}
@@ -113,7 +110,6 @@ start_adjust(void)
{
struct timeval newadj, oldadj;
struct timeval T1;
struct timezone tz;
double elapsed, accrued_error;
double adjust_required;
struct timeval exact_newadj;
@@ -122,8 +118,8 @@ start_adjust(void)
double old_adjust_remaining;
/* Determine the amount of error built up since the last adjustment */
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in start_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -151,7 +147,7 @@ start_adjust(void)
UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj);
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in start_adjust");
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
}
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
@@ -169,7 +165,6 @@ static void
stop_adjust(void)
{
struct timeval T1;
struct timezone tz;
struct timeval zeroadj, remadj;
double adjustment_remaining, adjustment_achieved;
double elapsed, elapsed_plus_adjust;
@@ -178,11 +173,11 @@ stop_adjust(void)
zeroadj.tv_usec = 0;
if (adjtime(&zeroadj, &remadj) < 0) {
CROAK("adjtime() failed in stop_adjust");
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
}
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in stop_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -204,7 +199,7 @@ stop_adjust(void)
slew backwards */
static void
accrue_offset(double offset)
accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;
@@ -221,18 +216,17 @@ static void
apply_step_offset(double offset)
{
struct timeval old_time, new_time, T1;
struct timezone tz;
stop_adjust();
if (gettimeofday(&old_time, &tz) < 0) {
CROAK("gettimeofday in apply_step_offset");
if (gettimeofday(&old_time, NULL) < 0) {
LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
}
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
if (settimeofday(&new_time, &tz) < 0) {
CROAK("settimeofday in apply_step_offset");
if (settimeofday(&new_time, NULL) < 0) {
LOG_FATAL(LOGF_SysNetBSD, "settimeofday() failed");
}
UTI_AddDoubleToTimeval(&T0, offset, &T1);
@@ -244,12 +238,14 @@ apply_step_offset(double offset)
/* ================================================== */
static void
static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
return current_freq * 1.0e6;
}
/* ================================================== */
@@ -264,11 +260,13 @@ read_frequency(void)
static void
get_offset_correction(struct timeval *raw,
double *corr)
double *corr, double *err)
{
stop_adjust();
*corr = -offset_register;
start_adjust();
if (err)
*err = 0.0;
}
/* ================================================== */
@@ -287,15 +285,15 @@ SYS_NetBSD_Initialise(void)
kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
if (!kt) {
CROAK("Cannot open kvm\n");
LOG_FATAL(LOGF_SysNetBSD, "Cannot open kvm");
}
if (kvm_nlist(kt, nl) < 0) {
CROAK("Cannot read kernel symbols\n");
LOG_FATAL(LOGF_SysNetBSD, "Cannot read kernel symbols");
}
if (kvm_read(kt, nl[0].n_value, (char *)(&kern_tickadj), sizeof(int)) < 0) {
CROAK("Cannot read from _tickadj\n");
LOG_FATAL(LOGF_SysNetBSD, "Cannot read from _tickadj");
}
if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_netbsd.h,v 1.2 2002/02/17 22:13:49 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_solaris.c,v 1.19 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -28,6 +24,8 @@
Driver file for Solaris operating system
*/
#include "config.h"
#ifdef SOLARIS
#include <kvm.h>
@@ -94,24 +92,23 @@ static void
clock_initialise(void)
{
struct timeval newadj, oldadj;
struct timezone tz;
offset_register = 0.0;
adjustment_requested = 0.0;
current_freq = 0.0;
if (gettimeofday(&T0, &tz) < 0) {
CROAK("gettimeofday() failed in clock_initialise()");
if (gettimeofday(&T0, NULL) < 0) {
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
}
newadj = GET_ZERO;
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in clock_initialise");
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
}
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in clock_initialise");
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
}
return;
@@ -135,7 +132,6 @@ start_adjust(void)
{
struct timeval newadj, oldadj;
struct timeval T1;
struct timezone tz;
double elapsed, accrued_error;
double adjust_required;
struct timeval exact_newadj;
@@ -143,8 +139,8 @@ start_adjust(void)
double old_adjust_remaining;
/* Determine the amount of error built up since the last adjustment */
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in start_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -164,7 +160,7 @@ start_adjust(void)
UTI_DiffTimevalsToDouble(&rounding_error, &exact_newadj, &newadj);
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in start_adjust");
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
}
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
@@ -182,7 +178,6 @@ static void
stop_adjust(void)
{
struct timeval T1;
struct timezone tz;
struct timeval zeroadj, remadj;
double adjustment_remaining, adjustment_achieved;
double elapsed, elapsed_plus_adjust;
@@ -191,11 +186,11 @@ stop_adjust(void)
zeroadj = GET_ZERO;
if (adjtime(&zeroadj, &remadj) < 0) {
CROAK("adjtime() failed in stop_adjust");
LOG_FATAL(LOGF_SysSolaris, "adjtime() failed");
}
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in stop_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -217,7 +212,7 @@ stop_adjust(void)
slew backwards */
static void
accrue_offset(double offset)
accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;
@@ -235,11 +230,10 @@ apply_step_offset(double offset)
{
struct timeval old_time, new_time, rounded_new_time, T1;
double rounding_error;
struct timezone tz;
stop_adjust();
if (gettimeofday(&old_time, &tz) < 0) {
CROAK("gettimeofday in apply_step_offset");
if (gettimeofday(&old_time, NULL) < 0) {
LOG_FATAL(LOGF_SysSolaris, "gettimeofday() failed");
}
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
@@ -259,8 +253,8 @@ apply_step_offset(double offset)
UTI_DiffTimevalsToDouble(&rounding_error, &rounded_new_time, &new_time);
if (settimeofday(&new_time, &tz) < 0) {
CROAK("settimeofday in apply_step_offset");
if (settimeofday(&new_time, NULL) < 0) {
LOG_FATAL(LOGF_SysSolaris, "settimeofday() failed");
}
UTI_AddDoubleToTimeval(&T0, offset, &T1);
@@ -273,12 +267,14 @@ apply_step_offset(double offset)
/* ================================================== */
static void
static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
return current_freq * 1.0e6;
}
/* ================================================== */
@@ -293,11 +289,13 @@ read_frequency(void)
static void
get_offset_correction(struct timeval *raw,
double *corr)
double *corr, double *err)
{
stop_adjust();
*corr = -offset_register;
start_adjust();
if (err)
*err = 0.0;
return;
}
@@ -390,9 +388,7 @@ set_dosynctodr(unsigned long on_off)
kvm_t *kt;
unsigned long read_back;
if (on_off!=1 && on_off!=0) {
CROAK("on_off should be 0 or 1");
}
assert(on_off == 1 || on_off == 0);
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
if (!kt) {
@@ -420,9 +416,7 @@ set_dosynctodr(unsigned long on_off)
kvm_close(kt);
if (read_back != on_off) {
CROAK("read_back should equal on_off");
}
assert(read_back == on_off);
#if 0
LOG(LOGS_INFO, LOGF_SysSolaris, "Set value of dosynctodr to %d", on_off);

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_solaris.h,v 1.7 2002/02/28 23:27:15 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_sunos.c,v 1.19 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -28,6 +24,8 @@
Driver file for the SunOS 4.1.x operating system.
*/
#include "config.h"
#ifdef SUNOS
#include <kvm.h>
@@ -84,25 +82,24 @@ static void
clock_initialise(void)
{
struct timeval newadj, oldadj;
struct timezone tz;
offset_register = 0.0;
adjustment_requested = 0.0;
current_freq = 0.0;
if (gettimeofday(&T0, &tz) < 0) {
CROAK("gettimeofday() failed in clock_initialise()");
if (gettimeofday(&T0, NULL) < 0) {
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
}
newadj.tv_sec = 0;
newadj.tv_usec = 0;
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in clock_initialise");
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
}
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in clock_initialise");
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
}
return;
@@ -126,7 +123,6 @@ start_adjust(void)
{
struct timeval newadj, oldadj;
struct timeval T1;
struct timezone tz;
double elapsed, accrued_error;
double adjust_required;
struct timeval exact_newadj;
@@ -135,8 +131,8 @@ start_adjust(void)
long remainder, multiplier;
/* Determine the amount of error built up since the last adjustment */
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in start_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -167,7 +163,7 @@ start_adjust(void)
UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj);
if (adjtime(&newadj, &oldadj) < 0) {
CROAK("adjtime() failed in start_adjust");
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
}
UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
@@ -185,7 +181,6 @@ static void
stop_adjust(void)
{
struct timeval T1;
struct timezone tz;
struct timeval zeroadj, remadj;
double adjustment_remaining, adjustment_achieved;
double gap;
@@ -195,11 +190,11 @@ stop_adjust(void)
zeroadj.tv_usec = 0;
if (adjtime(&zeroadj, &remadj) < 0) {
CROAK("adjtime() failed in stop_adjust");
LOG_FATAL(LOGF_SysSunOS, "adjtime() failed");
}
if (gettimeofday(&T1, &tz) < 0) {
CROAK("gettimeofday() failed in stop_adjust");
if (gettimeofday(&T1, NULL) < 0) {
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
}
UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
@@ -221,7 +216,7 @@ stop_adjust(void)
slew backwards */
static void
accrue_offset(double offset)
accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;
@@ -238,17 +233,16 @@ static void
apply_step_offset(double offset)
{
struct timeval old_time, new_time, T1;
struct timezone tz;
stop_adjust();
if (gettimeofday(&old_time, &tz) < 0) {
CROAK("gettimeofday in apply_step_offset");
if (gettimeofday(&old_time, NULL) < 0) {
LOG_FATAL(LOGF_SysSunOS, "gettimeofday() failed");
}
UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
if (settimeofday(&new_time, &tz) < 0) {
CROAK("settimeofday in apply_step_offset");
if (settimeofday(&new_time, NULL) < 0) {
LOG_FATAL(LOGF_SysSunOS, "settimeofday() failed");
}
UTI_AddDoubleToTimeval(&T0, offset, &T1);
@@ -260,12 +254,14 @@ apply_step_offset(double offset)
/* ================================================== */
static void
static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
return current_freq * 1.0e6;
}
/* ================================================== */
@@ -280,11 +276,13 @@ read_frequency(void)
static void
get_offset_correction(struct timeval *raw,
double *corr)
double *corr, double *err)
{
stop_adjust();
*corr = -offset_register;
start_adjust();
if (err)
*err = 0.0;
return;
}
@@ -339,9 +337,7 @@ setup_kernel(unsigned long on_off)
unsigned long our_tick = 10000;
unsigned long default_tickadj = 625;
if (on_off!=1 && on_off!=0) {
CROAK("on_off should be 0 or 1");
}
assert(on_off == 1 || on_off == 0);
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
if (!kt) {

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sys_sunos.h,v 1.7 2002/02/28 23:27:15 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/sysincl.h,v 1.11 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************

103
tempcomp.c Normal file
View File

@@ -0,0 +1,103 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2011
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Routines implementing temperature compensation.
*/
#include "config.h"
#include "conf.h"
#include "local.h"
#include "memory.h"
#include "util.h"
#include "logging.h"
#include "sched.h"
#include "tempcomp.h"
static SCH_TimeoutID timeout_id;
static LOG_FileID logfileid;
static char *filename;
static double update_interval;
static double T0, k0, k1, k2;
static void
read_timeout(void *arg)
{
FILE *f;
double temp, comp;
f = fopen(filename, "r");
if (f && fscanf(f, "%lf", &temp) == 1) {
comp = k0 + (temp - T0) * k1 + (temp - T0) * (temp - T0) * k2;
/* Don't allow corrections above 10 ppm */
if (fabs(comp) < 10.0) {
comp = LCL_SetTempComp(comp);
if (logfileid != -1) {
struct timeval now;
LCL_ReadCookedTime(&now, NULL);
LOG_FileWrite(logfileid, "%s %11.4e %11.4e",
UTI_TimeToLogForm(now.tv_sec), temp, comp);
}
}
}
if (f)
fclose(f);
timeout_id = SCH_AddTimeoutByDelay(update_interval, read_timeout, NULL);
}
void
TMC_Initialise(void)
{
CNF_GetTempComp(&filename, &update_interval, &T0, &k0, &k1, &k2);
if (filename == NULL)
return;
if (update_interval <= 0.0)
update_interval = 1.0;
logfileid = CNF_GetLogTempComp() ? LOG_FileOpen("tempcomp",
" Date (UTC) Time Temp. Comp.")
: -1;
read_timeout(NULL);
}
void
TMC_Finalise(void)
{
if (filename == NULL)
return;
SCH_RemoveTimeout(timeout_id);
Free(filename);
}

29
tempcomp.h Normal file
View File

@@ -0,0 +1,29 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2011
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Header file for temperature compensation.
*/
extern void TMC_Initialise(void);
extern void TMC_Finalise(void);

130
util.c
View File

@@ -1,13 +1,9 @@
/*
$Header: /cvs/src/chrony/util.c,v 1.22 2003/09/28 22:21:17 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* Copyright (C) Miroslav Lichvar 2009, 2012
*
* 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
@@ -29,10 +25,12 @@
Various utility functions
*/
#include "config.h"
#include "sysincl.h"
#include "util.h"
#include "md5.h"
#include "hash.h"
/* ================================================== */
@@ -242,7 +240,7 @@ UTI_TimestampToString(NTP_int64 *ts)
/* ================================================== */
char *
UTI_RefidToString(unsigned long ref_id)
UTI_RefidToString(uint32_t ref_id)
{
unsigned int i, j, c;
char buf[5], *result;
@@ -335,19 +333,27 @@ UTI_StringToIP(const char *addr, IPAddr *ip)
/* ================================================== */
unsigned long
uint32_t
UTI_IPToRefid(IPAddr *ip)
{
MD5_CTX ctx;
static int MD5_hash = -1;
unsigned char buf[16];
switch (ip->family) {
case IPADDR_INET4:
return ip->addr.in4;
case IPADDR_INET6:
MD5Init(&ctx);
MD5Update(&ctx, (unsigned const char *) ip->addr.in6, sizeof (ip->addr.in6));
MD5Final(&ctx);
return ctx.digest[0] << 24 | ctx.digest[1] << 16 | ctx.digest[2] << 8 | ctx.digest[3];
if (MD5_hash < 0) {
MD5_hash = HSH_GetHashId("MD5");
assert(MD5_hash >= 0);
}
if (HSH_Hash(MD5_hash, (unsigned const char *)ip->addr.in6, sizeof
(ip->addr.in6), NULL, 0, buf, 16) != 16) {
assert(0);
return 0;
};
return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
}
return 0;
}
@@ -442,13 +448,27 @@ UTI_TimeToLogForm(time_t t)
/* ================================================== */
void
UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double dfreq, double doffset)
UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta_time, double dfreq, double doffset)
{
double elapsed, delta_time;
double elapsed;
UTI_DiffTimevalsToDouble(&elapsed, when, old_tv);
delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(old_tv, delta_time, new_tv);
*delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(old_tv, *delta_time, new_tv);
}
/* ================================================== */
uint32_t
UTI_GetNTPTsFuzz(int precision)
{
uint32_t fuzz;
int fuzz_bits;
fuzz_bits = 32 - 1 + precision;
fuzz = random() % (1 << fuzz_bits);
return fuzz;
}
/* ================================================== */
@@ -459,10 +479,11 @@ UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *
void
UTI_TimevalToInt64(struct timeval *src,
NTP_int64 *dest)
NTP_int64 *dest, uint32_t fuzz)
{
unsigned long usec = src->tv_usec;
unsigned long sec = src->tv_sec;
uint32_t lo;
/* Recognize zero as a special case - it always signifies
an 'unknown' value */
@@ -472,7 +493,12 @@ UTI_TimevalToInt64(struct timeval *src,
dest->hi = htonl(src->tv_sec + JAN_1970);
/* 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);
}
}
@@ -506,9 +532,8 @@ UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
is only 32-bit */
if (sizeof (time_t) > 4 && sec_high == TV_NOHIGHSEC) {
struct timeval now;
struct timezone tz;
gettimeofday(&now, &tz);
gettimeofday(&now, NULL);
sec_high = now.tv_sec >> 16 >> 16;
}
dest->tv_sec = (time_t)sec_high << 16 << 16 | sec_low;
@@ -601,3 +626,66 @@ UTI_FloatHostToNetwork(double x)
}
/* ================================================== */
void
UTI_FdSetCloexec(int fd)
{
int flags;
flags = fcntl(fd, F_GETFD);
if (flags != -1) {
flags |= FD_CLOEXEC;
fcntl(fd, F_SETFD, flags);
}
}
/* ================================================== */
int
UTI_GenerateNTPAuth(int hash_id, const unsigned char *key, int key_len,
const unsigned char *data, int data_len, unsigned char *auth, int auth_len)
{
return HSH_Hash(hash_id, key, key_len, data, data_len, auth, auth_len);
}
/* ================================================== */
int
UTI_CheckNTPAuth(int hash_id, const unsigned char *key, int key_len,
const unsigned char *data, int data_len, const unsigned char *auth, int auth_len)
{
unsigned char buf[MAX_HASH_LENGTH];
return UTI_GenerateNTPAuth(hash_id, key, key_len, data, data_len,
buf, sizeof (buf)) == auth_len && !memcmp(buf, auth, auth_len);
}
/* ================================================== */
int
UTI_DecodePasswordFromText(char *key)
{
int i, j, len = strlen(key);
char buf[3], *p;
if (!strncmp(key, "ASCII:", 6)) {
memmove(key, key + 6, len - 6);
return len - 6;
} else if (!strncmp(key, "HEX:", 4)) {
if ((len - 4) % 2)
return 0;
for (i = 0, j = 4; j + 1 < len; i++, j += 2) {
buf[0] = key[j], buf[1] = key[j + 1], buf[2] = '\0';
key[i] = strtol(buf, &p, 16);
if (p != buf + 2)
return 0;
}
return i;
} else {
/* assume ASCII */
return len;
}
}

26
util.h
View File

@@ -1,8 +1,4 @@
/*
$Header: /cvs/src/chrony/util.h,v 1.15 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
@@ -36,6 +32,7 @@
#include "addressing.h"
#include "ntp.h"
#include "candm.h"
#include "hash.h"
/* Convert a timeval into a floating point number of seconds */
extern void UTI_TimevalToDouble(struct timeval *a, double *b);
@@ -75,13 +72,13 @@ extern char *UTI_TimevalToString(struct timeval *tv);
extern char *UTI_TimestampToString(NTP_int64 *ts);
/* Convert ref_id into a temporary string, for diagnostics */
extern char *UTI_RefidToString(unsigned long ref_id);
extern char *UTI_RefidToString(uint32_t ref_id);
/* Convert an IP address to string, for diagnostics */
extern char *UTI_IPToString(IPAddr *ip);
extern int UTI_StringToIP(const char *addr, IPAddr *ip);
extern unsigned long UTI_IPToRefid(IPAddr *ip);
extern uint32_t UTI_IPToRefid(IPAddr *ip);
extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
@@ -89,10 +86,12 @@ extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
extern char *UTI_TimeToLogForm(time_t t);
/* Adjust time following a frequency/offset change */
extern void UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, 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 void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fuzz);
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
@@ -102,6 +101,17 @@ extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
extern double UTI_FloatNetworkToHost(Float x);
extern Float UTI_FloatHostToNetwork(double x);
/* Set FD_CLOEXEC on descriptor */
extern void UTI_FdSetCloexec(int fd);
extern int UTI_GenerateNTPAuth(int hash_id, const unsigned char *key, int key_len,
const unsigned char *data, int data_len, unsigned char *auth, int auth_len);
extern int UTI_CheckNTPAuth(int hash_id, const unsigned char *key, int key_len,
const unsigned char *data, int data_len, const unsigned char *auth, int auth_len);
/* Decode password encoded in ASCII or HEX */
extern int UTI_DecodePasswordFromText(char *key);
#if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static
#include "util.c"

Some files were not shown because too many files have changed in this diff Show More