Compare commits

..

28 Commits

Author SHA1 Message Date
Miroslav Lichvar
2a299233b3 update NEWS 2015-06-10 14:44:54 +02:00
Miroslav Lichvar
64f83c8861 cmdmon: reply with STT_INVALID on invalid option in handle_manual() 2015-06-09 17:05:45 +02:00
Miroslav Lichvar
1009fe3d9c makefile: warn when Makefile needs to be regenerated 2015-06-09 16:43:56 +02:00
Miroslav Lichvar
ba341fe81a sources: remove unused code in SRC_SelectSource() 2015-06-09 16:15:30 +02:00
Miroslav Lichvar
36e8cb6530 client: add smoothtime command 2015-06-09 16:15:30 +02:00
Miroslav Lichvar
273da62aec cmdmon: add smoothtime command
This adds a command to reset or activate the time smoothing process.
2015-06-09 16:15:30 +02:00
Miroslav Lichvar
41788184a7 client: add smoothing command 2015-06-09 16:15:30 +02:00
Miroslav Lichvar
fb9c2c7dc8 cmdmon: add smoothing command
This adds a new request to get a current report on time smoothing.
2015-06-09 16:15:30 +02:00
Miroslav Lichvar
43116be122 smooth: fix resetting 2015-06-08 17:22:01 +02:00
Miroslav Lichvar
ee038d5de5 cmdmon: use SCH_GetLastEventTime() to get current time
It's cheaper and accurate enough.
2015-06-08 15:07:18 +02:00
Miroslav Lichvar
ea7fae5277 sched: detect timeout overflow in SCH_AddTimeoutByDelay()
Abort when the system time gets so close to the end of 32-bit time_t
that timeouts added by delay start to overflow. This is an addition to
the loop detector in dispatch_timeouts().
2015-06-08 14:49:52 +02:00
Miroslav Lichvar
70b108ab69 array: allow arrays larger than 4 GB
It's not expected we will work with such large arrays anytime soon, but
better be safe than sorry.

Also, limit the number of elements to 2^31-1 to prevent infinite loop in
the calculation of allocated elements.
2015-06-08 14:43:16 +02:00
Miroslav Lichvar
08b152d6a2 test: add 202-prefer 2015-06-08 12:33:46 +02:00
Miroslav Lichvar
83c6213c67 test: add option to override generated server directives on client 2015-06-08 12:33:34 +02:00
Miroslav Lichvar
4253075a97 sources: fix marking of non-preferred selectable sources
When reducing the list of selectable sources to sources with the prefer
option, sources before the first preferred source were left with the
SRC_OK status, which triggered an assertion failure in the next
selection.
2015-06-08 11:54:43 +02:00
Miroslav Lichvar
0abdc2a350 smooth: add option to smooth out only leap seconds
The leaponly option can be used to enable a mode where only leap seconds
are smoothed out and normal offset/frequency changes are ignored. This
is useful to make the interval in which a leap second is smoothed out
constant and allow an NTP client to use multiple leap smearing servers
safely.
2015-06-02 15:24:01 +02:00
Miroslav Lichvar
31669f343a cmdmon: replace definitions of empty requests with null request 2015-06-01 15:00:14 +02:00
Miroslav Lichvar
438b881ab4 cmdmon: set only non-success status in command handling functions 2015-05-28 15:21:25 +02:00
Miroslav Lichvar
27863146a3 cmdmon: refactor allow/deny functions 2015-05-28 14:32:45 +02:00
Miroslav Lichvar
cd4b73612b ntp: include message precision in peer dispersion 2015-05-28 13:49:43 +02:00
Miroslav Lichvar
3c217a9e37 util: add UTI_Log2ToDouble() 2015-05-28 12:51:54 +02:00
Miroslav Lichvar
cde3a003ea util: handle NaN in UTI_FloatHostToNetwork() 2015-05-18 15:51:32 +02:00
Miroslav Lichvar
2c35f56612 client: handle empty hostname before slash in allow/deny commands 2015-05-18 15:36:52 +02:00
Miroslav Lichvar
4295db25d7 doc: remove chrony(1) man page
It's a copy of README, chrony(1) is not a program itself.
2015-05-18 13:15:43 +02:00
Miroslav Lichvar
3c06e57f24 ntp: increase minimum replacement interval to 30 minutes 2015-05-18 13:15:43 +02:00
Miroslav Lichvar
e949cf5967 ntp: replace non-pool sources when unreachable or falsetickers
Sources that are not specified as a pool and have a name (i.e. not
specified by an IP address or added from chronyc) will be replaced with
a newly resolved address of the name when they become unreachable or
falseticker too.
2015-05-18 13:15:42 +02:00
Miroslav Lichvar
4eeaf34295 ntp: add sources specified by IP directly without name resolving 2015-05-18 13:12:00 +02:00
Miroslav Lichvar
2212a90698 ntp: improve alignment of columns in banner for measurements log 2015-05-04 10:23:17 +02:00
30 changed files with 626 additions and 541 deletions

View File

@@ -112,8 +112,6 @@ install: chronyd chronyc chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
cp README $(DESTDIR)$(DOCDIR)/README cp README $(DESTDIR)$(DOCDIR)/README
chmod 644 $(DESTDIR)$(DOCDIR)/README chmod 644 $(DESTDIR)$(DOCDIR)/README
cp chrony.1 $(DESTDIR)$(MANDIR)/man1
chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1 cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1 chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8 cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
@@ -152,6 +150,12 @@ chrony.html : chrony.texi
chrony.info : chrony.texi chrony.info : chrony.texi
makeinfo chrony.texi makeinfo chrony.texi
Makefile : Makefile.in configure
@echo
@echo Makefile needs to be regenerated, run ./configure
@echo
@exit 1
.deps: .deps:
@mkdir .deps @mkdir .deps

19
NEWS
View File

@@ -1,3 +1,22 @@
New in version 2.1
==================
Enhancements
------------
* Try to replace unreachable and falseticker servers/peers specified
by name like pool sources
* Add leaponly option to smoothtime directive to allow synchronised
leap smear between multiple servers
* Add smoothing command to report time smoothing status
* Add smoothtime command to activate or reset time smoothing
Bug fixes
---------
* Fix crash in source selection with preferred sources
* Fix resetting of time smoothing
* Include packet precision in peer dispersion
* Fix crash in chronyc on invalid command syntax
New in version 2.0 New in version 2.0
================== ==================

12
array.c
View File

@@ -44,6 +44,8 @@ ARR_CreateInstance(unsigned int elem_size)
{ {
ARR_Instance array; ARR_Instance array;
assert(elem_size > 0);
array = MallocNew(struct ARR_Instance_Record); array = MallocNew(struct ARR_Instance_Record);
array->data = NULL; array->data = NULL;
@@ -64,6 +66,9 @@ ARR_DestroyInstance(ARR_Instance array)
static void static void
realloc_array(ARR_Instance array, unsigned int min_size) realloc_array(ARR_Instance array, unsigned int min_size)
{ {
size_t data_size;
assert(min_size <= 2 * min_size);
if (array->allocated >= min_size && array->allocated <= 2 * min_size) if (array->allocated >= min_size && array->allocated <= 2 * min_size)
return; return;
@@ -74,7 +79,10 @@ realloc_array(ARR_Instance array, unsigned int min_size)
array->allocated = min_size; array->allocated = min_size;
} }
array->data = Realloc(array->data, array->elem_size * array->allocated); data_size = (size_t)array->elem_size * array->allocated;
assert(data_size / array->elem_size == array->allocated);
array->data = Realloc(array->data, data_size);
} }
void * void *
@@ -89,7 +97,7 @@ void *
ARR_GetElement(ARR_Instance array, unsigned int index) ARR_GetElement(ARR_Instance array, unsigned int index)
{ {
assert(index < array->used); assert(index < array->used);
return (void *)((char *)array->data + index * array->elem_size); return (void *)((char *)array->data + (size_t)index * array->elem_size);
} }
void * void *

92
candm.h
View File

