mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 18:45:07 -05:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a299233b3 | ||
|
|
64f83c8861 | ||
|
|
1009fe3d9c | ||
|
|
ba341fe81a | ||
|
|
36e8cb6530 | ||
|
|
273da62aec | ||
|
|
41788184a7 | ||
|
|
fb9c2c7dc8 | ||
|
|
43116be122 | ||
|
|
ee038d5de5 | ||
|
|
ea7fae5277 | ||
|
|
70b108ab69 | ||
|
|
08b152d6a2 | ||
|
|
83c6213c67 | ||
|
|
4253075a97 | ||
|
|
0abdc2a350 | ||
|
|
31669f343a | ||
|
|
438b881ab4 | ||
|
|
27863146a3 | ||
|
|
cd4b73612b | ||
|
|
3c217a9e37 | ||
|
|
cde3a003ea | ||
|
|
2c35f56612 | ||
|
|
4295db25d7 | ||
|
|
3c06e57f24 | ||
|
|
e949cf5967 | ||
|
|
4eeaf34295 | ||
|
|
2212a90698 | ||
|
|
dc52b61dad | ||
|
|
bbf4c3186b | ||
|
|
f72016a78e | ||
|
|
29b587a9c5 | ||
|
|
cec4f2b140 | ||
|
|
05278c3b4c | ||
|
|
1769b8ea0f | ||
|
|
5686bd87d7 | ||
|
|
1cda2db45d | ||
|
|
fdf9640349 | ||
|
|
8f2d5d99f1 | ||
|
|
61272e7ce8 | ||
|
|
88b76f49cc | ||
|
|
ad942e352d | ||
|
|
39c2bcd462 | ||
|
|
ae10664b24 |
@@ -112,8 +112,6 @@ install: chronyd chronyc chrony.txt
|
||||
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
|
||||
cp README $(DESTDIR)$(DOCDIR)/README
|
||||
chmod 644 $(DESTDIR)$(DOCDIR)/README
|
||||
cp chrony.1 $(DESTDIR)$(MANDIR)/man1
|
||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1
|
||||
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
|
||||
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
|
||||
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
|
||||
@@ -152,6 +150,12 @@ chrony.html : chrony.texi
|
||||
chrony.info : chrony.texi
|
||||
makeinfo chrony.texi
|
||||
|
||||
Makefile : Makefile.in configure
|
||||
@echo
|
||||
@echo Makefile needs to be regenerated, run ./configure
|
||||
@echo
|
||||
@exit 1
|
||||
|
||||
.deps:
|
||||
@mkdir .deps
|
||||
|
||||
|
||||
24
NEWS
24
NEWS
@@ -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
|
||||
==================
|
||||
|
||||
@@ -15,7 +34,7 @@ Enhancements
|
||||
* Improve source selection
|
||||
* Handle offline sources as unreachable
|
||||
* Open NTP server port only when necessary (client access is allowed by
|
||||
allow directive/command, peer or broadcast is configured)
|
||||
allow directive/command or peer/broadcast is configured)
|
||||
* Change default bindcmdaddress to loopback address
|
||||
* Change default maxdelay to 3 seconds
|
||||
* Change default stratumweight to 0.001
|
||||
@@ -30,6 +49,7 @@ Bug fixes
|
||||
---------
|
||||
* Add sanity checks for time and frequency offset
|
||||
* Don't report synchronised status during leap second
|
||||
* Don't combine reference clocks with close NTP sources
|
||||
* Fix accepting requests from configured sources
|
||||
* Fix initial fallback drift setting
|
||||
|
||||
@@ -39,7 +59,7 @@ New in version 1.31.1
|
||||
Security fixes
|
||||
--------------
|
||||
* Protect authenticated symmetric NTP associations against DoS attacks
|
||||
(CVE-2015-1799)
|
||||
(CVE-2015-1853)
|
||||
* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
|
||||
* Fix initialization of reply slots for authenticated commands (CVE-2015-1822)
|
||||
|
||||
|
||||
81
README
81
README
@@ -3,67 +3,35 @@ This is the README for chrony.
|
||||
What is chrony?
|
||||
===============
|
||||
|
||||
Chrony is a pair of programs for maintaining the accuracy of computer
|
||||
clocks.
|
||||
chrony is a versatile implementation of the Network Time Protocol (NTP).
|
||||
It can synchronize the system clock with NTP servers, reference clocks
|
||||
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
|
||||
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
|
||||
a time service to other computers in the network.
|
||||
|
||||
chronyd is a (background) daemon program that can be started at boot
|
||||
time. This does most of the work.
|
||||
It is designed to perform well in a wide range of conditions, including
|
||||
intermittent network connections, heavily congested networks, changing
|
||||
temperatures (ordinary computer clocks are sensitive to temperature),
|
||||
and systems that do not run continuosly, or run on a virtual machine.
|
||||
|
||||
chronyc is a command-line interface program which can be used to
|
||||
monitor chronyd's performance and to change various operating
|
||||
parameters whilst it is running.
|
||||
|
||||
chronyd's main function is to obtain measurements of the true (UTC)
|
||||
time from one of several sources, and correct the system clock
|
||||
accordingly. It also works out the rate at which the system clock
|
||||
gains or loses time and uses this information to keep it accurate
|
||||
between measurements from the reference.
|
||||
|
||||
The reference time can be derived from Network Time Protocol (NTP)
|
||||
servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
|
||||
The main source of information about the Network Time Protocol is
|
||||
http://www.ntp.org.
|
||||
|
||||
It is designed so that it can work on computers which only have
|
||||
intermittent access to reference sources, for example computers which
|
||||
use a dial-up account to access the Internet or laptops. Of course, it
|
||||
will work well on computers with permanent connections too.
|
||||
|
||||
In addition, on Linux it can monitor the system's real time clock
|
||||
performance, so the system can maintain accurate time even across
|
||||
reboots.
|
||||
|
||||
Typical accuracies available between 2 machines are
|
||||
|
||||
On an ethernet LAN : 100-200 microseconds, often much better
|
||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
||||
session to the next)
|
||||
|
||||
With a good reference clock the accuracy can reach one microsecond.
|
||||
|
||||
chronyd can also operate as an NTPv4 (RFC 5905) server, peer and broadcast
|
||||
server.
|
||||
Typical accuracy between two machines on a LAN is in tens, or a few
|
||||
hundreds, of microseconds; over the Internet, accuracy is typically
|
||||
within a few milliseconds. With a good hardware reference clock
|
||||
sub-microsecond accuracy is possible.
|
||||
|
||||
Two programs are included in chrony, chronyd is a daemon that can be
|
||||
started at boot time and chronyc is a command-line interface program
|
||||
which can be used to monitor chronyd's performance and to change various
|
||||
operating parameters whilst it is running.
|
||||
|
||||
What will chrony run on?
|
||||
========================
|
||||
|
||||
Chrony can be successfully built and run on
|
||||
|
||||
1. Linux 2.2.x, 2.3.x, 2.4.x, 2.6.x, 3.x
|
||||
|
||||
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
|
||||
|
||||
3. SunOS 4.1.4 (Sparc 2 and Sparc 20)
|
||||
|
||||
4. BSD/386 v1.1 has been reported to work using the SunOS 4.1 driver.
|
||||
|
||||
5. NetBSD.
|
||||
|
||||
Any other system will require a porting exercise. You would need to
|
||||
start from one of the existing system-specific drivers and look into
|
||||
the quirks of certain system calls and the kernel on your target
|
||||
system.
|
||||
The software is known to work on Linux, FreeBSD, NetBSD and Solaris.
|
||||
Closely related systems may work too. Any other system will likely
|
||||
require a porting exercise. You would need to start from one of the
|
||||
existing system-specific drivers and look into the quirks of certain
|
||||
system calls and the kernel on your target system.
|
||||
|
||||
How do I set it up?
|
||||
===================
|
||||
@@ -116,6 +84,11 @@ chrony-dev-request@chrony.tuxfamily.org
|
||||
|
||||
as applicable.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
chrony is distributed under the GNU General Public License version 2.
|
||||
|
||||
|
||||
Author
|
||||
======
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
|
||||
* Copyright (C) Miroslav Lichvar 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
||||
12
array.c
12
array.c
@@ -44,6 +44,8 @@ ARR_CreateInstance(unsigned int elem_size)
|
||||
{
|
||||
ARR_Instance array;
|
||||
|
||||
assert(elem_size > 0);
|
||||
|
||||
array = MallocNew(struct ARR_Instance_Record);
|
||||
|
||||
array->data = NULL;
|
||||
@@ -64,6 +66,9 @@ ARR_DestroyInstance(ARR_Instance array)
|
||||
static void
|
||||
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)
|
||||
return;
|
||||
|
||||
@@ -74,7 +79,10 @@ realloc_array(ARR_Instance array, unsigned int 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 *
|
||||
@@ -89,7 +97,7 @@ void *
|
||||
ARR_GetElement(ARR_Instance array, unsigned int index)
|
||||
{
|
||||
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 *
|
||||
|
||||
92
candm.h
92
candm.h
@@ -89,7 +89,9 @@
|
||||
#define REQ_RESELECT 48
|
||||
#define REQ_RESELECTDISTANCE 49
|
||||
#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
|
||||
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
|
||||
transmitted for each packet type. */
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Null;
|
||||
|
||||
typedef struct {
|
||||
IPAddr mask;
|
||||
IPAddr address;
|
||||
@@ -215,19 +221,11 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Manual;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_N_Sources;
|
||||
|
||||
typedef struct {
|
||||
int32_t index;
|
||||
int32_t EOR;
|
||||
} REQ_Source_Data;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Rekey;
|
||||
|
||||
typedef struct {
|
||||
IPAddr ip;
|
||||
int32_t subnet_bits;
|
||||
@@ -264,10 +262,6 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Del_Source;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_WriteRtc;
|
||||
|
||||
typedef struct {
|
||||
Float dfreq;
|
||||
int32_t EOR;
|
||||
@@ -279,27 +273,11 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Doffset;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Tracking;
|
||||
|
||||
typedef struct {
|
||||
uint32_t index;
|
||||
int32_t EOR;
|
||||
} 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
|
||||
request size */
|
||||
#define MAX_CLIENT_ACCESSES 8
|
||||
@@ -310,32 +288,24 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_ClientAccessesByIndex;
|
||||
|
||||
typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_ManualList;
|
||||
|
||||
typedef struct {
|
||||
int32_t index;
|
||||
int32_t EOR;
|
||||
} 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 {
|
||||
Float distance;
|
||||
int32_t EOR;
|
||||
} 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
|
||||
@@ -365,7 +335,7 @@ typedef struct {
|
||||
|
||||
Version 6 : added padding to requests to prevent amplification attack,
|
||||
changed maximum number of samples in manual list to 16, new commands: modify
|
||||
makestep
|
||||
makestep, smoothing report, smoothtime command
|
||||
*/
|
||||
|
||||
#define PROTO_VERSION_NUMBER 6
|
||||
@@ -398,6 +368,7 @@ typedef struct {
|
||||
uint32_t token; /* Command token (to prevent replay attack) */
|
||||
|
||||
union {
|
||||
REQ_Null null;
|
||||
REQ_Online online;
|
||||
REQ_Offline offline;
|
||||
REQ_Burst burst;
|
||||
@@ -415,28 +386,18 @@ typedef struct {
|
||||
REQ_Settime settime;
|
||||
REQ_Local local;
|
||||
REQ_Manual manual;
|
||||
REQ_N_Sources n_sources;
|
||||
REQ_Source_Data source_data;
|
||||
REQ_Rekey rekey;
|
||||
REQ_Allow_Deny allow_deny;
|
||||
REQ_Ac_Check ac_check;
|
||||
REQ_NTP_Source ntp_source;
|
||||
REQ_Del_Source del_source;
|
||||
REQ_WriteRtc writertc;
|
||||
REQ_Dfreq dfreq;
|
||||
REQ_Doffset doffset;
|
||||
REQ_Tracking tracking;
|
||||
REQ_Sourcestats sourcestats;
|
||||
REQ_RTCReport rtcreport;
|
||||
REQ_TrimRTC trimrtc;
|
||||
REQ_CycleLogs cyclelogs;
|
||||
REQ_ClientAccessesByIndex client_accesses_by_index;
|
||||
REQ_ManualList manual_list;
|
||||
REQ_ManualDelete manual_delete;
|
||||
REQ_MakeStep make_step;
|
||||
REQ_Activity activity;
|
||||
REQ_Reselect reselect;
|
||||
REQ_ReselectDistance reselect_distance;
|
||||
REQ_SmoothTime smoothtime;
|
||||
} data; /* Command specific parameters */
|
||||
|
||||
/* 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_MANUAL_LIST 11
|
||||
#define RPY_ACTIVITY 12
|
||||
#define N_REPLY_TYPES 13
|
||||
#define RPY_SMOOTHING 13
|
||||
#define N_REPLY_TYPES 14
|
||||
|
||||
/* Status codes */
|
||||
#define STT_SUCCESS 0
|
||||
@@ -627,6 +589,19 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} 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 {
|
||||
uint8_t version;
|
||||
uint8_t pkt_type;
|
||||
@@ -653,6 +628,7 @@ typedef struct {
|
||||
RPY_ClientAccessesByIndex client_accesses_by_index;
|
||||
RPY_ManualList manual_list;
|
||||
RPY_Activity activity;
|
||||
RPY_Smoothing smoothing;
|
||||
} data; /* Reply specific parameters */
|
||||
|
||||
/* authentication of the packet, there is no hole after the actual data
|
||||
|
||||
72
chrony.1
72
chrony.1
@@ -1,72 +0,0 @@
|
||||
.TH CHRONY 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual"
|
||||
.SH NAME
|
||||
chrony \- programs for keeping computer clocks accurate
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBchronyc\fR [\fIOPTIONS\fR]
|
||||
|
||||
\fBchronyd\fR [\fIOPTIONS\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBchrony\fR is a pair of programs for keeping computer clocks accurate.
|
||||
\fIchronyd\fR is a background (daemon) program and \fIchronyc\fR is a
|
||||
command-line interface to it. Time reference sources for chronyd can be
|
||||
NTP servers, human (via keyboard and \fIchronyc\fR), or the computer's
|
||||
real-time clock at boot time (Linux only). chronyd can determine the rate at
|
||||
which the computer gains or loses time and compensate for it while no external
|
||||
reference is present. Its use of NTP servers can be switched on and off
|
||||
(through \fIchronyc\fR) to support computers with dial-up/intermittent access
|
||||
to the Internet, and it can also act as an NTP server.
|
||||
|
||||
.SH USAGE
|
||||
\fIchronyc\fR is a command-line interface program which can be used to
|
||||
monitor \fIchronyd\fR's performance and to change various operating
|
||||
parameters whilst it is running.
|
||||
|
||||
\fIchronyd\fR's main function is to obtain measurements of the true (UTC)
|
||||
time from one of several sources, and correct the system clock
|
||||
accordingly. It also works out the rate at which the system clock
|
||||
gains or loses time and uses this information to keep it accurate
|
||||
between measurements from the reference.
|
||||
|
||||
The reference time can be derived from either Network Time Protocol
|
||||
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
|
||||
The main source of information about the Network Time Protocol is
|
||||
\fIhttp://www.ntp.org\fR.
|
||||
|
||||
It is designed so that it can work on computers which only have
|
||||
intermittent access to reference sources, for example computers which
|
||||
use a dial-up account to access the Internet or laptops. Of course, it
|
||||
will work well on computers with permanent connections too.
|
||||
|
||||
In addition, on Linux it can monitor the system's real time clock
|
||||
performance, so the system can maintain accurate time even across
|
||||
reboots.
|
||||
|
||||
Typical accuracies available between 2 machines are
|
||||
|
||||
On an ethernet LAN : 100-200 microseconds, often much better
|
||||
On a V32bis dial-up modem connection : 10's of milliseconds (from one
|
||||
session to the next)
|
||||
|
||||
With a good reference clock the accuracy can reach one microsecond.
|
||||
|
||||
\fIchronyd\fR can also operate as an NTPv4 (RFC 5905) server, peer and
|
||||
broadcast server.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chronyc(1),
|
||||
.BR chrony.conf(5),
|
||||
.BR chronyd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Curnow <rc@rc0.org.uk>
|
||||
|
||||
This man-page was written by Jan Schaumann <jschauma@netmeister.org> as part
|
||||
of "The Missing Man Pages Project". Please see
|
||||
\fIhttp://www.netmeister.org/misc/m2p2/index.html\fR for details.
|
||||
|
||||
The complete chrony documentation is supplied in texinfo format.
|
||||
|
||||
@@ -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
|
||||
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
|
||||
replace unreachable or bad servers automatically. The configuration file could
|
||||
in this case look like
|
||||
instead of multiple `server' directives. The configuration file could in this
|
||||
case look like
|
||||
|
||||
.EX
|
||||
pool pool.ntp.org iburst
|
||||
@@ -52,7 +51,6 @@ in this case look like
|
||||
.EE
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chrony(1),
|
||||
.BR chronyc(1),
|
||||
.BR chronyd(8)
|
||||
|
||||
|
||||
169
chrony.texi.in
169
chrony.texi.in
@@ -56,34 +56,30 @@ Copyright @copyright{} 2009-2014 Miroslav Lichvar
|
||||
@c {{{ S:Overview
|
||||
@node Overview
|
||||
@section Overview
|
||||
Chrony is a software package for maintaining the accuracy of computer
|
||||
system clocks. It consists of a pair of programs :
|
||||
chrony is a versatile implementation of the Network Time Protocol (NTP).
|
||||
It can synchronize the system clock with NTP servers, reference clocks
|
||||
(e.g. GPS receiver), and manual input using wristwatch and keyboard.
|
||||
It can also operate as an NTPv4 (RFC 5905) server and peer to provide
|
||||
a time service to other computers in the network.
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{chronyd}. This is a daemon which runs in background on the
|
||||
system. It obtains measurements (e.g. via the network) of the system's
|
||||
offset relative to other systems, and adjusts the system time
|
||||
accordingly. For isolated systems, the user can periodically enter the
|
||||
correct time by hand (using @code{chronyc}). In either case,
|
||||
@code{chronyd} determines the rate at which the computer gains or loses
|
||||
time, and compensates for this.
|
||||
It is designed to perform well in a wide range of conditions, including
|
||||
intermittent network connections, heavily congested networks, changing
|
||||
temperatures (ordinary computer clocks are sensitive to temperature),
|
||||
and systems that do not run continuosly, or run on a virtual machine.
|
||||
|
||||
@code{chronyd} can also act as an NTP server, and provide a time-of-day service
|
||||
to other computers. A typical set-up is to run @code{chronyd} on a gateway
|
||||
computer that has a dial-up link to the Internet, and use it to serve time to
|
||||
computers on a private LAN sitting behind the gateway. The IP addresses that
|
||||
can act as clients of @code{chronyd} can be tightly controlled. The default is
|
||||
no client access.
|
||||
Typical accuracy between two machines on a LAN is in tens, or a few
|
||||
hundreds, of microseconds; over the Internet, accuracy is typically
|
||||
within a few milliseconds. With a good hardware reference clock
|
||||
sub-microsecond accuracy is possible.
|
||||
|
||||
@item @code{chronyc}. This is a command-line driven control and
|
||||
monitoring program. An administrator can use this to fine-tune various
|
||||
parameters within the daemon, add or delete servers etc whilst the
|
||||
daemon is running.
|
||||
Two programs are included in chrony, @code{chronyd} is a daemon that can
|
||||
be started at boot time and @code{chronyc} is a command-line interface
|
||||
program which can be used to monitor @code{chronyd}'s performance and to
|
||||
change various operating parameters whilst it is running.
|
||||
|
||||
The IP addresses from which @code{chronyc} clients may connect can be tightly
|
||||
controlled. The default is just the computer that @code{chronyd} itself is
|
||||
running on.
|
||||
@end itemize
|
||||
@c }}}
|
||||
@c {{{ S:Acknowledgments
|
||||
@node Acknowledgements
|
||||
@@ -123,24 +119,10 @@ different operating systems may provide different function calls to
|
||||
achieve this, and even where the same function is used it may have
|
||||
different quirks in its behaviour.
|
||||
|
||||
The software is known to work in the following environments:
|
||||
@itemize @bullet
|
||||
@item Linux 2.2 and newer
|
||||
|
||||
@item NetBSD
|
||||
@item BSD/386
|
||||
|
||||
@item Solaris 2.3/2.5/2.5.1/2.6/2.7/2.8 on Sparc (Sparc 20, Ultrasparc) and
|
||||
i386
|
||||
|
||||
@item SunOS 4.1.4 on Sparc 2 and Sparc20.
|
||||
@end itemize
|
||||
|
||||
Closely related systems may work too, but they have not been tested.
|
||||
|
||||
Porting the software to other system (particularly to those supporting
|
||||
an @code{adjtime} system call) should not be difficult, however it
|
||||
requires access to such systems to test out the driver.
|
||||
The software is known to work on Linux, FreeBSD, NetBSD and Solaris. Closely
|
||||
related systems may work too. Porting the software to other systems
|
||||
(particularly to those supporting an @code{adjtime} system call) should not be
|
||||
difficult, however it requires access to such systems to test out the driver.
|
||||
@c }}}
|
||||
@c {{{ S:Other programs
|
||||
@node Other time synchronisation packages
|
||||
@@ -305,8 +287,7 @@ Particular areas that need addressing are :
|
||||
@item Porting to other Unices
|
||||
|
||||
This involves creating equivalents of sys_solaris.c, sys_linux.c etc for the
|
||||
new system. Note, the Linux driver has been reported as working on a range of
|
||||
different architectures (Alpha, Sparc, MIPS as well as x86 of course).
|
||||
new system.
|
||||
|
||||
@item Porting to Windows NT
|
||||
|
||||
@@ -600,9 +581,8 @@ rtcsync
|
||||
|
||||
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}
|
||||
directive instead of multiple @code{server} directives in order to allow
|
||||
@code{chronyd} to replace unreachable or bad servers automatically. The
|
||||
configuration file could in this case look like
|
||||
directive instead of multiple @code{server} directives. The configuration file
|
||||
could in this case look like
|
||||
|
||||
@example
|
||||
pool pool.ntp.org iburst
|
||||
@@ -1012,9 +992,8 @@ configuration file. This option is useful if you want to stop and
|
||||
restart @code{chronyd} briefly for any reason, e.g. to install a new
|
||||
version. However, it only makes sense on systems where the kernel can
|
||||
maintain clock compensation whilst not under @code{chronyd's} control.
|
||||
The only version where this happens so far is Linux. On systems where
|
||||
this is not the case, e.g. Solaris and SunOS the option should not be
|
||||
used.
|
||||
The only version where this happens so far is Linux. On other systems
|
||||
this option should not be used.
|
||||
@item -R
|
||||
When this option is used, the @code{initstepslew} directive and the
|
||||
@code{makestep} directive used with a positive limit will be ignored.
|
||||
@@ -2543,6 +2522,21 @@ be reported using the @code{clients} command in @code{chronyc}.
|
||||
The syntax of this directive is identical to that for the @code{server}
|
||||
directive (@pxref{server directive}), except that it is used to specify
|
||||
an NTP peer rather than an NTP server.
|
||||
|
||||
Please note that NTP peers that are not configured with a key to enable
|
||||
authentication are vulnerable to a denial-of-service attack. An attacker
|
||||
knowing that NTP hosts A and B are peering with each other can send a packet
|
||||
with random timestamps to host A with source address of B which will set the
|
||||
NTP state variables on A to the values sent by the attacker. Host A will then
|
||||
send on its next poll to B a packet with originate timestamp that doesn't match
|
||||
the transmit timestamp of B and the packet will be dropped. If the attacker
|
||||
does this periodically for both hosts, they won't be able to synchronize to
|
||||
each other.
|
||||
|
||||
This attack can be prevented by enabling authentication with the key option, or
|
||||
using the @code{server} directive on both sides to specify the other host as a
|
||||
server instead of peer, the only drawback is that it will double the network
|
||||
traffic between the two hosts.
|
||||
@c }}}
|
||||
@c {{{ pidfile
|
||||
@node pidfile directive
|
||||
@@ -3054,12 +3048,18 @@ falseticker or fail to select a source completely.
|
||||
|
||||
The smoothing process is independent from any slewing applied to the local
|
||||
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}
|
||||
directive or command.
|
||||
reset when the clock is corrected by stepping, e.g. by the @code{makestep}
|
||||
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
|
||||
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).
|
||||
frequency offset is allowed to change (in ppm per second). The smoothing
|
||||
process is activated automatically when 1/10000 of the estimated skew of the
|
||||
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
|
||||
interval could be
|
||||
@@ -3288,6 +3288,7 @@ password:
|
||||
@item @code{password}
|
||||
@item @code{quit}
|
||||
@item @code{rtcdata}
|
||||
@item @code{smoothing}
|
||||
@item @code{sources}
|
||||
@item @code{sourcestats}
|
||||
@item @code{tracking}
|
||||
@@ -3348,6 +3349,8 @@ interface.
|
||||
* retries command:: Set maximum number of retries
|
||||
* rtcdata command:: Display RTC parameters
|
||||
* 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
|
||||
* sourcestats command:: Display the rate & offset estimation performance of sources
|
||||
* timeout command:: Set initial response timeout
|
||||
@@ -4165,9 +4168,7 @@ password
|
||||
@end example
|
||||
|
||||
The computer will respond with a @samp{Password:} prompt, at which you
|
||||
should enter the password and press return. (Note that the no-echo mode
|
||||
is limited to 8 characters on SunOS 4.1 due to limitations in the system
|
||||
library. Other systems do not have this restriction.)
|
||||
should enter the password and press return.
|
||||
|
||||
The password can be encoded as a string of characters not containing a space
|
||||
with optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:}
|
||||
@@ -4326,6 +4327,66 @@ settime Nov 21, 1997 16:30:05
|
||||
|
||||
For a full description of @code{getdate}, get hold of the getdate
|
||||
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 {{{ sources
|
||||
@node sources command
|
||||
@@ -4551,7 +4612,7 @@ true time (which it reports to NTP clients when it is operating in
|
||||
server mode). The value reported on this line is the difference due to
|
||||
this effect.
|
||||
|
||||
On systems such as Solaris and SunOS, @code{chronyd} has no means to
|
||||
On systems other than Linux, @code{chronyd} doesn't
|
||||
adjust the fundamental rate of the system clock, so keeps the system
|
||||
time correct by periodically making offsets to it as though an error had
|
||||
been measured. The build up of these offsets will be observed in this
|
||||
|
||||
@@ -60,8 +60,7 @@ interactively.
|
||||
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR chronyd(8),
|
||||
.BR chrony(1)
|
||||
.BR chronyd(8)
|
||||
|
||||
.I http://chrony.tuxfamily.org/
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ option is useful if you want to stop and restart \fBchronyd\fR briefly for any
|
||||
reason, e.g. to install a new version. However, it only makes sense on
|
||||
systems where the kernel can maintain clock compensation whilst not under
|
||||
\fBchronyd\fR's control. The only version where this happens so far is Linux.
|
||||
On systems where this is not the case, e.g. Solaris and SunOS the option
|
||||
should not be used.
|
||||
On other systems this option should not be used.
|
||||
.TP
|
||||
.B \-R
|
||||
When this option is used, the \fIinitstepslew\fR directive and the
|
||||
@@ -135,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
|
||||
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR).
|
||||
|
||||
.BR chrony(1),
|
||||
.BR chronyc(1),
|
||||
.BR chrony.conf(5),
|
||||
.BR hwclock(8),
|
||||
|
||||
77
client.c
77
client.c
@@ -640,7 +640,8 @@ process_cmd_manual(CMD_Request *msg, const char *line)
|
||||
static int
|
||||
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;
|
||||
char *p;
|
||||
|
||||
@@ -657,7 +658,7 @@ parse_allow_deny(CMD_Request *msg, char *line)
|
||||
|
||||
n = 0;
|
||||
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 */
|
||||
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);
|
||||
|
||||
if (slashpos) {
|
||||
int specified_subnet_bits, n;
|
||||
n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
|
||||
if (n == 1) {
|
||||
msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits);
|
||||
@@ -1184,6 +1184,8 @@ give_help(void)
|
||||
printf("reselect : Reselect synchronisation source\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("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("sourcestats [-v] : Display estimation information about current sources\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
|
||||
process_cmd_rtcreport(char *line)
|
||||
{
|
||||
@@ -2535,6 +2594,11 @@ process_line(char *line, int *quit)
|
||||
} else if (!strcmp(command, "settime")) {
|
||||
do_normal_submit = 0;
|
||||
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")) {
|
||||
do_normal_submit = 0;
|
||||
ret = process_cmd_sources(line);
|
||||
@@ -2729,10 +2793,11 @@ main(int argc, char **argv)
|
||||
family = IPADDR_INET6;
|
||||
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
|
||||
printf("chronyc (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYC_FEATURES);
|
||||
exit(0);
|
||||
return 0;
|
||||
} else if (!strncmp(*argv, "-", 1)) {
|
||||
fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [-a] [-f <file>]] [command]\n", progname);
|
||||
exit(1);
|
||||
fprintf(stderr, "Usage: %s [-h HOST] [-p PORT] [-n] [-4|-6] [-a] [-f FILE] [-m] [COMMAND]\n",
|
||||
progname);
|
||||
return 1;
|
||||
} else {
|
||||
break; /* And process remainder of line as a command */
|
||||
}
|
||||
|
||||
368
cmdmon.c
368
cmdmon.c
@@ -37,6 +37,7 @@
|
||||
#include "keys.h"
|
||||
#include "ntp_sources.h"
|
||||
#include "ntp_core.h"
|
||||
#include "smooth.h"
|
||||
#include "sources.h"
|
||||
#include "sourcestats.h"
|
||||
#include "reference.h"
|
||||
@@ -162,6 +163,8 @@ static const char permissions[] = {
|
||||
PERMIT_AUTH, /* RESELECT */
|
||||
PERMIT_AUTH, /* RESELECTDISTANCE */
|
||||
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
|
||||
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,16 +728,12 @@ handle_null(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address, mask;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.online.mask, &mask);
|
||||
UTI_IPNetworkToHost(&rx_message->data.online.address, &address);
|
||||
status = NSR_TakeSourcesOnline(&mask, &address);
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_TakeSourcesOnline(&mask, &address))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -743,16 +741,12 @@ handle_online(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address, mask;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.offline.mask, &mask);
|
||||
UTI_IPNetworkToHost(&rx_message->data.offline.address, &address);
|
||||
status = NSR_TakeSourcesOffline(&mask, &address);
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_TakeSourcesOffline(&mask, &address))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -760,19 +754,14 @@ handle_offline(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address, mask;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.burst.mask, &mask);
|
||||
UTI_IPNetworkToHost(&rx_message->data.burst.address, &address);
|
||||
status = NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
|
||||
ntohl(rx_message->data.burst.n_total_samples),
|
||||
&mask, &address);
|
||||
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_InitiateSampleBurst(ntohl(rx_message->data.burst.n_good_samples),
|
||||
ntohl(rx_message->data.burst.n_total_samples),
|
||||
&mask, &address))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -780,17 +769,12 @@ handle_burst(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
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) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMinpoll(&address,
|
||||
ntohl(rx_message->data.modify_minpoll.new_minpoll)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -798,17 +782,12 @@ handle_modify_minpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
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) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMaxpoll(&address,
|
||||
ntohl(rx_message->data.modify_minpoll.new_minpoll)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -816,16 +795,12 @@ handle_modify_maxpoll(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
|
||||
status = NSR_ModifyMaxdelay(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay));
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMaxdelay(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -833,16 +808,12 @@ handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
|
||||
status = NSR_ModifyMaxdelayratio(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMaxdelayratio(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -850,16 +821,12 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelaydevratio.address, &address);
|
||||
status = NSR_ModifyMaxdelaydevratio(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio));
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMaxdelaydevratio(&address,
|
||||
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelaydevratio.new_max_delay_dev_ratio)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -867,17 +834,12 @@ handle_modify_maxdelaydevratio(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_minpoll.address, &address);
|
||||
status = NSR_ModifyMinstratum(&address,
|
||||
ntohl(rx_message->data.modify_minstratum.new_min_stratum));
|
||||
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyMinstratum(&address,
|
||||
ntohl(rx_message->data.modify_minstratum.new_min_stratum)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -885,17 +847,12 @@ handle_modify_minstratum(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_modify_polltarget(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
IPAddr address;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_polltarget.address, &address);
|
||||
status = NSR_ModifyPolltarget(&address,
|
||||
ntohl(rx_message->data.modify_polltarget.new_poll_target));
|
||||
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NSR_ModifyPolltarget(&address,
|
||||
ntohl(rx_message->data.modify_polltarget.new_poll_target)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -904,7 +861,6 @@ static void
|
||||
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
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),
|
||||
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()) {
|
||||
tx_message->status = htons(STT_NOTENABLED);
|
||||
} 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->data.manual_timestamp.centiseconds = htonl((int32_t)offset_cs);
|
||||
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 {
|
||||
REF_DisableLocal();
|
||||
}
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -972,8 +925,10 @@ handle_manual(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
case 2:
|
||||
MNL_Reset();
|
||||
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;
|
||||
n_sources = SRC_ReadNumberOfSources();
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_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;
|
||||
|
||||
/* 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)) {
|
||||
switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
|
||||
case SRC_NTP:
|
||||
@@ -1008,7 +962,6 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
break;
|
||||
}
|
||||
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_SOURCE_DATA);
|
||||
|
||||
UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.source_data.ip_addr);
|
||||
@@ -1071,136 +1024,35 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_rekey(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
KEY_Reload();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
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;
|
||||
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, 1, 0)) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!NCR_AddAccessRestriction(&ip, subnet_bits, allow, all))
|
||||
tx_message->status = htons(STT_BADSUBNET);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
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;
|
||||
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, 1, 1)) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!CAM_AddAccessRestriction(&ip, subnet_bits, allow, all))
|
||||
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, ¶ms);
|
||||
switch (status) {
|
||||
case NSR_Success:
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
break;
|
||||
case NSR_AlreadyInUse:
|
||||
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);
|
||||
switch (status) {
|
||||
case NSR_Success:
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
break;
|
||||
case NSR_NoSuchSource:
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
@@ -1317,7 +1167,6 @@ handle_writertc(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
switch (RTC_WriteParameters()) {
|
||||
case RTC_ST_OK:
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
break;
|
||||
case RTC_ST_NODRV:
|
||||
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);
|
||||
LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
|
||||
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;
|
||||
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
|
||||
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;
|
||||
|
||||
REF_GetTrackingReport(&rpt);
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_TRACKING);
|
||||
tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
|
||||
UTI_IPHostToNetwork(&rpt.ip_addr, &tx_message->data.tracking.ip_addr);
|
||||
@@ -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
|
||||
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;
|
||||
struct timeval now_corr;
|
||||
|
||||
LCL_ReadCookedTime(&now_corr, NULL);
|
||||
SCH_GetLastEventTime(&now_corr, NULL, NULL);
|
||||
status = SRC_ReportSourcestats(ntohl(rx_message->data.sourcestats.index),
|
||||
&report, &now_corr);
|
||||
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_SOURCESTATS);
|
||||
tx_message->data.sourcestats.ref_id = htonl(report.ref_id);
|
||||
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;
|
||||
status = RTC_GetReport(&report);
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_RTC);
|
||||
UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
|
||||
tx_message->data.rtc.n_samples = htons(report.n_samples);
|
||||
@@ -1439,13 +1337,8 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
static void
|
||||
handle_trimrtc(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
status = RTC_Trim();
|
||||
if (status) {
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
} else {
|
||||
if (!RTC_Trim())
|
||||
tx_message->status = htons(STT_NORTC);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1454,8 +1347,6 @@ static void
|
||||
handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
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;
|
||||
struct timeval now;
|
||||
|
||||
LCL_ReadCookedTime(&now, NULL);
|
||||
SCH_GetLastEventTime(&now, NULL, NULL);
|
||||
|
||||
first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
|
||||
n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices);
|
||||
if (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);
|
||||
|
||||
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;
|
||||
RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];
|
||||
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_MANUAL_LIST);
|
||||
|
||||
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
|
||||
handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
int status;
|
||||
int index;
|
||||
|
||||
index = ntohl(rx_message->data.manual_delete.index);
|
||||
status = MNL_DeleteSample(index);
|
||||
if (!status) {
|
||||
if (!MNL_DeleteSample(index))
|
||||
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
|
||||
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
if (!LCL_MakeStep()) {
|
||||
if (!LCL_MakeStep())
|
||||
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_offline = htonl(report.burst_offline);
|
||||
tx_message->data.activity.unresolved = htonl(report.unresolved);
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
tx_message->reply = htons(RPY_ACTIVITY);
|
||||
}
|
||||
|
||||
@@ -1588,7 +1468,6 @@ handle_reselect_distance(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
double dist;
|
||||
dist = UTI_FloatNetworkToHost(rx_message->data.reselect_distance.distance);
|
||||
SRC_SetReselectDistance(dist);
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1597,7 +1476,6 @@ static void
|
||||
handle_reselect(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
SRC_ReselectSource();
|
||||
tx_message->status = htons(STT_SUCCESS);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1653,8 +1531,8 @@ read_from_cmd_socket(void *anything)
|
||||
|
||||
read_length = status;
|
||||
|
||||
LCL_ReadRawTime(&now);
|
||||
LCL_CookTime(&now, &cooked_now, NULL);
|
||||
/* Get current time cheaply */
|
||||
SCH_GetLastEventTime(&cooked_now, NULL, &now);
|
||||
|
||||
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.sequence = rx_message.sequence;
|
||||
tx_message.reply = htons(RPY_NULL);
|
||||
tx_message.status = htons(STT_SUCCESS);
|
||||
tx_message.pad1 = 0;
|
||||
tx_message.pad2 = 0;
|
||||
tx_message.pad3 = 0;
|
||||
@@ -1909,7 +1788,11 @@ read_from_cmd_socket(void *anything)
|
||||
if (allowed) {
|
||||
switch(rx_command) {
|
||||
case REQ_NULL:
|
||||
handle_null(&rx_message, &tx_message);
|
||||
/* Do nothing */
|
||||
break;
|
||||
|
||||
case REQ_DUMP:
|
||||
handle_dump(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_ONLINE:
|
||||
@@ -1932,11 +1815,6 @@ read_from_cmd_socket(void *anything)
|
||||
handle_modify_maxpoll(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_DUMP:
|
||||
SRC_DumpSources();
|
||||
tx_message.status = htons(STT_SUCCESS);
|
||||
break;
|
||||
|
||||
case REQ_MODIFY_MAXDELAY:
|
||||
handle_modify_maxdelay(&rx_message, &tx_message);
|
||||
break;
|
||||
@@ -2004,35 +1882,35 @@ read_from_cmd_socket(void *anything)
|
||||
break;
|
||||
|
||||
case REQ_ALLOW:
|
||||
handle_allow(&rx_message, &tx_message);
|
||||
handle_allowdeny(&rx_message, &tx_message, 1, 0);
|
||||
break;
|
||||
|
||||
case REQ_ALLOWALL:
|
||||
handle_allowall(&rx_message, &tx_message);
|
||||
handle_allowdeny(&rx_message, &tx_message, 1, 1);
|
||||
break;
|
||||
|
||||
case REQ_DENY:
|
||||
handle_deny(&rx_message, &tx_message);
|
||||
handle_allowdeny(&rx_message, &tx_message, 0, 0);
|
||||
break;
|
||||
|
||||
case REQ_DENYALL:
|
||||
handle_denyall(&rx_message, &tx_message);
|
||||
handle_allowdeny(&rx_message, &tx_message, 0, 1);
|
||||
break;
|
||||
|
||||
case REQ_CMDALLOW:
|
||||
handle_cmdallow(&rx_message, &tx_message);
|
||||
handle_cmdallowdeny(&rx_message, &tx_message, 1, 0);
|
||||
break;
|
||||
|
||||
case REQ_CMDALLOWALL:
|
||||
handle_cmdallowall(&rx_message, &tx_message);
|
||||
handle_cmdallowdeny(&rx_message, &tx_message, 1, 1);
|
||||
break;
|
||||
|
||||
case REQ_CMDDENY:
|
||||
handle_cmddeny(&rx_message, &tx_message);
|
||||
handle_cmdallowdeny(&rx_message, &tx_message, 0, 0);
|
||||
break;
|
||||
|
||||
case REQ_CMDDENYALL:
|
||||
handle_cmddenyall(&rx_message, &tx_message);
|
||||
handle_cmdallowdeny(&rx_message, &tx_message, 0, 1);
|
||||
break;
|
||||
|
||||
case REQ_ACCHECK:
|
||||
@@ -2071,6 +1949,14 @@ read_from_cmd_socket(void *anything)
|
||||
handle_tracking(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_SMOOTHING:
|
||||
handle_smoothing(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_SMOOTHTIME:
|
||||
handle_smoothtime(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_SOURCESTATS:
|
||||
handle_sourcestats(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2013
|
||||
* Copyright (C) Miroslav Lichvar 2013-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
||||
20
conf.c
20
conf.c
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
||||
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -189,6 +189,7 @@ static char *pidfile;
|
||||
/* Smoothing constants */
|
||||
static double smooth_max_freq = 0.0; /* in ppm */
|
||||
static double smooth_max_wander = 0.0; /* in ppm/s */
|
||||
static int smooth_leap_only = 0;
|
||||
|
||||
/* Temperature sensor, update interval and compensation coefficients */
|
||||
static char *tempcomp_sensor_file = NULL;
|
||||
@@ -1174,11 +1175,23 @@ parse_broadcast(char *line)
|
||||
static void
|
||||
parse_smoothtime(char *line)
|
||||
{
|
||||
check_number_of_args(line, 2);
|
||||
if (get_number_of_args(line) != 3)
|
||||
check_number_of_args(line, 2);
|
||||
|
||||
if (sscanf(line, "%lf %lf", &smooth_max_freq, &smooth_max_wander) != 2) {
|
||||
smooth_max_freq = 0.0;
|
||||
command_parse_error();
|
||||
}
|
||||
|
||||
line = CPS_SplitWord(CPS_SplitWord(line));
|
||||
smooth_leap_only = 0;
|
||||
|
||||
if (*line) {
|
||||
if (!strcasecmp(line, "leaponly"))
|
||||
smooth_leap_only = 1;
|
||||
else
|
||||
command_parse_error();
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1738,10 +1751,11 @@ CNF_GetLockMemory(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_wander = smooth_max_wander;
|
||||
*leap_only = smooth_leap_only;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
2
conf.h
2
conf.h
@@ -96,7 +96,7 @@ extern void CNF_SetupAccessRestrictions(void);
|
||||
extern int CNF_GetSchedPriority(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 char *CNF_GetUser(void);
|
||||
|
||||
@@ -45,7 +45,6 @@ cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
|
||||
%{_sbindir}/chronyd
|
||||
%{_bindir}/chronyc
|
||||
%{_infodir}/chrony.info*
|
||||
%{_mandir}/man1/chrony.1.gz
|
||||
%{_mandir}/man1/chronyc.1.gz
|
||||
%{_mandir}/man5/chrony.conf.5.gz
|
||||
%{_mandir}/man8/chronyd.8.gz
|
||||
|
||||
5
local.c
5
local.c
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2011, 2014
|
||||
* Copyright (C) Miroslav Lichvar 2011, 2014-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -564,6 +564,9 @@ LCL_NotifyLeap(int leap)
|
||||
LCL_ReadRawTime(&raw);
|
||||
LCL_CookTime(&raw, &cooked, NULL);
|
||||
|
||||
/* Smooth the leap second out */
|
||||
SMT_Leap(&cooked, leap);
|
||||
|
||||
/* Dispatch to all handlers as if the clock was stepped */
|
||||
invoke_parameter_change_handlers(&raw, &cooked, 0.0, -leap, LCL_ChangeStep);
|
||||
}
|
||||
|
||||
9
main.c
9
main.c
@@ -347,6 +347,7 @@ int main
|
||||
(int argc, char **argv)
|
||||
{
|
||||
const char *conf_file = DEFAULT_CONF_FILE;
|
||||
const char *progname = argv[0];
|
||||
char *user = NULL;
|
||||
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
|
||||
int do_init_rtc = 0, restarted = 0;
|
||||
@@ -386,7 +387,7 @@ int main
|
||||
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
|
||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||
printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
|
||||
exit(0);
|
||||
return 0;
|
||||
} else if (!strcmp("-n", *argv)) {
|
||||
nofork = 1;
|
||||
} else if (!strcmp("-d", *argv)) {
|
||||
@@ -405,6 +406,10 @@ int main
|
||||
address_family = IPADDR_INET4;
|
||||
} else if (!strcmp("-6", *argv)) {
|
||||
address_family = IPADDR_INET6;
|
||||
} else if (!strcmp("-h", *argv) || !strcmp("--help", *argv)) {
|
||||
printf("Usage: %s [-4|-6] [-n|-d] [-q|-Q] [-r] [-R] [-s] [-f FILE|COMMAND...]\n",
|
||||
progname);
|
||||
return 0;
|
||||
} else if (*argv[0] == '-') {
|
||||
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
||||
} else {
|
||||
@@ -417,7 +422,7 @@ int main
|
||||
if (getuid() != 0) {
|
||||
/* This write to the terminal is OK, it comes before we turn into a daemon */
|
||||
fprintf(stderr,"Not superuser\n");
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Turn into a daemon */
|
||||
|
||||
@@ -39,7 +39,7 @@ echo $version > version.txt
|
||||
|
||||
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}%" \
|
||||
< $m > ${m}_
|
||||
mv -f ${m}_ $m
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
||||
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -316,7 +316,7 @@ NCR_Initialise(void)
|
||||
do_time_checks();
|
||||
|
||||
logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
|
||||
" Date (UTC) Time IP Address L St 123 567 ABCD LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
" Date (UTC) Time IP Address L St 123 567 ABCD LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
: -1;
|
||||
|
||||
access_auth_table = ADF_CreateTable();
|
||||
@@ -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;
|
||||
|
||||
if (valid_packet) {
|
||||
precision = LCL_GetSysPrecisionAsQuantum();
|
||||
precision = LCL_GetSysPrecisionAsQuantum() +
|
||||
UTI_Log2ToDouble(message->precision);
|
||||
|
||||
SRC_GetFrequencyRange(inst->source, &source_freq_lo, &source_freq_hi);
|
||||
|
||||
|
||||
11
ntp_io.c
11
ntp_io.c
@@ -4,7 +4,7 @@
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Timo Teras 2009
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2014
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2013-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -97,8 +97,13 @@ prepare_socket(int family, int port_number, int client_only)
|
||||
sock_fd = socket(family, SOCK_DGRAM, 0);
|
||||
|
||||
if (sock_fd < 0) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||
if (!client_only) {
|
||||
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||
} else {
|
||||
DEBUG_LOG(LOGF_NtpIO, "Could not open %s NTP socket : %s",
|
||||
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
|
||||
}
|
||||
return INVALID_SOCK_FD;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef struct {
|
||||
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
|
||||
means this slot in table is in use */
|
||||
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
|
||||
added or INVALID_POOL */
|
||||
int tentative; /* Flag indicating there was no valid response
|
||||
@@ -85,6 +86,7 @@ struct UnresolvedSource {
|
||||
#define RESOLVE_INTERVAL_UNIT 7
|
||||
#define MIN_RESOLVE_INTERVAL 2
|
||||
#define MAX_RESOLVE_INTERVAL 9
|
||||
#define MIN_REPLACEMENT_INTERVAL 8
|
||||
|
||||
static struct UnresolvedSource *unresolved_sources = NULL;
|
||||
static int resolving_interval = 0;
|
||||
@@ -92,15 +94,11 @@ static SCH_TimeoutID resolving_id;
|
||||
static struct UnresolvedSource *resolving_source = NULL;
|
||||
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
||||
|
||||
#define MIN_POOL_RESOLVE_INTERVAL 5
|
||||
#define MAX_POOL_SOURCES 16
|
||||
#define INVALID_POOL (-1)
|
||||
|
||||
/* Pool of sources, the name is expected to resolve to multiple addresses
|
||||
which change over time */
|
||||
/* Pool of sources with the same name */
|
||||
struct SourcePool {
|
||||
char *name;
|
||||
int port;
|
||||
/* Number of sources added from this pool (ignoring tentative sources) */
|
||||
int sources;
|
||||
/* Maximum number of sources */
|
||||
@@ -115,6 +113,7 @@ static ARR_Instance pools;
|
||||
|
||||
static void resolve_sources(void *arg);
|
||||
static void rehash_records(void);
|
||||
static void clean_source_record(SourceRecord *record);
|
||||
|
||||
static void
|
||||
slew_sources(struct timeval *raw,
|
||||
@@ -162,16 +161,12 @@ NSR_Finalise(void)
|
||||
struct UnresolvedSource *us;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(pools); i++)
|
||||
Free(((struct SourcePool *)ARR_GetElement(pools, i))->name);
|
||||
ARR_DestroyInstance(pools);
|
||||
|
||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||
record = get_record(i);
|
||||
if (!record->remote_addr)
|
||||
continue;
|
||||
record->remote_addr = NULL;
|
||||
NCR_DestroyInstance(record->data);
|
||||
if (record->remote_addr)
|
||||
clean_source_record(record);
|
||||
}
|
||||
|
||||
ARR_DestroyInstance(records);
|
||||
@@ -296,7 +291,7 @@ rehash_records(void)
|
||||
|
||||
/* Procedure to add a new source */
|
||||
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;
|
||||
int slot, found;
|
||||
@@ -323,6 +318,7 @@ add_source(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParamete
|
||||
record = get_record(slot);
|
||||
record->data = NCR_GetInstance(remote_addr, type, params);
|
||||
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
||||
record->name = name ? Strdup(name) : NULL;
|
||||
record->pool = pool;
|
||||
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)
|
||||
break;
|
||||
} 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)
|
||||
added++;
|
||||
|
||||
@@ -495,7 +491,7 @@ append_unresolved_source(struct UnresolvedSource *us)
|
||||
NSR_Status
|
||||
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 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->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;
|
||||
} else {
|
||||
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
||||
sp->name = Strdup(name);
|
||||
sp->port = port;
|
||||
sp->sources = 0;
|
||||
sp->max_sources = params->max_sources;
|
||||
us->new_source.pool = ARR_GetSize(pools) - 1;
|
||||
@@ -587,6 +590,8 @@ clean_source_record(SourceRecord *record)
|
||||
assert(record->remote_addr);
|
||||
record->remote_addr = NULL;
|
||||
NCR_DestroyInstance(record->data);
|
||||
if (record->name)
|
||||
Free(record->name);
|
||||
|
||||
n_sources--;
|
||||
}
|
||||
@@ -640,15 +645,18 @@ NSR_RemoveAllSources(void)
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
resolve_pool_replacement(struct SourcePool *sp, NTP_Remote_Address *addr)
|
||||
resolve_source_replacement(SourceRecord *record)
|
||||
{
|
||||
struct UnresolvedSource *us;
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSources, "trying to replace %s",
|
||||
UTI_IPToString(&record->remote_addr->ip_addr));
|
||||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
us->name = Strdup(sp->name);
|
||||
us->port = sp->port;
|
||||
us->name = Strdup(record->name);
|
||||
us->port = record->remote_addr->port;
|
||||
us->replacement = 1;
|
||||
us->replace_source = *addr;
|
||||
us->replace_source = *record->remote_addr;
|
||||
|
||||
append_unresolved_source(us);
|
||||
NSR_ResolveSources();
|
||||
@@ -662,32 +670,33 @@ NSR_HandleBadSource(IPAddr *address)
|
||||
static struct timeval last_replacement;
|
||||
struct timeval now;
|
||||
NTP_Remote_Address remote_addr;
|
||||
struct SourcePool *pool;
|
||||
int pool_index, slot, found;
|
||||
SourceRecord *record;
|
||||
int slot, found;
|
||||
double diff;
|
||||
|
||||
remote_addr.ip_addr = *address;
|
||||
remote_addr.port = 0;
|
||||
|
||||
/* Only sources from a pool can be replaced */
|
||||
find_slot(&remote_addr, &slot, &found);
|
||||
if (!found || (pool_index = get_record(slot)->pool) == INVALID_POOL)
|
||||
if (!found)
|
||||
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);
|
||||
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");
|
||||
return;
|
||||
}
|
||||
last_replacement = now;
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSources, "pool replacement for %s", UTI_IPToString(address));
|
||||
|
||||
resolve_pool_replacement(pool, &remote_addr);
|
||||
resolve_source_replacement(record);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -741,7 +750,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP
|
||||
pool->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
|
||||
the tentative sources added from this pool */
|
||||
|
||||
58
pktlength.c
58
pktlength.c
@@ -44,9 +44,8 @@ command_unpadded_length(CMD_Request *r)
|
||||
return 0;
|
||||
} else {
|
||||
switch (type) {
|
||||
|
||||
case REQ_NULL:
|
||||
return offsetof(CMD_Request, data);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ONLINE:
|
||||
return offsetof(CMD_Request, data.online.EOR);
|
||||
case REQ_OFFLINE:
|
||||
@@ -78,11 +77,11 @@ command_unpadded_length(CMD_Request *r)
|
||||
case REQ_MANUAL :
|
||||
return offsetof(CMD_Request, data.manual.EOR);
|
||||
case REQ_N_SOURCES :
|
||||
return offsetof(CMD_Request, data.n_sources.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SOURCE_DATA :
|
||||
return offsetof(CMD_Request, data.source_data.EOR);
|
||||
case REQ_REKEY :
|
||||
return offsetof(CMD_Request, data.rekey.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ALLOW :
|
||||
return offsetof(CMD_Request, data.allow_deny.EOR);
|
||||
case REQ_ALLOWALL :
|
||||
@@ -110,21 +109,21 @@ command_unpadded_length(CMD_Request *r)
|
||||
case REQ_DEL_SOURCE :
|
||||
return offsetof(CMD_Request, data.del_source.EOR);
|
||||
case REQ_WRITERTC :
|
||||
return offsetof(CMD_Request, data.writertc.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_DFREQ :
|
||||
return offsetof(CMD_Request, data.dfreq.EOR);
|
||||
case REQ_DOFFSET :
|
||||
return offsetof(CMD_Request, data.doffset.EOR);
|
||||
case REQ_TRACKING :
|
||||
return offsetof(CMD_Request, data.tracking.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SOURCESTATS :
|
||||
return offsetof(CMD_Request, data.sourcestats.EOR);
|
||||
case REQ_RTCREPORT :
|
||||
return offsetof(CMD_Request, data.rtcreport.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_TRIMRTC :
|
||||
return offsetof(CMD_Request, data.trimrtc.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_CYCLELOGS :
|
||||
return offsetof(CMD_Request, data.cyclelogs.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SUBNETS_ACCESSED :
|
||||
case REQ_CLIENT_ACCESSES:
|
||||
/* No longer supported */
|
||||
@@ -132,21 +131,25 @@ command_unpadded_length(CMD_Request *r)
|
||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||
return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
|
||||
case REQ_MANUAL_LIST:
|
||||
return offsetof(CMD_Request, data.manual_list.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_MANUAL_DELETE:
|
||||
return offsetof(CMD_Request, data.manual_delete.EOR);
|
||||
case REQ_MAKESTEP:
|
||||
return offsetof(CMD_Request, data.make_step.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_ACTIVITY:
|
||||
return offsetof(CMD_Request, data.activity.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_RESELECT:
|
||||
return offsetof(CMD_Request, data.reselect.EOR);
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_RESELECTDISTANCE:
|
||||
return offsetof(CMD_Request, data.reselect_distance.EOR);
|
||||
case REQ_MODIFY_MINSTRATUM:
|
||||
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
||||
case REQ_MODIFY_POLLTARGET:
|
||||
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
||||
case REQ_SMOOTHING:
|
||||
return offsetof(CMD_Request, data.null.EOR);
|
||||
case REQ_SMOOTHTIME:
|
||||
return offsetof(CMD_Request, data.smoothtime.EOR);
|
||||
default:
|
||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||
assert(0);
|
||||
@@ -228,11 +231,11 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
||||
case REQ_MANUAL:
|
||||
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
|
||||
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:
|
||||
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
|
||||
case REQ_REKEY:
|
||||
return PADDING_LENGTH(data.rekey.EOR, data.null.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_ALLOW:
|
||||
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
|
||||
case REQ_ALLOWALL:
|
||||
@@ -260,21 +263,21 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
||||
case REQ_DEL_SOURCE:
|
||||
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
|
||||
case REQ_WRITERTC:
|
||||
return PADDING_LENGTH(data.writertc.EOR, data.null.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_DFREQ:
|
||||
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
|
||||
case REQ_DOFFSET:
|
||||
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
|
||||
case REQ_TRACKING:
|
||||
return PADDING_LENGTH(data.tracking.EOR, data.tracking.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.tracking.EOR);
|
||||
case REQ_SOURCESTATS:
|
||||
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
|
||||
case REQ_RTCREPORT:
|
||||
return PADDING_LENGTH(data.rtcreport.EOR, data.rtc.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.rtc.EOR);
|
||||
case REQ_TRIMRTC:
|
||||
return PADDING_LENGTH(data.trimrtc.EOR, data.null.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
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_CLIENT_ACCESSES:
|
||||
/* No longer supported */
|
||||
@@ -282,21 +285,25 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
||||
case REQ_CLIENT_ACCESSES_BY_INDEX:
|
||||
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
|
||||
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:
|
||||
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
|
||||
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:
|
||||
return PADDING_LENGTH(data.activity.EOR, data.activity.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.activity.EOR);
|
||||
case REQ_RESELECT:
|
||||
return PADDING_LENGTH(data.reselect.EOR, data.null.EOR);
|
||||
return PADDING_LENGTH(data.null.EOR, data.null.EOR);
|
||||
case REQ_RESELECTDISTANCE:
|
||||
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_MINSTRATUM:
|
||||
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
||||
case REQ_MODIFY_POLLTARGET:
|
||||
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:
|
||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||
assert(0);
|
||||
@@ -360,7 +367,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
||||
}
|
||||
case RPY_ACTIVITY:
|
||||
return offsetof(CMD_Reply, data.activity.EOR);
|
||||
|
||||
case RPY_SMOOTHING:
|
||||
return offsetof(CMD_Reply, data.smoothing.EOR);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
13
refclock.c
13
refclock.c
@@ -499,15 +499,6 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static double
|
||||
poll_interval(int poll)
|
||||
{
|
||||
if (poll >= 0)
|
||||
return 1 << poll;
|
||||
else
|
||||
return 1.0 / (1 << -poll);
|
||||
}
|
||||
|
||||
static int
|
||||
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);
|
||||
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",
|
||||
UTI_RefidToString(instance->ref_id), diff, UTI_TimevalToString(tv));
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009-2014
|
||||
* Copyright (C) Miroslav Lichvar 2009-2015
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -248,9 +248,9 @@ REF_Initialise(void)
|
||||
|
||||
leap_tzname = CNF_GetLeapSecTimezone();
|
||||
if (leap_tzname) {
|
||||
/* Check that the timezone has good data for Jun 30 2008 and Dec 31 2008 */
|
||||
if (get_tz_leap(1214784000) == LEAP_Normal &&
|
||||
get_tz_leap(1230681600) == LEAP_InsertSecond) {
|
||||
/* Check that the timezone has good data for Jun 30 2012 and Dec 31 2012 */
|
||||
if (get_tz_leap(1341014400) == LEAP_InsertSecond &&
|
||||
get_tz_leap(1356912000) == LEAP_Normal) {
|
||||
LOG(LOGS_INFO, LOGF_Reference, "Using %s timezone to obtain leap second data", leap_tzname);
|
||||
} else {
|
||||
LOG(LOGS_WARN, LOGF_Reference, "Timezone %s failed leap second check, ignoring", leap_tzname);
|
||||
|
||||
10
reports.h
10
reports.h
@@ -112,4 +112,14 @@ typedef struct {
|
||||
int unresolved;
|
||||
} 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 */
|
||||
|
||||
4
sched.c
4
sched.c
@@ -330,6 +330,10 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
|
||||
|
||||
LCL_ReadRawTime(&now);
|
||||
UTI_AddDoubleToTimeval(&now, delay, &then);
|
||||
if (UTI_CompareTimevals(&now, &then) > 0) {
|
||||
LOG_FATAL(LOGF_Scheduler, "Timeout overflow");
|
||||
}
|
||||
|
||||
return SCH_AddTimeout(&then, handler, arg);
|
||||
|
||||
}
|
||||
|
||||
111
smooth.c
111
smooth.c
@@ -77,6 +77,10 @@ static struct stage stages[NUM_STAGES];
|
||||
/* Enabled/disabled smoothing */
|
||||
static int enabled;
|
||||
|
||||
/* Enabled/disabled mode where only leap seconds are smoothed out and normal
|
||||
offset/frequency changes are ignored */
|
||||
static int leap_only_mode;
|
||||
|
||||
/* Maximum skew/max_wander ratio to start updating offset and frequency */
|
||||
#define UNLOCK_SKEW_WANDER_RATIO 10000
|
||||
|
||||
@@ -93,15 +97,17 @@ static struct timeval last_update;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
||||
|
||||
*offset = smooth_offset;
|
||||
*freq = smooth_freq;
|
||||
offset = smooth_offset;
|
||||
freq = smooth_freq;
|
||||
wander = 0.0;
|
||||
|
||||
for (i = 0; i < NUM_STAGES; i++) {
|
||||
if (elapsed <= 0.0)
|
||||
@@ -111,13 +117,21 @@ get_offset_freq(struct timeval *now, double *offset, double *freq)
|
||||
if (length >= elapsed)
|
||||
length = elapsed;
|
||||
|
||||
*offset -= length * (2.0 * *freq + stages[i].wander * length) / 2.0;
|
||||
*freq += stages[i].wander * length;
|
||||
wander = stages[i].wander;
|
||||
offset -= length * (2.0 * freq + wander * length) / 2.0;
|
||||
freq += wander * length;
|
||||
elapsed -= length;
|
||||
}
|
||||
|
||||
if (elapsed > 0.0)
|
||||
*offset -= elapsed * *freq;
|
||||
if (elapsed > 0.0) {
|
||||
wander = 0.0;
|
||||
offset -= elapsed * freq;
|
||||
}
|
||||
|
||||
*poffset = offset;
|
||||
*pfreq = freq;
|
||||
if (pwander)
|
||||
*pwander = wander;
|
||||
}
|
||||
|
||||
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 */
|
||||
if (locked) {
|
||||
if (REF_GetSkew() / max_wander < UNLOCK_SKEW_WANDER_RATIO) {
|
||||
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated");
|
||||
locked = 0;
|
||||
}
|
||||
if (REF_GetSkew() / max_wander < UNLOCK_SKEW_WANDER_RATIO || leap_only_mode)
|
||||
SMT_Activate(now);
|
||||
return;
|
||||
}
|
||||
|
||||
get_offset_freq(now, &smooth_offset, &smooth_freq);
|
||||
get_smoothing(now, &smooth_offset, &smooth_freq, NULL);
|
||||
smooth_offset += offset;
|
||||
smooth_freq = (smooth_freq - freq) / (1.0 - freq);
|
||||
last_update = *now;
|
||||
@@ -208,15 +220,19 @@ handle_slew(struct timeval *raw, struct timeval *cooked, double dfreq,
|
||||
{
|
||||
double delta;
|
||||
|
||||
if (change_type == LCL_ChangeAdjust)
|
||||
update_smoothing(cooked, doffset, dfreq);
|
||||
if (change_type == LCL_ChangeAdjust) {
|
||||
if (leap_only_mode)
|
||||
update_smoothing(cooked, 0.0, 0.0);
|
||||
else
|
||||
update_smoothing(cooked, doffset, dfreq);
|
||||
}
|
||||
|
||||
UTI_AdjustTimeval(&last_update, cooked, &last_update, &delta, dfreq, doffset);
|
||||
}
|
||||
|
||||
void SMT_Initialise(void)
|
||||
{
|
||||
CNF_GetSmooth(&max_freq, &max_wander);
|
||||
CNF_GetSmooth(&max_freq, &max_wander, &leap_only_mode);
|
||||
if (max_freq <= 0.0 || max_wander <= 0.0) {
|
||||
enabled = 0;
|
||||
return;
|
||||
@@ -249,19 +265,78 @@ SMT_GetOffset(struct timeval *now)
|
||||
if (!enabled)
|
||||
return 0.0;
|
||||
|
||||
get_offset_freq(now, &offset, &freq);
|
||||
get_smoothing(now, &offset, &freq, NULL);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
SMT_Activate(struct timeval *now)
|
||||
{
|
||||
if (!enabled || !locked)
|
||||
return;
|
||||
|
||||
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated%s", leap_only_mode ?
|
||||
" (leap seconds only)" : "");
|
||||
locked = 0;
|
||||
last_update = *now;
|
||||
}
|
||||
|
||||
void
|
||||
SMT_Reset(struct timeval *now)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
locked = 1;
|
||||
smooth_offset = 0.0;
|
||||
smooth_freq = 0.0;
|
||||
last_update = *now;
|
||||
|
||||
for (i = 0; i < NUM_STAGES; i++)
|
||||
stages[i].wander = stages[i].length = 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
SMT_Leap(struct timeval *now, int leap)
|
||||
{
|
||||
/* When the leap-only mode is disabled, the leap second will be accumulated
|
||||
in handle_slew() as a normal offset */
|
||||
if (!enabled || !leap_only_mode)
|
||||
return;
|
||||
|
||||
update_smoothing(now, leap, 0.0);
|
||||
}
|
||||
|
||||
int
|
||||
SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now)
|
||||
{
|
||||
double length, elapsed;
|
||||
int i;
|
||||
|
||||
if (!enabled)
|
||||
return 0;
|
||||
|
||||
report->active = !locked;
|
||||
report->leap_only = leap_only_mode;
|
||||
|
||||
get_smoothing(now, &report->offset, &report->freq_ppm, &report->wander_ppm);
|
||||
|
||||
/* Convert to ppm and negate (positive values mean faster/speeding up) */
|
||||
report->freq_ppm *= -1.0e6;
|
||||
report->wander_ppm *= -1.0e6;
|
||||
|
||||
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
||||
if (!locked && elapsed >= 0.0) {
|
||||
for (i = 0, length = 0.0; i < NUM_STAGES; i++)
|
||||
length += stages[i].length;
|
||||
report->last_update_ago = elapsed;
|
||||
report->remaining_time = elapsed < length ? length - elapsed : 0.0;
|
||||
} else {
|
||||
report->last_update_ago = 0.0;
|
||||
report->remaining_time = 0.0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
8
smooth.h
8
smooth.h
@@ -27,6 +27,8 @@
|
||||
#ifndef GOT_SMOOTH_H
|
||||
#define GOT_SMOOTH_H
|
||||
|
||||
#include "reports.h"
|
||||
|
||||
extern void SMT_Initialise(void);
|
||||
|
||||
extern void SMT_Finalise(void);
|
||||
@@ -35,6 +37,12 @@ extern int SMT_IsEnabled(void);
|
||||
|
||||
extern double SMT_GetOffset(struct timeval *now);
|
||||
|
||||
extern void SMT_Activate(struct timeval *now);
|
||||
|
||||
extern void SMT_Reset(struct timeval *now);
|
||||
|
||||
extern void SMT_Leap(struct timeval *now, int leap);
|
||||
|
||||
extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
|
||||
|
||||
#endif
|
||||
|
||||
58
sources.c
58
sources.c
@@ -513,7 +513,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
||||
{
|
||||
struct timeval src_ref_time;
|
||||
double src_offset, src_offset_sd, src_frequency, src_skew;
|
||||
double src_root_delay, src_root_dispersion, elapsed;
|
||||
double src_root_delay, src_root_dispersion, sel_src_distance, elapsed;
|
||||
double offset_weight, sum_offset_weight, sum_offset, sum2_offset_sd;
|
||||
double frequency_weight, sum_frequency_weight, sum_frequency, inv_sum2_skew;
|
||||
int i, index, combined;
|
||||
@@ -524,6 +524,10 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
||||
sum_offset_weight = sum_offset = sum2_offset_sd = 0.0;
|
||||
sum_frequency_weight = sum_frequency = inv_sum2_skew = 0.0;
|
||||
|
||||
sel_src_distance = sources[selected_source_index]->sel_info.root_distance;
|
||||
if (sources[selected_source_index]->type == SRC_NTP)
|
||||
sel_src_distance += reselect_distance;
|
||||
|
||||
for (i = combined = 0; i < n_sel_sources; i++) {
|
||||
index = sel_sources[i];
|
||||
SST_GetTrackingData(sources[index]->stats, &src_ref_time,
|
||||
@@ -536,8 +540,7 @@ combine_sources(int n_sel_sources, struct timeval *ref_time, double *offset,
|
||||
are not close, or it was recently marked as distant */
|
||||
|
||||
if (index != selected_source_index &&
|
||||
(sources[index]->sel_info.root_distance > combine_limit *
|
||||
(reselect_distance + sources[selected_source_index]->sel_info.root_distance) ||
|
||||
(sources[index]->sel_info.root_distance > combine_limit * sel_src_distance ||
|
||||
fabs(*frequency - src_frequency) >
|
||||
combine_limit * (*skew + src_skew + LCL_GetMaxClockError()))) {
|
||||
/* Use a smaller penalty in first few updates */
|
||||
@@ -804,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 (selected_source_index != INVALID_SOURCE) {
|
||||
log_selection_message("Can't synchronise: %s selectable sources",
|
||||
@@ -869,16 +835,18 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
|
||||
/* If there are any sources with prefer option, reduce the list again
|
||||
only to the preferred sources */
|
||||
for (i = j = 0; i < n_sel_sources; i++) {
|
||||
for (i = 0; i < n_sel_sources; i++) {
|
||||
if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer)
|
||||
sel_sources[j++] = sel_sources[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (j > 0) {
|
||||
for (i = 0; i < n_sel_sources; i++) {
|
||||
if (i < n_sel_sources) {
|
||||
for (i = j = 0; i < n_sel_sources; i++) {
|
||||
if (sources[sel_sources[i]]->sel_option != SRC_SelectPrefer)
|
||||
sources[sel_sources[i]]->status = SRC_NONPREFERRED;
|
||||
else
|
||||
sel_sources[j++] = sel_sources[i];
|
||||
}
|
||||
assert(j > 0);
|
||||
n_sel_sources = j;
|
||||
sel_prefer = 1;
|
||||
} else {
|
||||
|
||||
@@ -107,6 +107,18 @@ handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static double
|
||||
clamp_freq(double freq)
|
||||
{
|
||||
if (freq > max_freq)
|
||||
return max_freq;
|
||||
if (freq < -max_freq)
|
||||
return -max_freq;
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* End currently running slew and start a new one */
|
||||
|
||||
@@ -144,11 +156,7 @@ update_slew(void)
|
||||
corr_freq = max_corr_freq;
|
||||
|
||||
/* Get the new real frequency and clamp it */
|
||||
total_freq = base_freq + corr_freq * (1.0e6 - base_freq);
|
||||
if (total_freq > max_freq)
|
||||
total_freq = max_freq;
|
||||
else if (total_freq < -max_freq)
|
||||
total_freq = -max_freq;
|
||||
total_freq = clamp_freq(base_freq + corr_freq * (1.0e6 - base_freq));
|
||||
|
||||
/* Set the new frequency (the actual frequency returned by the call may be
|
||||
slightly different from the requested frequency due to rounding) */
|
||||
@@ -330,7 +338,7 @@ SYS_Generic_Finalise(void)
|
||||
slew_timer_running = 0;
|
||||
}
|
||||
|
||||
(*drv_set_freq)(base_freq);
|
||||
(*drv_set_freq)(clamp_freq(base_freq));
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -27,18 +27,20 @@ for leapmode in system step slew; do
|
||||
check_sync || test_fail
|
||||
done
|
||||
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapsectz right/UTC
|
||||
leapsecmode slew
|
||||
smoothtime 400 0.001"
|
||||
client_conf="leapsecmode system"
|
||||
min_sync_time=230000
|
||||
max_sync_time=240000
|
||||
for smoothmode in "" "leaponly"; do
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapsectz right/UTC
|
||||
leapsecmode slew
|
||||
smoothtime 400 0.001 $smoothmode"
|
||||
client_conf="leapsecmode system"
|
||||
min_sync_time=230000
|
||||
max_sync_time=240000
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
done
|
||||
|
||||
test_pass
|
||||
|
||||
21
test/simulation/202-prefer
Executable file
21
test/simulation/202-prefer
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
. test.common
|
||||
|
||||
# Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629
|
||||
|
||||
test_start "prefer option"
|
||||
|
||||
servers=3
|
||||
client_server_conf="
|
||||
server 192.168.123.1
|
||||
server 192.168.123.2
|
||||
server 192.168.123.3 prefer"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
test_pass
|
||||
@@ -65,6 +65,7 @@ default_chronyc_start=1000.0
|
||||
default_server_step=""
|
||||
default_client_step=""
|
||||
|
||||
default_client_server_conf=""
|
||||
default_server_server_options=""
|
||||
default_client_server_options=""
|
||||
default_server_peer_options=""
|
||||
@@ -192,9 +193,13 @@ get_chronyd_conf() {
|
||||
done
|
||||
echo "$server_conf"
|
||||
else
|
||||
for i in $(seq 1 $servers); do
|
||||
echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options"
|
||||
done
|
||||
if [ -n "$client_server_conf" ]; then
|
||||
echo "$client_server_conf"
|
||||
else
|
||||
for i in $(seq 1 $servers); do
|
||||
echo "server 192.168.123.$[$servers * ($stratum - 2) + $i] $client_server_options"
|
||||
done
|
||||
fi
|
||||
for i in $(seq 1 $peers); do
|
||||
[ $i -eq $peer -o $i -gt $clients ] && continue
|
||||
echo "peer 192.168.123.$[$servers * ($stratum - 1) + $i] $client_peer_options"
|
||||
|
||||
29
util.c
29
util.c
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2012-2013
|
||||
* Copyright (C) Miroslav Lichvar 2009, 2012-2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -609,6 +609,9 @@ UTI_Int64ToTimeval(NTP_int64 *src,
|
||||
/* Maximum offset between two sane times */
|
||||
#define MAX_OFFSET 4294967296.0
|
||||
|
||||
/* Minimum allowed distance from maximum 32-bit time_t */
|
||||
#define MIN_ENDOFTIME_DISTANCE (365 * 24 * 3600)
|
||||
|
||||
int
|
||||
UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
|
||||
{
|
||||
@@ -629,6 +632,10 @@ UTI_IsTimeOffsetSane(struct timeval *tv, double offset)
|
||||
/* Check if it's in the interval to which NTP time is mapped */
|
||||
if (t < (double)NTP_ERA_SPLIT || t > (double)(NTP_ERA_SPLIT + (1LL << 32)))
|
||||
return 0;
|
||||
#else
|
||||
/* Don't get too close to 32-bit time_t overflow */
|
||||
if (t > (double)(0x7fffffff - MIN_ENDOFTIME_DISTANCE))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -636,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
|
||||
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
|
||||
{
|
||||
@@ -700,7 +723,11 @@ UTI_FloatHostToNetwork(double x)
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
neg = 1;
|
||||
} else if (x >= 0.0) {
|
||||
neg = 0;
|
||||
} else {
|
||||
/* Save NaN as zero */
|
||||
x = 0.0;
|
||||
neg = 0;
|
||||
}
|
||||
|
||||
|
||||
3
util.h
3
util.h
@@ -107,6 +107,9 @@ extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
|
||||
/* Check if time + offset is sane */
|
||||
extern int UTI_IsTimeOffsetSane(struct timeval *tv, double offset);
|
||||
|
||||
/* Get 2 raised to power of a signed integer */
|
||||
extern double UTI_Log2ToDouble(int l);
|
||||
|
||||
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
|
||||
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ TMX_ResetOffset(void)
|
||||
|
||||
/* Set status back */
|
||||
txc.modes = ADJ_STATUS;
|
||||
txc.modes = status;
|
||||
txc.status = status;
|
||||
if (adjtimex(&txc) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user