@@ -89,7 +89,9 @@
#define REQ_RESELECT 48 #define REQ_RESELECT 48
#define REQ_RESELECTDISTANCE 49 #define REQ_RESELECTDISTANCE 49
#define REQ_MODIFY_MAKESTEP 50 #define REQ_MODIFY_MAKESTEP 50
#define N_REQUEST_TYPES 51 #define REQ_SMOOTHING 51
#define REQ_SMOOTHTIME 52
#define N_REQUEST_TYPES 53
/* Special utoken value used to log on with first exchange being the /* Special utoken value used to log on with first exchange being the
password. (This time value has long since gone by) */ password. (This time value has long since gone by) */
@@ -116,6 +118,10 @@ typedef struct {
pktlength.c, to get the number of bytes that ought to be pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */ transmitted for each packet type. */
typedef struct {
int32_t EOR;
} REQ_Null;
typedef struct { typedef struct {
IPAddr mask; IPAddr mask;
IPAddr address; IPAddr address;
@@ -215,19 +221,11 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_Manual; } REQ_Manual;
typedef struct {
int32_t EOR;
} REQ_N_Sources;
typedef struct { typedef struct {
int32_t index; int32_t index;
int32_t EOR; int32_t EOR;
} REQ_Source_Data; } REQ_Source_Data;
typedef struct {
int32_t EOR;
} REQ_Rekey;
typedef struct { typedef struct {
IPAddr ip; IPAddr ip;
int32_t subnet_bits; int32_t subnet_bits;
@@ -264,10 +262,6 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_Del_Source; } REQ_Del_Source;
typedef struct {
int32_t EOR;
} REQ_WriteRtc;
typedef struct { typedef struct {
Float dfreq; Float dfreq;
int32_t EOR; int32_t EOR;
@@ -279,27 +273,11 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_Doffset; } REQ_Doffset;
typedef struct {
int32_t EOR;
} REQ_Tracking;
typedef struct { typedef struct {
uint32_t index; uint32_t index;
int32_t EOR; int32_t EOR;
} REQ_Sourcestats; } REQ_Sourcestats;
typedef struct {
int32_t EOR;
} REQ_RTCReport;
typedef struct {
int32_t EOR;
} REQ_TrimRTC;
typedef struct {
int32_t EOR;
} REQ_CycleLogs;
/* This is based on the response size rather than the /* This is based on the response size rather than the
request size */ request size */
#define MAX_CLIENT_ACCESSES 8 #define MAX_CLIENT_ACCESSES 8
@@ -310,32 +288,24 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_ClientAccessesByIndex; } REQ_ClientAccessesByIndex;
typedef struct {
int32_t EOR;
} REQ_ManualList;
typedef struct { typedef struct {
int32_t index; int32_t index;
int32_t EOR; int32_t EOR;
} REQ_ManualDelete; } REQ_ManualDelete;
typedef struct {
int32_t EOR;
} REQ_MakeStep;
typedef struct {
int32_t EOR;
} REQ_Activity;
typedef struct {
int32_t EOR;
} REQ_Reselect;
typedef struct { typedef struct {
Float distance; Float distance;
int32_t EOR; int32_t EOR;
} REQ_ReselectDistance; } REQ_ReselectDistance;
#define REQ_SMOOTHTIME_RESET 0
#define REQ_SMOOTHTIME_ACTIVATE 1
typedef struct {
int32_t option;
int32_t EOR;
} REQ_SmoothTime;
/* ================================================== */ /* ================================================== */
#define PKT_TYPE_CMD_REQUEST 1 #define PKT_TYPE_CMD_REQUEST 1
@@ -365,7 +335,7 @@ typedef struct {
Version 6 : added padding to requests to prevent amplification attack, Version 6 : added padding to requests to prevent amplification attack,
changed maximum number of samples in manual list to 16, new commands: modify changed maximum number of samples in manual list to 16, new commands: modify
makestep makestep, smoothing report, smoothtime command
*/ */
#define PROTO_VERSION_NUMBER 6 #define PROTO_VERSION_NUMBER 6
@@ -398,6 +368,7 @@ typedef struct {
uint32_t token; /* Command token (to prevent replay attack) */ uint32_t token; /* Command token (to prevent replay attack) */
union { union {
REQ_Null null;
REQ_Online online; REQ_Online online;
REQ_Offline offline; REQ_Offline offline;
REQ_Burst burst; REQ_Burst burst;
@@ -415,28 +386,18 @@ typedef struct {
REQ_Settime settime; REQ_Settime settime;
REQ_Local local; REQ_Local local;
REQ_Manual manual; REQ_Manual manual;
REQ_N_Sources n_sources;
REQ_Source_Data source_data; REQ_Source_Data source_data;
REQ_Rekey rekey;
REQ_Allow_Deny allow_deny; REQ_Allow_Deny allow_deny;
REQ_Ac_Check ac_check; REQ_Ac_Check ac_check;
REQ_NTP_Source ntp_source; REQ_NTP_Source ntp_source;
REQ_Del_Source del_source; REQ_Del_Source del_source;
REQ_WriteRtc writertc;
REQ_Dfreq dfreq; REQ_Dfreq dfreq;
REQ_Doffset doffset; REQ_Doffset doffset;
REQ_Tracking tracking;
REQ_Sourcestats sourcestats; REQ_Sourcestats sourcestats;
REQ_RTCReport rtcreport;
REQ_TrimRTC trimrtc;
REQ_CycleLogs cyclelogs;
REQ_ClientAccessesByIndex client_accesses_by_index; REQ_ClientAccessesByIndex client_accesses_by_index;
REQ_ManualList manual_list;
REQ_ManualDelete manual_delete; REQ_ManualDelete manual_delete;
REQ_MakeStep make_step;
REQ_Activity activity;
REQ_Reselect reselect;
REQ_ReselectDistance reselect_distance; REQ_ReselectDistance reselect_distance;
REQ_SmoothTime smoothtime;
} data; /* Command specific parameters */ } data; /* Command specific parameters */
/* The following fields only set the maximum size of the packet. /* The following fields only set the maximum size of the packet.
@@ -472,7 +433,8 @@ typedef struct {
#define RPY_CLIENT_ACCESSES_BY_INDEX 10 #define RPY_CLIENT_ACCESSES_BY_INDEX 10
#define RPY_MANUAL_LIST 11 #define RPY_MANUAL_LIST 11
#define RPY_ACTIVITY 12 #define RPY_ACTIVITY 12
#define N_REPLY_TYPES 13 #define RPY_SMOOTHING 13
#define N_REPLY_TYPES 14
/* Status codes */ /* Status codes */
#define STT_SUCCESS 0 #define STT_SUCCESS 0
@@ -627,6 +589,19 @@ typedef struct {
int32_t EOR; int32_t EOR;
} RPY_Activity; } RPY_Activity;
#define RPY_SMT_FLAG_ACTIVE 0x1
#define RPY_SMT_FLAG_LEAPONLY 0x2
typedef struct {
uint32_t flags;
Float offset;
Float freq_ppm;
Float wander_ppm;
Float last_update_ago;
Float remaining_time;
int32_t EOR;
} RPY_Smoothing;
typedef struct { typedef struct {
uint8_t version; uint8_t version;
uint8_t pkt_type; uint8_t pkt_type;
@@ -653,6 +628,7 @@ typedef struct {
RPY_ClientAccessesByIndex client_accesses_by_index; RPY_ClientAccessesByIndex client_accesses_by_index;
RPY_ManualList manual_list; RPY_ManualList manual_list;
RPY_Activity activity; RPY_Activity activity;
RPY_Smoothing smoothing;
} data; /* Reply specific parameters */ } data; /* Reply specific parameters */
/* authentication of the packet, there is no hole after the actual data /* authentication of the packet, there is no hole after the actual data

View File

@@ -1,72 +0,0 @@
.TH CHRONY 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
.SH NAME
chrony \- programs for keeping computer clocks accurate
.SH SYNOPSIS
\fBchronyc\fR [\fIOPTIONS\fR]
\fBchronyd\fR [\fIOPTIONS\fR]
.SH DESCRIPTION
\fBchrony\fR is a pair of programs for keeping computer clocks accurate.
\fIchronyd\fR is a background (daemon) program and \fIchronyc\fR is a
command-line interface to it. Time reference sources for chronyd can be
NTP servers, human (via keyboard and \fIchronyc\fR), or the computer's
real-time clock at boot time (Linux only). chronyd can determine the rate at
which the computer gains or loses time and compensate for it while no external
reference is present. Its use of NTP servers can be switched on and off
(through \fIchronyc\fR) to support computers with dial-up/intermittent access
to the Internet, and it can also act as an NTP server.
.SH USAGE
\fIchronyc\fR is a command-line interface program which can be used to
monitor \fIchronyd\fR's performance and to change various operating
parameters whilst it is running.
\fIchronyd\fR's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock
accordingly. It also works out the rate at which the system clock
gains or loses time and uses this information to keep it accurate
between measurements from the reference.
The reference time can be derived from either Network Time Protocol
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
The main source of information about the Network Time Protocol is
\fIhttp://www.ntp.org\fR.
It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet or laptops. Of course, it
will work well on computers with permanent connections too.
In addition, on Linux it can monitor the system's real time clock
performance, so the system can maintain accurate time even across
reboots.
Typical accuracies available between 2 machines are
On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next)
With a good reference clock the accuracy can reach one microsecond.
\fIchronyd\fR can also operate as an NTPv4 (RFC 5905) server, peer and
broadcast server.
.SH "SEE ALSO"
.BR chronyc(1),
.BR chrony.conf(5),
.BR chronyd(8)
.I http://chrony.tuxfamily.org/
.SH AUTHOR
Richard Curnow <rc@rc0.org.uk>
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
of "The Missing Man Pages Project". Please see
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
The complete chrony documentation is supplied in texinfo format.

View File

@@ -40,9 +40,8 @@ useful configuration file would look something like
When using a pool of NTP servers (one name is used for multiple servers which When using a pool of NTP servers (one name is used for multiple servers which
may change over time), it's better to specify them with the `pool' directive may change over time), it's better to specify them with the `pool' directive
instead of multiple `server' directives in order to allow \fIchronyd\fR to instead of multiple `server' directives. The configuration file could in this
replace unreachable or bad servers automatically. The configuration file could case look like
in this case look like
.EX .EX
pool pool.ntp.org iburst pool pool.ntp.org iburst
@@ -52,7 +51,6 @@ in this case look like
.EE .EE
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chronyd(8) .BR chronyd(8)

View File

@@ -581,9 +581,8 @@ rtcsync
When using a pool of NTP servers (one name is used for multiple servers which When using a pool of NTP servers (one name is used for multiple servers which
may change over time), it's better to specify them with the @code{pool} may change over time), it's better to specify them with the @code{pool}
directive instead of multiple @code{server} directives in order to allow directive instead of multiple @code{server} directives. The configuration file
@code{chronyd} to replace unreachable or bad servers automatically. The could in this case look like
configuration file could in this case look like
@example @example
pool pool.ntp.org iburst pool pool.ntp.org iburst
@@ -3049,14 +3048,18 @@ falseticker or fail to select a source completely.
The smoothing process is independent from any slewing applied to the local The smoothing process is independent from any slewing applied to the local
system clock, but the accumulated offset and frequency for smoothing will be system clock, but the accumulated offset and frequency for smoothing will be
reset when the clock is corrected by step, e.g. by the @code{makestep} reset when the clock is corrected by stepping, e.g. by the @code{makestep}
directive or command. directive or command. The process can be reset without stepping the clock
by the @code{smoothtime reset} command (@pxref{smoothtime command}).
The directive takes two arguments, the maximum frequency offset of the smoothed The directive takes two arguments, the maximum frequency offset of the smoothed
time to the tracked NTP time (in ppm) and the maximum rate at which the time to the tracked NTP time (in ppm) and the maximum rate at which the
frequency offset is allowed to change (in ppm per second). The smoothing frequency offset is allowed to change (in ppm per second). The smoothing
process is activated when 1/10000 of the estimated skew of the local clock process is activated automatically when 1/10000 of the estimated skew of the
falls below the maximum rate of frequency change. local clock falls below the maximum rate of frequency change. It can be
activated explicitly by the @code{smoothtime activate} command, which is
particularly useful when the clock is synchronized only with manual input
since the skew can't be small enough to activate the process.
An example suitable for clients using @code{ntpd} and 1024 second polling An example suitable for clients using @code{ntpd} and 1024 second polling
interval could be interval could be
@@ -3285,6 +3288,7 @@ password:
@item @code{password} @item @code{password}
@item @code{quit} @item @code{quit}
@item @code{rtcdata} @item @code{rtcdata}
@item @code{smoothing}
@item @code{sources} @item @code{sources}
@item @code{sourcestats} @item @code{sourcestats}
@item @code{tracking} @item @code{tracking}
@@ -3345,6 +3349,8 @@ interface.
* retries command:: Set maximum number of retries * retries command:: Set maximum number of retries
* rtcdata command:: Display RTC parameters * rtcdata command:: Display RTC parameters
* settime command:: Provide a manual input of the current time * settime command:: Provide a manual input of the current time
* smoothing command:: Display current time smoothing state
* smoothtime command:: Reset/activate server time smoothing
* sources command:: Display information about the current set of sources * sources command:: Display information about the current set of sources
* sourcestats command:: Display the rate & offset estimation performance of sources * sourcestats command:: Display the rate & offset estimation performance of sources
* timeout command:: Set initial response timeout * timeout command:: Set initial response timeout
@@ -4321,6 +4327,66 @@ settime Nov 21, 1997 16:30:05
For a full description of @code{getdate}, get hold of the getdate For a full description of @code{getdate}, get hold of the getdate
documentation (bundled, for example, with the source for GNU tar). documentation (bundled, for example, with the source for GNU tar).
@c }}}
@c {{{ smoothing
@node smoothing command
@subsubsection smoothing
The @code{smoothing} command displays the current state of the NTP server time
smoothing. An example of the output is shown below.
@example
Active : Yes
Offset : +1.000268817 seconds
Frequency : -0.142859 ppm
Wander : -0.010000 ppm per second
Last update : 17.8 seconds ago
Remaining time : 19988.4 seconds
@end example
The fields are explained as follows.
@table @code
@item Active
This shows if the server time smoothing is currently active. Possible values
are @code{Yes} and @code{No}. If the @code{leaponly} option is included in the
@code{smoothtime} directive, @code{(leap second only)} will be shown on the
line.
@item Offset
This is the current offset applied to the time sent to NTP clients. Positive
value means the clients are getting time that's ahead of true time.
@item Frequency
The current frequency offset of the served time. Negative value means the time
observed by clients is running slower than true time.
@item Wander
The current frequency wander of the served time. Negative value means the time
observed by clients is slowing down.
@item Last update
This field shows how long ago was the time smoothing process updated, e.g.
@code{chronyd} accumulated a new measurement.
@item Remaining time
The time it would take for the smoothing process to get to zero offset and
frequency if there were no more updates.
@end table
@c }}}
@c {{{ smoothtime
@node smoothtime command
@subsubsection smoothtime
The @code{smoothtime} command can be used to reset or activate the server time
smoothing process if it is configured with the @code{smoothtime} directive
(@pxref{smoothtime directive}).
The syntax is as follows
@example
smoothtime reset
smoothtime activate
@end example
@c }}} @c }}}
@c {{{ sources @c {{{ sources
@node sources command @node sources command

View File

@@ -60,8 +60,7 @@ interactively.
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chronyd(8), .BR chronyd(8)
.BR chrony(1)
.I http://chrony.tuxfamily.org/ .I http://chrony.tuxfamily.org/

View File

@@ -134,7 +134,6 @@ To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
\fBchronyd\fR is documented in detail in the documentation supplied with the \fBchronyd\fR is documented in detail in the documentation supplied with the
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR). distribution (\fIchrony.txt\fR and \fIchrony.texi\fR).
.BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chrony.conf(5), .BR chrony.conf(5),
.BR hwclock(8), .BR hwclock(8),

View File

@@ -640,7 +640,8 @@ process_cmd_manual(CMD_Request *msg, const char *line)
static int static int
parse_allow_deny(CMD_Request *msg, char *line) parse_allow_deny(CMD_Request *msg, char *line)
{ {
unsigned long a, b, c, d, n; unsigned long a, b, c, d;
int n, specified_subnet_bits;
IPAddr ip; IPAddr ip;
char *p; char *p;
@@ -657,7 +658,7 @@ parse_allow_deny(CMD_Request *msg, char *line)
n = 0; n = 0;
if (!UTI_StringToIP(p, &ip) && if (!UTI_StringToIP(p, &ip) &&
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) { (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) <= 0) {
/* Try to parse as the name of a machine */ /* Try to parse as the name of a machine */
if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) { if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) {
@@ -710,7 +711,6 @@ parse_allow_deny(CMD_Request *msg, char *line)
UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip); UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip);
if (slashpos) { if (slashpos) {
int specified_subnet_bits, n;
n = sscanf(slashpos+1, "%d", &specified_subnet_bits); n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
if (n == 1) { if (n == 1) {
msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits); msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits);
@@ -1184,6 +1184,8 @@ give_help(void)
printf("reselect : Reselect synchronisation source\n"); printf("reselect : Reselect synchronisation source\n");
printf("rtcdata : Print current RTC performance parameters\n"); printf("rtcdata : Print current RTC performance parameters\n");
printf("settime <date/time (e.g. Nov 21, 1997 16:30:05 or 16:30:05)> : Manually set the daemon time\n"); printf("settime <date/time (e.g. Nov 21, 1997 16:30:05 or 16:30:05)> : Manually set the daemon time\n");
printf("smoothing : Display current time smoothing state\n");
printf("smoothtime reset|activate : Reset/activate time smoothing\n");
printf("sources [-v] : Display information about current sources\n"); printf("sources [-v] : Display information about current sources\n");
printf("sourcestats [-v] : Display estimation information about current sources\n"); printf("sourcestats [-v] : Display estimation information about current sources\n");
printf("tracking : Display system time information\n"); printf("tracking : Display system time information\n");
@@ -1964,6 +1966,63 @@ process_cmd_tracking(char *line)
} }
/* ================================================== */ /* ================================================== */
static int
process_cmd_smoothing(char *line)
{
CMD_Request request;
CMD_Reply reply;
uint32_t flags;
double offset;
double freq_ppm;
double wander_ppm;
double last_update_ago;
double remaining_time;
request.command = htons(REQ_SMOOTHING);
if (request_reply(&request, &reply, RPY_SMOOTHING, 0)) {
flags = ntohl(reply.data.smoothing.flags);
offset = UTI_FloatNetworkToHost(reply.data.smoothing.offset);
freq_ppm = UTI_FloatNetworkToHost(reply.data.smoothing.freq_ppm);
wander_ppm = UTI_FloatNetworkToHost(reply.data.smoothing.wander_ppm);
last_update_ago = UTI_FloatNetworkToHost(reply.data.smoothing.last_update_ago);
remaining_time = UTI_FloatNetworkToHost(reply.data.smoothing.remaining_time);
printf("Active : %s%s\n",
flags & RPY_SMT_FLAG_ACTIVE ? "Yes" : "No",
flags & RPY_SMT_FLAG_LEAPONLY ? " (leap second only)" : "");
printf("Offset : %+.9f seconds\n", offset);
printf("Frequency : %+.6f ppm\n", freq_ppm);
printf("Wander : %+.6f ppm per second\n", wander_ppm);
printf("Last update : %.1f seconds ago\n", last_update_ago);
printf("Remaining time : %.1f seconds\n", remaining_time);
return 1;
}
return 0;
}
/* ================================================== */
static int
process_cmd_smoothtime(CMD_Request *msg, const char *line)
{
if (!strcmp(line, "reset")) {
msg->data.smoothtime.option = htonl(REQ_SMOOTHTIME_RESET);
} else if (!strcmp(line, "activate")) {
msg->data.smoothtime.option = htonl(REQ_SMOOTHTIME_ACTIVATE);
} else {
fprintf(stderr, "Invalid syntax for smoothtime command\n");
return 0;
}
msg->command = htons(REQ_SMOOTHTIME);
return 1;
}
/* ================================================== */
static int static int
process_cmd_rtcreport(char *line) process_cmd_rtcreport(char *line)
{ {
@@ -2535,6 +2594,11 @@ process_line(char *line, int *quit)
} else if (!strcmp(command, "settime")) { } else if (!strcmp(command, "settime")) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_settime(line); ret = process_cmd_settime(line);
} else if (!strcmp(command, "smoothing")) {
do_normal_submit = 0;
ret = process_cmd_smoothing(line);
} else if (!strcmp(command, "smoothtime")) {
do_normal_submit = process_cmd_smoothtime(&tx_message, line);
} else if (!strcmp(command, "sources")) { } else if (!strcmp(command, "sources")) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_sources(line); ret = process_cmd_sources(line);

366
cmdmon.c
View File

@@ -37,6 +37,7 @@
#include "keys.h" #include "keys.h"
#include "ntp_sources.h" #include "ntp_sources.h"
#include "ntp_core.h" #include "ntp_core.h"
#include "smooth.h"
#include "sources.h" #include "sources.h"
#include "sourcestats.h" #include "sourcestats.h"
#include "reference.h" #include "reference.h"
@@ -162,6 +163,8 @@ static const char permissions[] = {
PERMIT_AUTH, /* RESELECT */ PERMIT_AUTH, /* RESELECT */
PERMIT_AUTH, /* RESELECTDISTANCE */ PERMIT_AUTH, /* RESELECTDISTANCE */
PERMIT_AUTH, /* MODIFY_MAKESTEP */ PERMIT_AUTH, /* MODIFY_MAKESTEP */
PERMIT_OPEN, /* SMOOTHING */
PERMIT_AUTH, /* SMOOTHTIME */
}; };
/* ================================================== */ /* ================================================== */
@@ -712,13 +715,12 @@ transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to, int auth_len)
} }
} }
/* ================================================== */ /* ================================================== */
static void static void
handle_null(CMD_Request *rx_message, CMD_Reply *tx_message) handle_dump(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
tx_message->status = htons(STT_SUCCESS); SRC_DumpSources();
} }
/* ================================================== */ /* ================================================== */
@@ -726,177 +728,132 @@ handle_null(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message) handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address, mask; IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask); UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.online.address, &address); UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
status = NSR_TakeSourcesOnline(&mask, &address); if (!NSR_TakeSourcesOnline(&mask, &address))
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message) handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address, mask; IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask); UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.offline.address, &address); UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
status = NSR_TakeSourcesOffline(&mask, &address); if (!NSR_TakeSourcesOffline(&mask, &address))
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message) handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address, mask; IPAddr address, mask;
UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask); UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
UTI_IPNetworkToHost(&rx_message->data.burst.address, &address); UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples), if (!NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
ntohl(rx_message->data.burst.n_total_samples), ntohl(rx_message->data.burst.n_total_samples),
&mask, &address); &mask, &address))
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
status = NSR_ModifyMinpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) { UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
tx_message->status = htons(STT_SUCCESS); if (!NSR_ModifyMinpoll(&address,
} else { ntohl(rx_message->data.modify_minpoll.new_minpoll)))
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
status = NSR_ModifyMaxpoll(&address,
ntohl(rx_message->data.modify_minpoll.new_minpoll));
if (status) { UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
tx_message->status = htons(STT_SUCCESS); if (!NSR_ModifyMaxpoll(&address,
} else { ntohl(rx_message->data.modify_minpoll.new_minpoll)))
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address); UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
status = NSR_ModifyMaxdelay(&address, if (!NSR_ModifyMaxdelay(&address,
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay)); UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay)))
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address); UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
status = NSR_ModifyMaxdelayratio(&address, if (!NSR_ModifyMaxdelayratio(&address,
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)); UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)))
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address); UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address);
status = NSR_ModifyMaxdelaydevratio(&address, if (!NSR_ModifyMaxdelaydevratio(&address,
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio)); 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); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; 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) { UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
tx_message->status = htons(STT_SUCCESS); if (!NSR_ModifyMinstratum(&address,
} else { ntohl(rx_message->data.modify_minstratum.new_min_stratum)))
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
IPAddr address; 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) { UTI_IPNetworkToHost(&rx_message->data.modify_polltarget.address, &address);
tx_message->status = htons(STT_SUCCESS); if (!NSR_ModifyPolltarget(&address,
} else { ntohl(rx_message->data.modify_polltarget.new_poll_target)))
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
}
/* ================================================== */ /* ================================================== */
@@ -904,7 +861,6 @@ static void
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew)); REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -914,7 +870,6 @@ handle_modify_makestep(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
REF_ModifyMakestep(ntohl(rx_message->data.modify_makestep.limit), REF_ModifyMakestep(ntohl(rx_message->data.modify_makestep.limit),
UTI_FloatNetworkToHost(rx_message->data.modify_makestep.threshold)); UTI_FloatNetworkToHost(rx_message->data.modify_makestep.threshold));
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -929,7 +884,6 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
if (!MNL_IsEnabled()) { if (!MNL_IsEnabled()) {
tx_message->status = htons(STT_NOTENABLED); tx_message->status = htons(STT_NOTENABLED);
} else if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) { } else if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_TIMESTAMP); tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
tx_message->data.manual_timestamp.centiseconds = htonl((int32_t)offset_cs); tx_message->data.manual_timestamp.centiseconds = htonl((int32_t)offset_cs);
tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm); tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
@@ -952,7 +906,6 @@ handle_local(CMD_Request *rx_message, CMD_Reply *tx_message)
} else { } else {
REF_DisableLocal(); REF_DisableLocal();
} }
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -972,8 +925,10 @@ handle_manual(CMD_Request *rx_message, CMD_Reply *tx_message)
case 2: case 2:
MNL_Reset(); MNL_Reset();
break; break;
default:
tx_message->status = htons(STT_INVALID);
break;
} }
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -983,7 +938,6 @@ handle_n_sources(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int n_sources; int n_sources;
n_sources = SRC_ReadNumberOfSources(); n_sources = SRC_ReadNumberOfSources();
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_N_SOURCES); tx_message->reply = htons(RPY_N_SOURCES);
tx_message->data.n_sources.n_sources = htonl(n_sources); tx_message->data.n_sources.n_sources = htonl(n_sources);
} }
@@ -997,7 +951,7 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
struct timeval now_corr; struct timeval now_corr;
/* Get data */ /* Get data */
LCL_ReadCookedTime(&now_corr, NULL); SCH_GetLastEventTime(&now_corr, NULL, NULL);
if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) { if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) { switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
case SRC_NTP: case SRC_NTP:
@@ -1008,7 +962,6 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
break; break;
} }
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCE_DATA); tx_message->reply = htons(RPY_SOURCE_DATA);
UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr); UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
@@ -1071,137 +1024,36 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message) handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
tx_message->status = htons(STT_SUCCESS);
KEY_Reload(); KEY_Reload();
} }
/* ================================================== */ /* ================================================== */
static void static void
handle_allow(CMD_Request *rx_message, CMD_Reply *tx_message) handle_allowdeny(CMD_Request *rx_message, CMD_Reply *tx_message, int allow, int all)
{ {
IPAddr ip; IPAddr ip;
int subnet_bits; int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 0)) { if (!NCR_AddAccessRestriction(&ip, subnet_bits, allow, all))
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
} }
}
/* ================================================== */ /* ================================================== */
static void static void
handle_allowall(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cmdallowdeny(CMD_Request *rx_message, CMD_Reply *tx_message, int allow, int all)
{ {
IPAddr ip; IPAddr ip;
int subnet_bits; int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip); UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits); subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(&ip, subnet_bits, 1, 1)) { if (!CAM_AddAccessRestriction(&ip, subnet_bits, allow, all))
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET); tx_message->status = htons(STT_BADSUBNET);
} }
}
/* ================================================== */
static void
handle_deny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */
static void
handle_denyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (NCR_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */
static void
handle_cmdallow(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */
static void
handle_cmdallowall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(&ip, subnet_bits, 1, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */
static void
handle_cmddeny(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 0)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */
static void
handle_cmddenyall(CMD_Request *rx_message, CMD_Reply *tx_message)
{
IPAddr ip;
int subnet_bits;
UTI_IPNetworkToHost(&rx_message->data.allow_deny.ip, &ip);
subnet_bits = ntohl(rx_message->data.allow_deny.subnet_bits);
if (CAM_AddAccessRestriction(&ip, subnet_bits, 0, 1)) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_BADSUBNET);
}
}
/* ================================================== */ /* ================================================== */
@@ -1266,7 +1118,6 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
status = NSR_AddSource(&rem_addr, type, &params); status = NSR_AddSource(&rem_addr, type, &params);
switch (status) { switch (status) {
case NSR_Success: case NSR_Success:
tx_message->status = htons(STT_SUCCESS);
break; break;
case NSR_AlreadyInUse: case NSR_AlreadyInUse:
tx_message->status = htons(STT_SOURCEALREADYKNOWN); tx_message->status = htons(STT_SOURCEALREADYKNOWN);
@@ -1297,7 +1148,6 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
status = NSR_RemoveSource(&rem_addr); status = NSR_RemoveSource(&rem_addr);
switch (status) { switch (status) {
case NSR_Success: case NSR_Success:
tx_message->status = htons(STT_SUCCESS);
break; break;
case NSR_NoSuchSource: case NSR_NoSuchSource:
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
@@ -1317,7 +1167,6 @@ handle_writertc(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
switch (RTC_WriteParameters()) { switch (RTC_WriteParameters()) {
case RTC_ST_OK: case RTC_ST_OK:
tx_message->status = htons(STT_SUCCESS);
break; break;
case RTC_ST_NODRV: case RTC_ST_NODRV:
tx_message->status = htons(STT_NORTC); tx_message->status = htons(STT_NORTC);
@@ -1337,7 +1186,6 @@ handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq); dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6); LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq); LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -1352,7 +1200,6 @@ handle_doffset(CMD_Request *rx_message, CMD_Reply *tx_message)
doffset = (double) sec + 1.0e-6 * (double) usec; doffset = (double) sec + 1.0e-6 * (double) usec;
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset); LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
LCL_AccumulateOffset(doffset, 0.0); LCL_AccumulateOffset(doffset, 0.0);
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -1363,7 +1210,6 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
RPT_TrackingReport rpt; RPT_TrackingReport rpt;
REF_GetTrackingReport(&rpt); REF_GetTrackingReport(&rpt);
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_TRACKING); tx_message->reply = htons(RPY_TRACKING);
tx_message->data.tracking.ref_id = htonl(rpt.ref_id); tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr); UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
@@ -1383,6 +1229,60 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
/* ================================================== */ /* ================================================== */
static void
handle_smoothing(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_SmoothingReport report;
struct timeval now;
SCH_GetLastEventTime(&now, NULL, NULL);
if (!SMT_GetSmoothingReport(&report, &now)) {
tx_message->status = htons(STT_NOTENABLED);
return;
}
tx_message->reply = htons(RPY_SMOOTHING);
tx_message->data.smoothing.flags = htonl((report.active ? RPY_SMT_FLAG_ACTIVE : 0) |
(report.leap_only ? RPY_SMT_FLAG_LEAPONLY : 0));
tx_message->data.smoothing.offset = UTI_FloatHostToNetwork(report.offset);
tx_message->data.smoothing.freq_ppm = UTI_FloatHostToNetwork(report.freq_ppm);
tx_message->data.smoothing.wander_ppm = UTI_FloatHostToNetwork(report.wander_ppm);
tx_message->data.smoothing.last_update_ago = UTI_FloatHostToNetwork(report.last_update_ago);
tx_message->data.smoothing.remaining_time = UTI_FloatHostToNetwork(report.remaining_time);
}
/* ================================================== */
static void
handle_smoothtime(CMD_Request *rx_message, CMD_Reply *tx_message)
{
struct timeval now;
int option;
if (!SMT_IsEnabled()) {
tx_message->status = htons(STT_NOTENABLED);
return;
}
option = ntohl(rx_message->data.smoothtime.option);
SCH_GetLastEventTime(&now, NULL, NULL);
switch (option) {
case REQ_SMOOTHTIME_RESET:
SMT_Reset(&now);
break;
case REQ_SMOOTHTIME_ACTIVATE:
SMT_Activate(&now);
break;
default:
tx_message->status = htons(STT_INVALID);
break;
}
}
/* ================================================== */
static void static void
handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message) handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
@@ -1390,12 +1290,11 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
RPT_SourcestatsReport report; RPT_SourcestatsReport report;
struct timeval now_corr; struct timeval now_corr;
LCL_ReadCookedTime(&now_corr, NULL); SCH_GetLastEventTime(&now_corr, NULL, NULL);
status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index), status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
&report, &now_corr); &report, &now_corr);
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_SOURCESTATS); tx_message->reply = htons(RPY_SOURCESTATS);
tx_message->data.sourcestats.ref_id = htonl(report.ref_id); tx_message->data.sourcestats.ref_id = htonl(report.ref_id);
UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr); UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.sourcestats.ip_addr);
@@ -1421,7 +1320,6 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
RPT_RTC_Report report; RPT_RTC_Report report;
status = RTC_GetReport(&report); status = RTC_GetReport(&report);
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_RTC); tx_message->reply = htons(RPY_RTC);
UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time); UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
tx_message->data.rtc.n_samples = htons(report.n_samples); tx_message->data.rtc.n_samples = htons(report.n_samples);
@@ -1439,14 +1337,9 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message) handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status; if (!RTC_Trim())
status = RTC_Trim();
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
tx_message->status = htons(STT_NORTC); tx_message->status = htons(STT_NORTC);
} }
}
/* ================================================== */ /* ================================================== */
@@ -1454,8 +1347,6 @@ static void
handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message) handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
LOG_CycleLogFiles(); LOG_CycleLogFiles();
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -1469,14 +1360,13 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
int i, j; int i, j;
struct timeval now; struct timeval now;
LCL_ReadCookedTime(&now, NULL); SCH_GetLastEventTime(&now, NULL, NULL);
first_index = ntohl(rx_message->data.client_accesses_by_index.first_index); first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices); n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices);
if (n_indices > MAX_CLIENT_ACCESSES) if (n_indices > MAX_CLIENT_ACCESSES)
n_indices = MAX_CLIENT_ACCESSES; n_indices = MAX_CLIENT_ACCESSES;
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX); tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX);
for (i = 0, j = 0; i < n_indices; i++) { for (i = 0, j = 0; i < n_indices; i++) {
@@ -1521,7 +1411,6 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
RPY_ManualListSample *sample; RPY_ManualListSample *sample;
RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES]; RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_LIST); tx_message->reply = htons(RPY_MANUAL_LIST);
MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples); MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples);
@@ -1540,16 +1429,11 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message) handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
int status;
int index; int index;
index = ntohl(rx_message->data.manual_delete.index); index = ntohl(rx_message->data.manual_delete.index);
status = MNL_DeleteSample(index); if (!MNL_DeleteSample(index))
if (!status) {
tx_message->status = htons(STT_BADSAMPLE); tx_message->status = htons(STT_BADSAMPLE);
} else {
tx_message->status = htons(STT_SUCCESS);
}
} }
/* ================================================== */ /* ================================================== */
@@ -1557,11 +1441,8 @@ handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message) handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
if (!LCL_MakeStep()) { if (!LCL_MakeStep())
tx_message->status = htons(STT_FAILED); tx_message->status = htons(STT_FAILED);
} else {
tx_message->status = htons(STT_SUCCESS);
}
} }
/* ================================================== */ /* ================================================== */
@@ -1576,7 +1457,6 @@ handle_activity(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.activity.burst_online = htonl(report.burst_online); tx_message->data.activity.burst_online = htonl(report.burst_online);
tx_message->data.activity.burst_offline = htonl(report.burst_offline); tx_message->data.activity.burst_offline = htonl(report.burst_offline);
tx_message->data.activity.unresolved = htonl(report.unresolved); tx_message->data.activity.unresolved = htonl(report.unresolved);
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_ACTIVITY); tx_message->reply = htons(RPY_ACTIVITY);
} }
@@ -1588,7 +1468,6 @@ handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
double dist; double dist;
dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance); dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
SRC_SetReselectDistance(dist); SRC_SetReselectDistance(dist);
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -1597,7 +1476,6 @@ static void
handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message) handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
SRC_ReselectSource(); SRC_ReselectSource();
tx_message->status = htons(STT_SUCCESS);
} }
/* ================================================== */ /* ================================================== */
@@ -1653,8 +1531,8 @@ read_from_cmd_socket(void *anything)
read_length = status; read_length = status;
LCL_ReadRawTime(&now); /* Get current time cheaply */
LCL_CookTime(&now, &cooked_now, NULL); SCH_GetLastEventTime(&cooked_now, NULL, &now);
UTI_SockaddrToIPAndPort(&where_from.u, &remote_ip, &remote_port); UTI_SockaddrToIPAndPort(&where_from.u, &remote_ip, &remote_port);
@@ -1709,6 +1587,7 @@ read_from_cmd_socket(void *anything)
tx_message.command = rx_message.command; tx_message.command = rx_message.command;
tx_message.sequence = rx_message.sequence; tx_message.sequence = rx_message.sequence;
tx_message.reply = htons(RPY_NULL); tx_message.reply = htons(RPY_NULL);
tx_message.status = htons(STT_SUCCESS);
tx_message.pad1 = 0; tx_message.pad1 = 0;
tx_message.pad2 = 0; tx_message.pad2 = 0;
tx_message.pad3 = 0; tx_message.pad3 = 0;
@@ -1909,7 +1788,11 @@ read_from_cmd_socket(void *anything)
if (allowed) { if (allowed) {
switch(rx_command) { switch(rx_command) {
case REQ_NULL: case REQ_NULL:
handle_null(&rx_message, &tx_message); /* Do nothing */
break;
case REQ_DUMP:
handle_dump(&rx_message, &tx_message);
break; break;
case REQ_ONLINE: case REQ_ONLINE:
@@ -1932,11 +1815,6 @@ read_from_cmd_socket(void *anything)
handle_modify_maxpoll(&rx_message, &tx_message); handle_modify_maxpoll(&rx_message, &tx_message);
break; break;
case REQ_DUMP:
SRC_DumpSources();
tx_message.status = htons(STT_SUCCESS);
break;
case REQ_MODIFY_MAXDELAY: case REQ_MODIFY_MAXDELAY:
handle_modify_maxdelay(&rx_message, &tx_message); handle_modify_maxdelay(&rx_message, &tx_message);
break; break;
@@ -2004,35 +1882,35 @@ read_from_cmd_socket(void *anything)
break; break;
case REQ_ALLOW: case REQ_ALLOW:
handle_allow(&rx_message, &tx_message); handle_allowdeny(&rx_message, &tx_message, 1, 0);
break; break;
case REQ_ALLOWALL: case REQ_ALLOWALL:
handle_allowall(&rx_message, &tx_message); handle_allowdeny(&rx_message, &tx_message, 1, 1);
break; break;
case REQ_DENY: case REQ_DENY:
handle_deny(&rx_message, &tx_message); handle_allowdeny(&rx_message, &tx_message, 0, 0);
break; break;
case REQ_DENYALL: case REQ_DENYALL:
handle_denyall(&rx_message, &tx_message); handle_allowdeny(&rx_message, &tx_message, 0, 1);
break; break;
case REQ_CMDALLOW: case REQ_CMDALLOW:
handle_cmdallow(&rx_message, &tx_message); handle_cmdallowdeny(&rx_message, &tx_message, 1, 0);
break; break;
case REQ_CMDALLOWALL: case REQ_CMDALLOWALL:
handle_cmdallowall(&rx_message, &tx_message); handle_cmdallowdeny(&rx_message, &tx_message, 1, 1);
break; break;
case REQ_CMDDENY: case REQ_CMDDENY:
handle_cmddeny(&rx_message, &tx_message); handle_cmdallowdeny(&rx_message, &tx_message, 0, 0);
break; break;
case REQ_CMDDENYALL: case REQ_CMDDENYALL:
handle_cmddenyall(&rx_message, &tx_message); handle_cmdallowdeny(&rx_message, &tx_message, 0, 1);
break; break;
case REQ_ACCHECK: case REQ_ACCHECK:
@@ -2071,6 +1949,14 @@ read_from_cmd_socket(void *anything)
handle_tracking(&rx_message, &tx_message); handle_tracking(&rx_message, &tx_message);
break; break;
case REQ_SMOOTHING:
handle_smoothing(&rx_message, &tx_message);
break;
case REQ_SMOOTHTIME:
handle_smoothtime(&rx_message, &tx_message);
break;
case REQ_SOURCESTATS: case REQ_SOURCESTATS:
handle_sourcestats(&rx_message, &tx_message); handle_sourcestats(&rx_message, &tx_message);
break; break;

16
conf.c
View File

@@ -189,6 +189,7 @@ static char *pidfile;
/* Smoothing constants */ /* Smoothing constants */
static double smooth_max_freq = 0.0; /* in ppm */ static double smooth_max_freq = 0.0; /* in ppm */
static double smooth_max_wander = 0.0; /* in ppm/s */ static double smooth_max_wander = 0.0; /* in ppm/s */
static int smooth_leap_only = 0;
/* Temperature sensor, update interval and compensation coefficients */ /* Temperature sensor, update interval and compensation coefficients */
static char *tempcomp_sensor_file = NULL; static char *tempcomp_sensor_file = NULL;
@@ -1174,11 +1175,23 @@ parse_broadcast(char *line)
static void static void
parse_smoothtime(char *line) parse_smoothtime(char *line)
{ {
if (get_number_of_args(line) != 3)
check_number_of_args(line, 2); check_number_of_args(line, 2);
if (sscanf(line, "%lf %lf", &smooth_max_freq, &smooth_max_wander) != 2) { if (sscanf(line, "%lf %lf", &smooth_max_freq, &smooth_max_wander) != 2) {
smooth_max_freq = 0.0; smooth_max_freq = 0.0;
command_parse_error(); command_parse_error();
} }
line = CPS_SplitWord(CPS_SplitWord(line));
smooth_leap_only = 0;
if (*line) {
if (!strcasecmp(line, "leaponly"))
smooth_leap_only = 1;
else
command_parse_error();
}
} }
/* ================================================== */ /* ================================================== */
@@ -1738,10 +1751,11 @@ CNF_GetLockMemory(void)
/* ================================================== */ /* ================================================== */
void void
CNF_GetSmooth(double *max_freq, double *max_wander) CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only)
{ {
*max_freq = smooth_max_freq; *max_freq = smooth_max_freq;
*max_wander = smooth_max_wander; *max_wander = smooth_max_wander;
*leap_only = smooth_leap_only;
} }
/* ================================================== */ /* ================================================== */

2
conf.h
View File

@@ -96,7 +96,7 @@ extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void); extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void); extern int CNF_GetLockMemory(void);
extern void CNF_GetSmooth(double *max_freq, double *max_wander); extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2); extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);
extern char *CNF_GetUser(void); extern char *CNF_GetUser(void);

View File

@@ -45,7 +45,6 @@ cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
%{_sbindir}/chronyd %{_sbindir}/chronyd
%{_bindir}/chronyc %{_bindir}/chronyc
%{_infodir}/chrony.info* %{_infodir}/chrony.info*
%{_mandir}/man1/chrony.1.gz
%{_mandir}/man1/chronyc.1.gz %{_mandir}/man1/chronyc.1.gz
%{_mandir}/man5/chrony.conf.5.gz %{_mandir}/man5/chrony.conf.5.gz
%{_mandir}/man8/chronyd.8.gz %{_mandir}/man8/chronyd.8.gz

View File

@@ -564,6 +564,9 @@ LCL_NotifyLeap(int leap)
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL); LCL_CookTime(&raw, &cooked, NULL);
/* Smooth the leap second out */
SMT_Leap(&cooked, leap);
/* Dispatch to all handlers as if the clock was stepped */ /* Dispatch to all handlers as if the clock was stepped */
invoke_parameter_change_handlers(&raw, &cooked, 0.0, -leap, LCL_ChangeStep); invoke_parameter_change_handlers(&raw, &cooked, 0.0, -leap, LCL_ChangeStep);
} }

View File

@@ -39,7 +39,7 @@ echo $version > version.txt
sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec
for m in chrony.1 chronyc.1.in chrony.conf.5.in chronyd.8.in; do for m in chronyc.1.in chrony.conf.5.in chronyd.8.in; do
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \ sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
< $m > ${m}_ < $m > ${m}_
mv -f ${m}_ $m mv -f ${m}_ $m

View File

@@ -1230,7 +1230,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
inst->local_ntp_tx.hi = inst->local_ntp_tx.lo = 0; inst->local_ntp_tx.hi = inst->local_ntp_tx.lo = 0;
if (valid_packet) { if (valid_packet) {
precision = LCL_GetSysPrecisionAsQuantum(); precision = LCL_GetSysPrecisionAsQuantum() +
UTI_Log2ToDouble(message->precision);
SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi); SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);

View File

@@ -49,6 +49,7 @@ typedef struct {
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
means this slot in table is in use */ means this slot in table is in use */
NCR_Instance data; /* Data for the protocol engine for this source */ NCR_Instance data; /* Data for the protocol engine for this source */
char *name; /* Name of the source, may be NULL */
int pool; /* Number of the pool from which was this source int pool; /* Number of the pool from which was this source
added or INVALID_POOL */ added or INVALID_POOL */
int tentative; /* Flag indicating there was no valid response int tentative; /* Flag indicating there was no valid response
@@ -85,6 +86,7 @@ struct UnresolvedSource {
#define RESOLVE_INTERVAL_UNIT 7 #define RESOLVE_INTERVAL_UNIT 7
#define MIN_RESOLVE_INTERVAL 2 #define MIN_RESOLVE_INTERVAL 2
#define MAX_RESOLVE_INTERVAL 9 #define MAX_RESOLVE_INTERVAL 9
#define MIN_REPLACEMENT_INTERVAL 8
static struct UnresolvedSource *unresolved_sources = NULL; static struct UnresolvedSource *unresolved_sources = NULL;
static int resolving_interval = 0; static int resolving_interval = 0;
@@ -92,15 +94,11 @@ static SCH_TimeoutID resolving_id;
static struct UnresolvedSource *resolving_source = NULL; static struct UnresolvedSource *resolving_source = NULL;
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL; static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
#define MIN_POOL_RESOLVE_INTERVAL 5
#define MAX_POOL_SOURCES 16 #define MAX_POOL_SOURCES 16
#define INVALID_POOL (-1) #define INVALID_POOL (-1)
/* Pool of sources, the name is expected to resolve to multiple addresses /* Pool of sources with the same name */
which change over time */
struct SourcePool { struct SourcePool {
char *name;
int port;
/* Number of sources added from this pool (ignoring tentative sources) */ /* Number of sources added from this pool (ignoring tentative sources) */
int sources; int sources;
/* Maximum number of sources */ /* Maximum number of sources */
@@ -115,6 +113,7 @@ static ARR_Instance pools;
static void resolve_sources(void *arg); static void resolve_sources(void *arg);
static void rehash_records(void); static void rehash_records(void);
static void clean_source_record(SourceRecord *record);
static void static void
slew_sources(struct timeval *raw, slew_sources(struct timeval *raw,
@@ -162,16 +161,12 @@ NSR_Finalise(void)
struct UnresolvedSource *us; struct UnresolvedSource *us;
unsigned int i; unsigned int i;
for (i = 0; i < ARR_GetSize(pools); i++)
Free(((struct SourcePool *)ARR_GetElement(pools, i))->name);
ARR_DestroyInstance(pools); ARR_DestroyInstance(pools);
for (i = 0; i < ARR_GetSize(records); i++) { for (i = 0; i < ARR_GetSize(records); i++) {
record = get_record(i); record = get_record(i);
if (!record->remote_addr) if (record->remote_addr)
continue; clean_source_record(record);
record->remote_addr = NULL;
NCR_DestroyInstance(record->data);
} }
ARR_DestroyInstance(records); ARR_DestroyInstance(records);
@@ -296,7 +291,7 @@ rehash_records(void)
/* Procedure to add a new source */ /* Procedure to add a new source */
static NSR_Status static NSR_Status
add_source(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params, int pool) add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, SourceParameters *params, int pool)
{ {
SourceRecord *record; SourceRecord *record;
int slot, found; int slot, found;
@@ -323,6 +318,7 @@ add_source(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParamete
record = get_record(slot); record = get_record(slot);
record->data = NCR_GetInstance(remote_addr, type, params); record->data = NCR_GetInstance(remote_addr, type, params);
record->remote_addr = NCR_GetRemoteAddress(record->data); record->remote_addr = NCR_GetRemoteAddress(record->data);
record->name = name ? Strdup(name) : NULL;
record->pool = pool; record->pool = pool;
record->tentative = pool != INVALID_POOL ? 1 : 0; record->tentative = pool != INVALID_POOL ? 1 : 0;
@@ -382,7 +378,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse) if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse)
break; break;
} else { } else {
if (add_source(&address, us->new_source.type, &us->new_source.params, if (add_source(&address, us->name, us->new_source.type, &us->new_source.params,
us->new_source.pool) == NSR_Success) us->new_source.pool) == NSR_Success)
added++; added++;
@@ -495,7 +491,7 @@ append_unresolved_source(struct UnresolvedSource *us)
NSR_Status NSR_Status
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params) NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params)
{ {
return add_source(remote_addr, type, params, INVALID_POOL); return add_source(remote_addr, NULL, type, params, INVALID_POOL);
} }
/* ================================================== */ /* ================================================== */
@@ -505,6 +501,15 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
{ {
struct UnresolvedSource *us; struct UnresolvedSource *us;
struct SourcePool *sp; struct SourcePool *sp;
NTP_Remote_Address remote_addr;
/* If the name is an IP address, don't bother with full resolving now
or later when trying to replace the source */
if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
remote_addr.port = port;
NSR_AddSource(&remote_addr, type, params);
return;
}
us = MallocNew(struct UnresolvedSource); us = MallocNew(struct UnresolvedSource);
us->name = Strdup(name); us->name = Strdup(name);
@@ -518,8 +523,6 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
us->new_source.max_new_sources = 1; us->new_source.max_new_sources = 1;
} else { } else {
sp = (struct SourcePool *)ARR_GetNewElement(pools); sp = (struct SourcePool *)ARR_GetNewElement(pools);
sp->name = Strdup(name);
sp->port = port;
sp->sources = 0; sp->sources = 0;
sp->max_sources = params->max_sources; sp->max_sources = params->max_sources;
us->new_source.pool = ARR_GetSize(pools) - 1; us->new_source.pool = ARR_GetSize(pools) - 1;
@@ -587,6 +590,8 @@ clean_source_record(SourceRecord *record)
assert(record->remote_addr); assert(record->remote_addr);
record->remote_addr = NULL; record->remote_addr = NULL;
NCR_DestroyInstance(record->data); NCR_DestroyInstance(record->data);
if (record->name)
Free(record->name);
n_sources--; n_sources--;
} }
@@ -640,15 +645,18 @@ NSR_RemoveAllSources(void)
/* ================================================== */ /* ================================================== */
static void static void
resolve_pool_replacement(struct SourcePool *sp, NTP_Remote_Address *addr) resolve_source_replacement(SourceRecord *record)
{ {
struct UnresolvedSource *us; struct UnresolvedSource *us;
DEBUG_LOG(LOGF_NtpSources, "trying to replace %s",
UTI_IPToString(&record->remote_addr->ip_addr));
us = MallocNew(struct UnresolvedSource); us = MallocNew(struct UnresolvedSource);
us->name = Strdup(sp->name); us->name = Strdup(record->name);
us->port = sp->port; us->port = record->remote_addr->port;
us->replacement = 1; us->replacement = 1;
us->replace_source = *addr; us->replace_source = *record->remote_addr;
append_unresolved_source(us); append_unresolved_source(us);
NSR_ResolveSources(); NSR_ResolveSources();
@@ -662,32 +670,33 @@ NSR_HandleBadSource(IPAddr *address)
static struct timeval last_replacement; static struct timeval last_replacement;
struct timeval now; struct timeval now;
NTP_Remote_Address remote_addr; NTP_Remote_Address remote_addr;
struct SourcePool *pool; SourceRecord *record;
int pool_index, slot, found; int slot, found;
double diff; double diff;
remote_addr.ip_addr = *address; remote_addr.ip_addr = *address;
remote_addr.port = 0; remote_addr.port = 0;
/* Only sources from a pool can be replaced */
find_slot(&remote_addr, &slot, &found); find_slot(&remote_addr, &slot, &found);
if (!found || (pool_index = get_record(slot)->pool) == INVALID_POOL) if (!found)
return; return;
pool = (struct SourcePool *)ARR_GetElement(pools, pool_index); record = get_record(slot);
/* Don't resolve the pool name too frequently */ /* Only sources with a name can be replaced */
if (!record->name)
return;
/* Don't resolve names too frequently */
SCH_GetLastEventTime(NULL, NULL, &now); SCH_GetLastEventTime(NULL, NULL, &now);
UTI_DiffTimevalsToDouble(&diff, &now, &last_replacement); UTI_DiffTimevalsToDouble(&diff, &now, &last_replacement);
if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_POOL_RESOLVE_INTERVAL)) { if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_REPLACEMENT_INTERVAL)) {
DEBUG_LOG(LOGF_NtpSources, "replacement postponed"); DEBUG_LOG(LOGF_NtpSources, "replacement postponed");
return; return;
} }
last_replacement = now; last_replacement = now;
DEBUG_LOG(LOGF_NtpSources, "pool replacement for %s", UTI_IPToString(address)); resolve_source_replacement(record);
resolve_pool_replacement(pool, &remote_addr);
} }
/* ================================================== */ /* ================================================== */
@@ -741,7 +750,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP
pool->sources++; pool->sources++;
DEBUG_LOG(LOGF_NtpSources, "pool %s has %d confirmed sources", DEBUG_LOG(LOGF_NtpSources, "pool %s has %d confirmed sources",
pool->name, pool->sources); record->name, pool->sources);
/* If the number of sources reached the configured maximum, remove /* If the number of sources reached the configured maximum, remove
the tentative sources added from this pool */ the tentative sources added from this pool */

View File

@@ -44,9 +44,8 @@ command_unpadded_length(CMD_Request *r)
return 0; return 0;
} else { } else {
switch (type) { switch (type) {
case REQ_NULL: case REQ_NULL:
return offsetof(CMD_Request, data); return offsetof(CMD_Request, data.null.EOR);
case REQ_ONLINE: case REQ_ONLINE:
return offsetof(CMD_Request, data.online.EOR); return offsetof(CMD_Request, data.online.EOR);
case REQ_OFFLINE: case REQ_OFFLINE:
@@ -78,11 +77,11 @@ command_unpadded_length(CMD_Request *r)
case REQ_MANUAL : case REQ_MANUAL :
return offsetof(CMD_Request, data.manual.EOR); return offsetof(CMD_Request, data.manual.EOR);
case REQ_N_SOURCES : case REQ_N_SOURCES :
return offsetof(CMD_Request, data.n_sources.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_SOURCE_DATA : case REQ_SOURCE_DATA :
return offsetof(CMD_Request, data.source_data.EOR); return offsetof(CMD_Request, data.source_data.EOR);
case REQ_REKEY : case REQ_REKEY :
return offsetof(CMD_Request, data.rekey.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_ALLOW : case REQ_ALLOW :
return offsetof(CMD_Request, data.allow_deny.EOR); return offsetof(CMD_Request, data.allow_deny.EOR);
case REQ_ALLOWALL : case REQ_ALLOWALL :
@@ -110,21 +109,21 @@ command_unpadded_length(CMD_Request *r)
case REQ_DEL_SOURCE : case REQ_DEL_SOURCE :
return offsetof(CMD_Request, data.del_source.EOR); return offsetof(CMD_Request, data.del_source.EOR);
case REQ_WRITERTC : case REQ_WRITERTC :
return offsetof(CMD_Request, data.writertc.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_DFREQ : case REQ_DFREQ :
return offsetof(CMD_Request, data.dfreq.EOR); return offsetof(CMD_Request, data.dfreq.EOR);
case REQ_DOFFSET : case REQ_DOFFSET :
return offsetof(CMD_Request, data.doffset.EOR); return offsetof(CMD_Request, data.doffset.EOR);
case REQ_TRACKING : case REQ_TRACKING :
return offsetof(CMD_Request, data.tracking.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_SOURCESTATS : case REQ_SOURCESTATS :
return offsetof(CMD_Request, data.sourcestats.EOR); return offsetof(CMD_Request, data.sourcestats.EOR);
case REQ_RTCREPORT : case REQ_RTCREPORT :
return offsetof(CMD_Request, data.rtcreport.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_TRIMRTC : case REQ_TRIMRTC :
return offsetof(CMD_Request, data.trimrtc.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_CYCLELOGS : case REQ_CYCLELOGS :
return offsetof(CMD_Request, data.cyclelogs.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_SUBNETS_ACCESSED : case REQ_SUBNETS_ACCESSED :
case REQ_CLIENT_ACCESSES: case REQ_CLIENT_ACCESSES:
/* No longer supported */ /* No longer supported */
@@ -132,21 +131,25 @@ command_unpadded_length(CMD_Request *r)
case REQ_CLIENT_ACCESSES_BY_INDEX: case REQ_CLIENT_ACCESSES_BY_INDEX:
return offsetof(CMD_Request, data.client_accesses_by_index.EOR); return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
case REQ_MANUAL_LIST: case REQ_MANUAL_LIST:
return offsetof(CMD_Request, data.manual_list.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_MANUAL_DELETE: case REQ_MANUAL_DELETE:
return offsetof(CMD_Request, data.manual_delete.EOR); return offsetof(CMD_Request, data.manual_delete.EOR);
case REQ_MAKESTEP: case REQ_MAKESTEP:
return offsetof(CMD_Request, data.make_step.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_ACTIVITY: case REQ_ACTIVITY:
return offsetof(CMD_Request, data.activity.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_RESELECT: case REQ_RESELECT:
return offsetof(CMD_Request, data.reselect.EOR); return offsetof(CMD_Request, data.null.EOR);
case REQ_RESELECTDISTANCE: case REQ_RESELECTDISTANCE:
return offsetof(CMD_Request, data.reselect_distance.EOR); return offsetof(CMD_Request, data.reselect_distance.EOR);
case REQ_MODIFY_MINSTRATUM: case REQ_MODIFY_MINSTRATUM:
return offsetof(CMD_Request, data.modify_minstratum.EOR); return offsetof(CMD_Request, data.modify_minstratum.EOR);
case REQ_MODIFY_POLLTARGET: case REQ_MODIFY_POLLTARGET:
return offsetof(CMD_Request, data.modify_polltarget.EOR); return offsetof(CMD_Request, data.modify_polltarget.EOR);
case REQ_SMOOTHING:
return offsetof(CMD_Request, data.null.EOR);
case REQ_SMOOTHTIME:
return offsetof(CMD_Request, data.smoothtime.EOR);
default: default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */ /* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0); assert(0);
@@ -228,11 +231,11 @@ PKL_CommandPaddingLength(CMD_Request *r)
case REQ_MANUAL: case REQ_MANUAL:
return PADDING_LENGTH(data.manual.EOR, data.null.EOR); return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
case REQ_N_SOURCES: case REQ_N_SOURCES:
return PADDING_LENGTH(data.n_sources.EOR, data.n_sources.EOR); return PADDING_LENGTH(data.null.EOR, data.n_sources.EOR);
case REQ_SOURCE_DATA: case REQ_SOURCE_DATA:
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR); return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
case REQ_REKEY: case REQ_REKEY:
return PADDING_LENGTH(data.rekey.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_ALLOW: case REQ_ALLOW:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR); return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_ALLOWALL: case REQ_ALLOWALL:
@@ -260,21 +263,21 @@ PKL_CommandPaddingLength(CMD_Request *r)
case REQ_DEL_SOURCE: case REQ_DEL_SOURCE:
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR); return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
case REQ_WRITERTC: case REQ_WRITERTC:
return PADDING_LENGTH(data.writertc.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_DFREQ: case REQ_DFREQ:
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR); return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
case REQ_DOFFSET: case REQ_DOFFSET:
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR); return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
case REQ_TRACKING: case REQ_TRACKING:
return PADDING_LENGTH(data.tracking.EOR, data.tracking.EOR); return PADDING_LENGTH(data.null.EOR, data.tracking.EOR);
case REQ_SOURCESTATS: case REQ_SOURCESTATS:
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR); return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
case REQ_RTCREPORT: case REQ_RTCREPORT:
return PADDING_LENGTH(data.rtcreport.EOR, data.rtc.EOR); return PADDING_LENGTH(data.null.EOR, data.rtc.EOR);
case REQ_TRIMRTC: case REQ_TRIMRTC:
return PADDING_LENGTH(data.trimrtc.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_CYCLELOGS: case REQ_CYCLELOGS:
return PADDING_LENGTH(data.cyclelogs.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_SUBNETS_ACCESSED: case REQ_SUBNETS_ACCESSED:
case REQ_CLIENT_ACCESSES: case REQ_CLIENT_ACCESSES:
/* No longer supported */ /* No longer supported */
@@ -282,21 +285,25 @@ PKL_CommandPaddingLength(CMD_Request *r)
case REQ_CLIENT_ACCESSES_BY_INDEX: case REQ_CLIENT_ACCESSES_BY_INDEX:
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR); return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
case REQ_MANUAL_LIST: case REQ_MANUAL_LIST:
return PADDING_LENGTH(data.manual_list.EOR, data.manual_list.EOR); return PADDING_LENGTH(data.null.EOR, data.manual_list.EOR);
case REQ_MANUAL_DELETE: case REQ_MANUAL_DELETE:
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR); return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
case REQ_MAKESTEP: case REQ_MAKESTEP:
return PADDING_LENGTH(data.make_step.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_ACTIVITY: case REQ_ACTIVITY:
return PADDING_LENGTH(data.activity.EOR, data.activity.EOR); return PADDING_LENGTH(data.null.EOR, data.activity.EOR);
case REQ_RESELECT: case REQ_RESELECT:
return PADDING_LENGTH(data.reselect.EOR, data.null.EOR); return PADDING_LENGTH(data.null.EOR, data.null.EOR);
case REQ_RESELECTDISTANCE: case REQ_RESELECTDISTANCE:
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR); return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
case REQ_MODIFY_MINSTRATUM: case REQ_MODIFY_MINSTRATUM:
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR); return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
case REQ_MODIFY_POLLTARGET: case REQ_MODIFY_POLLTARGET:
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR); return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
case REQ_SMOOTHING:
return PADDING_LENGTH(data.null.EOR, data.smoothing.EOR);
case REQ_SMOOTHTIME:
return PADDING_LENGTH(data.smoothtime.EOR, data.null.EOR);
default: default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */ /* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0); assert(0);
@@ -360,7 +367,8 @@ PKL_ReplyLength(CMD_Reply *r)
} }
case RPY_ACTIVITY: case RPY_ACTIVITY:
return offsetof(CMD_Reply, data.activity.EOR); return offsetof(CMD_Reply, data.activity.EOR);
case RPY_SMOOTHING:
return offsetof(CMD_Reply, data.smoothing.EOR);
default: default:
assert(0); assert(0);
} }

View File

@@ -499,15 +499,6 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
return 1; return 1;
} }
static double
poll_interval(int poll)
{
if (poll >= 0)
return 1 << poll;
else
return 1.0 / (1 << -poll);
}
static int static int
valid_sample_time(RCL_Instance instance, struct timeval *tv) valid_sample_time(RCL_Instance instance, struct timeval *tv)
{ {
@@ -516,7 +507,7 @@ valid_sample_time(RCL_Instance instance, struct timeval *tv)
LCL_ReadRawTime(&raw_time); LCL_ReadRawTime(&raw_time);
UTI_DiffTimevalsToDouble(&diff, &raw_time, tv); UTI_DiffTimevalsToDouble(&diff, &raw_time, tv);
if (diff < 0.0 || diff > poll_interval(instance->poll + 1)) { if (diff < 0.0 || diff > UTI_Log2ToDouble(instance->poll + 1)) {
DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f tv=%s", DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f tv=%s",
UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv)); UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv));
return 0; return 0;
@@ -595,7 +586,7 @@ poll_timeout(void *arg)
} }
} }
inst->timeout_id = SCH_AddTimeoutByDelay(poll_interval(poll), poll_timeout, arg); inst->timeout_id = SCH_AddTimeoutByDelay(UTI_Log2ToDouble(poll), poll_timeout, arg);
} }
static void static void

View File

@@ -112,4 +112,14 @@ typedef struct {
int unresolved; int unresolved;
} RPT_ActivityReport; } RPT_ActivityReport;
typedef struct {
int active;
int leap_only;
double offset;
double freq_ppm;
double wander_ppm;
double last_update_ago;
double remaining_time;
} RPT_SmoothingReport;
#endif /* GOT_REPORTS_H */ #endif /* GOT_REPORTS_H */

View File

@@ -330,6 +330,10 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
LCL_ReadRawTime(&now); LCL_ReadRawTime(&now);
UTI_AddDoubleToTimeval(&now, delay, &then); UTI_AddDoubleToTimeval(&now, delay, &then);
if (UTI_CompareTimevals(&now, &then) > 0) {
LOG_FATAL(LOGF_Scheduler, "Timeout overflow");
}
return SCH_AddTimeout(&then, handler, arg); return SCH_AddTimeout(&then, handler, arg);
} }

109
smooth.c
View File

@@ -77,6 +77,10 @@ static struct stage stages[NUM_STAGES];
/* Enabled/disabled smoothing */ /* Enabled/disabled smoothing */
static int enabled; static int enabled;
/* Enabled/disabled mode where only leap seconds are smoothed out and normal
offset/frequency changes are ignored */
static int leap_only_mode;
/* Maximum skew/max_wander ratio to start updating offset and frequency */ /* Maximum skew/max_wander ratio to start updating offset and frequency */
#define UNLOCK_SKEW_WANDER_RATIO 10000 #define UNLOCK_SKEW_WANDER_RATIO 10000
@@ -93,15 +97,17 @@ static struct timeval last_update;
static void static void
get_offset_freq(struct timeval *now, double *offset, double *freq) get_smoothing(struct timeval *now, double *poffset, double *pfreq,
double *pwander)
{ {
double elapsed, length; double elapsed, length, offset, freq, wander;
int i; int i;
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update); UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
*offset = smooth_offset; offset = smooth_offset;
*freq = smooth_freq; freq = smooth_freq;
wander = 0.0;
for (i = 0; i < NUM_STAGES; i++) { for (i = 0; i < NUM_STAGES; i++) {
if (elapsed <= 0.0) if (elapsed <= 0.0)
@@ -111,13 +117,21 @@ get_offset_freq(struct timeval *now, double *offset, double *freq)
if (length >= elapsed) if (length >= elapsed)
length = elapsed; length = elapsed;
*offset -= length * (2.0 * *freq + stages[i].wander * length) / 2.0; wander = stages[i].wander;
*freq += stages[i].wander * length; offset -= length * (2.0 * freq + wander * length) / 2.0;
freq += wander * length;
elapsed -= length; elapsed -= length;
} }
if (elapsed > 0.0) if (elapsed > 0.0) {
*offset -= elapsed * *freq; wander = 0.0;
offset -= elapsed * freq;
}
*poffset = offset;
*pfreq = freq;
if (pwander)
*pwander = wander;
} }
static void static void
@@ -185,14 +199,12 @@ update_smoothing(struct timeval *now, double offset, double freq)
{ {
/* Don't accept offset/frequency until the clock has stabilized */ /* Don't accept offset/frequency until the clock has stabilized */
if (locked) { if (locked) {
if (REF_GetSkew() / max_wander < UNLOCK_SKEW_WANDER_RATIO) { if (REF_GetSkew() / max_wander < UNLOCK_SKEW_WANDER_RATIO || leap_only_mode)
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated"); SMT_Activate(now);
locked = 0;
}
return; return;
} }
get_offset_freq(now, &smooth_offset, &smooth_freq); get_smoothing(now, &smooth_offset, &smooth_freq, NULL);
smooth_offset += offset; smooth_offset += offset;
smooth_freq = (smooth_freq - freq) / (1.0 - freq); smooth_freq = (smooth_freq - freq) / (1.0 - freq);
last_update = *now; last_update = *now;
@@ -208,15 +220,19 @@ handle_slew(struct timeval *raw, struct timeval *cooked, double dfreq,
{ {
double delta; double delta;
if (change_type == LCL_ChangeAdjust) if (change_type == LCL_ChangeAdjust) {
if (leap_only_mode)
update_smoothing(cooked, 0.0, 0.0);
else
update_smoothing(cooked, doffset, dfreq); update_smoothing(cooked, doffset, dfreq);
}
UTI_AdjustTimeval(&last_update, cooked, &last_update, &delta, dfreq, doffset); UTI_AdjustTimeval(&last_update, cooked, &last_update, &delta, dfreq, doffset);
} }
void SMT_Initialise(void) void SMT_Initialise(void)
{ {
CNF_GetSmooth(&max_freq, &max_wander); CNF_GetSmooth(&max_freq, &max_wander, &leap_only_mode);
if (max_freq <= 0.0 || max_wander <= 0.0) { if (max_freq <= 0.0 || max_wander <= 0.0) {
enabled = 0; enabled = 0;
return; return;
@@ -249,19 +265,78 @@ SMT_GetOffset(struct timeval *now)
if (!enabled) if (!enabled)
return 0.0; return 0.0;
get_offset_freq(now, &offset, &freq); get_smoothing(now, &offset, &freq, NULL);
return offset; return offset;
} }
void
SMT_Activate(struct timeval *now)
{
if (!enabled || !locked)
return;
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated%s", leap_only_mode ?
" (leap seconds only)" : "");
locked = 0;
last_update = *now;
}
void void
SMT_Reset(struct timeval *now) SMT_Reset(struct timeval *now)
{ {
int i;
if (!enabled) if (!enabled)
return; return;
locked = 1;
smooth_offset = 0.0; smooth_offset = 0.0;
smooth_freq = 0.0; smooth_freq = 0.0;
last_update = *now; last_update = *now;
for (i = 0; i < NUM_STAGES; i++)
stages[i].wander = stages[i].length = 0.0;
}
void
SMT_Leap(struct timeval *now, int leap)
{
/* When the leap-only mode is disabled, the leap second will be accumulated
in handle_slew() as a normal offset */
if (!enabled || !leap_only_mode)
return;
update_smoothing(now, leap, 0.0);
}
int
SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now)
{
double length, elapsed;
int i;
if (!enabled)
return 0;
report->active = !locked;
report->leap_only = leap_only_mode;
get_smoothing(now, &report->offset, &report->freq_ppm, &report->wander_ppm);
/* Convert to ppm and negate (positive values mean faster/speeding up) */
report->freq_ppm *= -1.0e6;
report->wander_ppm *= -1.0e6;
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
if (!locked && elapsed >= 0.0) {
for (i = 0, length = 0.0; i < NUM_STAGES; i++)
length += stages[i].length;
report->last_update_ago = elapsed;
report->remaining_time = elapsed < length ? length - elapsed : 0.0;
} else {
report->last_update_ago = 0.0;
report->remaining_time = 0.0;
}
return 1;
} }

View File

@@ -27,6 +27,8 @@
#ifndef GOT_SMOOTH_H #ifndef GOT_SMOOTH_H
#define GOT_SMOOTH_H #define GOT_SMOOTH_H
#include "reports.h"
extern void SMT_Initialise(void); extern void SMT_Initialise(void);
extern void SMT_Finalise(void); extern void SMT_Finalise(void);
@@ -35,6 +37,12 @@ extern int SMT_IsEnabled(void);
extern double SMT_GetOffset(struct timeval *now); extern double SMT_GetOffset(struct timeval *now);
extern void SMT_Activate(struct timeval *now);
extern void SMT_Reset(struct timeval *now); extern void SMT_Reset(struct timeval *now);
extern void SMT_Leap(struct timeval *now, int leap);
extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
#endif #endif

View File

@@ -807,43 +807,6 @@ SRC_SelectSource(SRC_Instance updated_inst)
} }
} }
#if 0
/* We now have a list of indices for the sources which pass the
false-ticker test. Now go on to reject those whose variance is
greater than the minimum distance of any other */
/* Find minimum distance */
index = sel_sources[0];
min_distance = sources[index]->sel_info.root_distance;
for (i = 1; i < n_sel_sources; i++) {
index = sel_sources[i];
distance = sources[index]->sel_info.root_distance;
if (distance < min_distance) {
min_distance = distance;
}
}
/* Now go through and prune any NTP sources that have excessive
variance */
for (i = 0; i < n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->type == SRC_NTP &&
sqrt(sources[index]->sel_info.variance) > min_distance) {
sel_sources[i] = INVALID_SOURCE;
sources[index]->status = SRC_JITTERY;
}
}
/* Now crunch the list and mark all sources as selectable */
for (i = j = 0; i < n_sel_sources; i++) {
index = sel_sources[i];
if (index == INVALID_SOURCE)
continue;
sel_sources[j++] = index;
}
n_sel_sources = j;
#endif
if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) { if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) {
if (selected_source_index != INVALID_SOURCE) { if (selected_source_index != INVALID_SOURCE) {
log_selection_message("Can't synchronise: %s selectable sources", log_selection_message("Can't synchronise: %s selectable sources",
@@ -872,16 +835,18 @@ SRC_SelectSource(SRC_Instance updated_inst)
/* If there are any sources with prefer option, reduce the list again /* If there are any sources with prefer option, reduce the list again
only to the preferred sources */ only to the preferred sources */
for (i = j = 0; i < n_sel_sources; i++) {
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer)
sel_sources[j++] = sel_sources[i];
}
if (j > 0) {
for (i = 0; i < n_sel_sources; i++) { for (i = 0; i < n_sel_sources; i++) {
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer)
break;
}
if (i < n_sel_sources) {
for (i = j = 0; i < n_sel_sources; i++) {
if (sources[sel_sources[i]]->sel_option != SRC_SelectPrefer) if (sources[sel_sources[i]]->sel_option != SRC_SelectPrefer)
sources[sel_sources[i]]->status = SRC_NONPREFERRED; sources[sel_sources[i]]->status = SRC_NONPREFERRED;
else
sel_sources[j++] = sel_sources[i];
} }
assert(j > 0);
n_sel_sources = j; n_sel_sources = j;
sel_prefer = 1; sel_prefer = 1;
} else { } else {

View File

@@ -27,10 +27,11 @@ for leapmode in system step slew; do
check_sync || test_fail check_sync || test_fail
done done
for smoothmode in "" "leaponly"; do
server_conf="refclock SHM 0 dpoll 10 poll 10 server_conf="refclock SHM 0 dpoll 10 poll 10
leapsectz right/UTC leapsectz right/UTC
leapsecmode slew leapsecmode slew
smoothtime 400 0.001" smoothtime 400 0.001 $smoothmode"
client_conf="leapsecmode system" client_conf="leapsecmode system"
min_sync_time=230000 min_sync_time=230000
max_sync_time=240000 max_sync_time=240000
@@ -40,5 +41,6 @@ check_chronyd_exit || test_fail
check_source_selection || test_fail check_source_selection || test_fail
check_packet_interval || test_fail check_packet_interval || test_fail
check_sync || test_fail check_sync || test_fail
done
test_pass test_pass

21
test/simulation/202-prefer Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
. test.common
# Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629
test_start "prefer option"
servers=3
client_server_conf="
server 192.168.123.1
server 192.168.123.2
server 192.168.123.3 prefer"
run_test || test_fail
check_chronyd_exit || test_fail
check_source_selection || test_fail
check_packet_interval || test_fail
check_sync || test_fail
test_pass

View File

@@ -65,6 +65,7 @@ default_chronyc_start=1000.0
default_server_step="" default_server_step=""
default_client_step="" default_client_step=""
default_client_server_conf=""
default_server_server_options="" default_server_server_options=""
default_client_server_options="" default_client_server_options=""
default_server_peer_options="" default_server_peer_options=""
@@ -191,10 +192,14 @@ get_chronyd_conf() {
echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $server_peer_options" echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $server_peer_options"
done done
echo "$server_conf" echo "$server_conf"
else
if [ -n "$client_server_conf" ]; then
echo "$client_server_conf"
else else
for i in $(seq 1 $servers); do for i in $(seq 1 $servers); do
echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options" echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options"
done done
fi
for i in $(seq 1 $peers); do for i in $(seq 1 $peers); do
[ $i -eq $peer -o $i -gt $clients ] && continue [ $i -eq $peer -o $i -gt $clients ] && continue
echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $client_peer_options" echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $client_peer_options"

20
util.c
View File

@@ -643,6 +643,22 @@ UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
/* ================================================== */ /* ================================================== */
double
UTI_Log2ToDouble(int l)
{
if (l >= 0) {
if (l > 31)
l = 31;
return 1 << l;
} else {
if (l < -31)
l = -31;
return 1.0 / (1 << -l);
}
}
/* ================================================== */
void void
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest) UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
{ {
@@ -707,7 +723,11 @@ UTI_FloatHostToNetwork(double x)
if (x < 0.0) { if (x < 0.0) {
x = -x; x = -x;
neg = 1; neg = 1;
} else if (x >= 0.0) {
neg = 0;
} else { } else {
/* Save NaN as zero */
x = 0.0;
neg = 0; neg = 0;
} }

3
util.h
View File

@@ -107,6 +107,9 @@ extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
/* Check if time + offset is sane */ /* Check if time + offset is sane */
extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset); extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset);
/* Get 2 raised to power of a signed integer */
extern double UTI_Log2ToDouble(int l);
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest); extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest); extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);