mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 23:55:07 -05:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42a85f685e | ||
|
|
feca2399e4 | ||
|
|
d34e611ec8 | ||
|
|
02098ed830 | ||
|
|
aa4228bf1b | ||
|
|
b296441708 | ||
|
|
b827475378 | ||
|
|
78a6698ae1 | ||
|
|
e7b6feb34b | ||
|
|
84be834385 | ||
|
|
e83d808dfd | ||
|
|
35a68d5b59 | ||
|
|
3c593137b0 | ||
|
|
deaf0ffed3 | ||
|
|
af145e871e | ||
|
|
fbca570d0b | ||
|
|
448ef779c2 | ||
|
|
499a69e611 | ||
|
|
58c2915878 | ||
|
|
eda4b111d3 | ||
|
|
c6dd749687 | ||
|
|
d2a96f5fbc | ||
|
|
499f513d40 | ||
|
|
8b1f68b1b4 | ||
|
|
8e4c776900 | ||
|
|
d0eb9427c2 | ||
|
|
7d100b89fc | ||
|
|
a4bd7f1800 | ||
|
|
5308e0a25f | ||
|
|
da862158bf | ||
|
|
7b98443a13 | ||
|
|
4da9f74d24 | ||
|
|
e41042e258 | ||
|
|
5581466c63 | ||
|
|
e79a6c2116 | ||
|
|
666ece122e | ||
|
|
2c7ab98370 | ||
|
|
f0f18a02a7 | ||
|
|
c5d8af0285 | ||
|
|
0ce15a8472 | ||
|
|
da60629201 | ||
|
|
2343e7a89c | ||
|
|
45f27f4f5e | ||
|
|
0bc112f8b4 | ||
|
|
bfc2fa645c | ||
|
|
11111804fd | ||
|
|
87ec67247e | ||
|
|
0df8328ceb | ||
|
|
b563048ee2 | ||
|
|
e8096330be | ||
|
|
b1647dbcb7 | ||
|
|
4ddadd5622 | ||
|
|
3e854006c7 | ||
|
|
2c4c235147 | ||
|
|
6863e43269 | ||
|
|
de8708f331 | ||
|
|
d0b2486036 | ||
|
|
5384a93645 | ||
|
|
4bbc768652 | ||
|
|
fead915b45 | ||
|
|
5422e49026 | ||
|
|
77a1f27a1d | ||
|
|
b45d864f73 | ||
|
|
f35c81c871 | ||
|
|
a349b2803c | ||
|
|
f5d1b8fb74 | ||
|
|
a0fe71eef1 | ||
|
|
154b39cf7a | ||
|
|
6f54210db2 | ||
|
|
f6539449c5 |
23
NEWS
23
NEWS
@@ -1,3 +1,26 @@
|
|||||||
|
New in version 3.3
|
||||||
|
==================
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
* Add burst option to server/pool directive
|
||||||
|
* Add stratum and tai options to refclock directive
|
||||||
|
* Add support for Nettle crypto library
|
||||||
|
* Add workaround for missing kernel receive timestamps on Linux
|
||||||
|
* Wait for late hardware transmit timestamps
|
||||||
|
* Improve source selection with unreachable sources
|
||||||
|
* Improve protection against replay attacks on symmetric mode
|
||||||
|
* Allow PHC refclock to use socket in /var/run/chrony
|
||||||
|
* Add shutdown command to stop chronyd
|
||||||
|
* Simplify format of response to manual list command
|
||||||
|
* Improve handling of unknown responses in chronyc
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
* Respond to NTPv1 client requests with zero mode
|
||||||
|
* Fix -x option to not require CAP_SYS_TIME under non-root user
|
||||||
|
* Fix chronyc to not get stuck in infinite loop after clock step
|
||||||
|
|
||||||
New in version 3.2
|
New in version 3.2
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|||||||
45
README
45
README
@@ -37,20 +37,16 @@ How do I set it up?
|
|||||||
===================
|
===================
|
||||||
|
|
||||||
The file INSTALL gives instructions. On supported systems the
|
The file INSTALL gives instructions. On supported systems the
|
||||||
compilation process should be automatic.
|
compilation process should be automatic. You will need a C compiler,
|
||||||
|
e.g. gcc or clang.
|
||||||
You will need an ANSI C compiler -- gcc is recommended.
|
|
||||||
|
|
||||||
The manual (in texinfo and text formats) describes how to set the
|
|
||||||
software up for the less straightforward cases.
|
|
||||||
|
|
||||||
What documentation is there?
|
What documentation is there?
|
||||||
============================
|
============================
|
||||||
|
|
||||||
A manual is supplied in Texinfo format (chrony.texi) and
|
The distribution includes manual pages and a document containing
|
||||||
ready-formatted plain text (chrony.txt) in the distribution.
|
Frequently Asked Questions (FAQ).
|
||||||
|
|
||||||
There is also information available on the chrony web pages, accessible
|
The documentation is also available on the chrony web pages, accessible
|
||||||
through the URL
|
through the URL
|
||||||
|
|
||||||
https://chrony.tuxfamily.org/
|
https://chrony.tuxfamily.org/
|
||||||
@@ -126,7 +122,7 @@ Andrew Bishop <amb@gedanken.demon.co.uk>
|
|||||||
Improvements to 'sources' and 'sourcestats' output from chronyc
|
Improvements to 'sources' and 'sourcestats' output from chronyc
|
||||||
Improvements to documentation
|
Improvements to documentation
|
||||||
Investigation of required dosynctodr behaviour for various Solaris
|
Investigation of required dosynctodr behaviour for various Solaris
|
||||||
versions.
|
versions
|
||||||
|
|
||||||
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
Stephan I. Boettcher <stephan@nevis1.columbia.edu>
|
||||||
Entries in contrib directory
|
Entries in contrib directory
|
||||||
@@ -140,27 +136,27 @@ Bryan Christianson <bryan@whatroute.net>
|
|||||||
Entries in contrib directory
|
Entries in contrib directory
|
||||||
|
|
||||||
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
Juliusz Chroboczek <jch@pps.jussieu.fr>
|
||||||
Fix install rule in Makefile if chronyd file is in use.
|
Patch to fix install rule in Makefile if chronyd file is in use
|
||||||
|
|
||||||
|
Christian Ehrhardt <christian.ehrhardt@canonical.com>
|
||||||
|
Patch to generate a warning message when CAP_SYS_TIME is missing
|
||||||
|
|
||||||
Paul Elliott <pelliott@io.com>
|
Paul Elliott <pelliott@io.com>
|
||||||
DNSchrony (in contrib directory), a tool for handling NTP servers
|
Entries in contrib directory
|
||||||
with variable IP addresses.
|
|
||||||
|
|
||||||
Mike Fleetwood <mike@rockover.demon.co.uk>
|
Mike Fleetwood <mike@rockover.demon.co.uk>
|
||||||
Fixes for compiler warnings
|
Fixes for compiler warnings
|
||||||
|
|
||||||
Alexander Gretencord <arutha@gmx.de>
|
Alexander Gretencord <arutha@gmx.de>
|
||||||
Changes to installation directory system to make it easier for
|
Changes to installation directory system to make it easier for
|
||||||
package builders.
|
package builders
|
||||||
|
|
||||||
Andrew Griffiths <agriffit@redhat.com>
|
Andrew Griffiths <agriffit@redhat.com>
|
||||||
Patch to add support for seccomp filter
|
Patch to add support for seccomp filter
|
||||||
|
|
||||||
Walter Haidinger <walter.haidinger@gmx.at>
|
Walter Haidinger <walter.haidinger@gmx.at>
|
||||||
Providing me with login access to a Linux installation where v1.12
|
Access to a Linux installation where v1.12 wouldn't compile
|
||||||
wouldn't compile, so I could develop the fixes for v1.13. Also, for
|
Disc space for an independent backup of the sources
|
||||||
providing the disc space so I can keep an independent backup of the
|
|
||||||
sources.
|
|
||||||
|
|
||||||
Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
|
Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
|
||||||
Port to NetBSD
|
Port to NetBSD
|
||||||
@@ -170,7 +166,7 @@ John Hasler <john@dhh.gt.org>
|
|||||||
Changes to support 64 bit machines (i.e. those where
|
Changes to support 64 bit machines (i.e. those where
|
||||||
sizeof(unsigned long) > 4)
|
sizeof(unsigned long) > 4)
|
||||||
Bug fix to initstepslew directive
|
Bug fix to initstepslew directive
|
||||||
Fix to remove potential buffer overrun errors.
|
Fix to remove potential buffer overrun errors
|
||||||
Memory locking and real-time scheduler support
|
Memory locking and real-time scheduler support
|
||||||
Fix fault where chronyd enters an endless loop
|
Fix fault where chronyd enters an endless loop
|
||||||
|
|
||||||
@@ -198,7 +194,7 @@ Victor Moroz <vim@prv.adlum.ru>
|
|||||||
Patch to support Linux with HZ!=100
|
Patch to support Linux with HZ!=100
|
||||||
|
|
||||||
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
||||||
acquisitionport support
|
Patch to add acquisitionport directive
|
||||||
|
|
||||||
Frank Otto <sandwichmacher@web.de>
|
Frank Otto <sandwichmacher@web.de>
|
||||||
Handling arbitrary HZ values
|
Handling arbitrary HZ values
|
||||||
@@ -206,12 +202,18 @@ Frank Otto <sandwichmacher@web.de>
|
|||||||
Denny Page <dennypage@me.com>
|
Denny Page <dennypage@me.com>
|
||||||
Advice on support for hardware timestamping
|
Advice on support for hardware timestamping
|
||||||
|
|
||||||
|
Chris Perl <cperl@janestreet.com>
|
||||||
|
Patches to improve support for refclocks keeping time in TAI
|
||||||
|
|
||||||
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
||||||
Patch to add refresh command to chronyc
|
Patch to add refresh command to chronyc
|
||||||
|
|
||||||
Andreas Piesk <apiesk@virbus.de>
|
Andreas Piesk <apiesk@virbus.de>
|
||||||
Patch to make chronyc use the readline library if available
|
Patch to make chronyc use the readline library if available
|
||||||
|
|
||||||
|
Andreas Steinmetz <ast@domdv.de>
|
||||||
|
Patch to make stratum of refclocks configurable
|
||||||
|
|
||||||
Timo Teras <timo.teras@iki.fi>
|
Timo Teras <timo.teras@iki.fi>
|
||||||
Patch to reply correctly on multihomed hosts
|
Patch to reply correctly on multihomed hosts
|
||||||
|
|
||||||
@@ -228,8 +230,7 @@ Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
|||||||
Many robustness and security improvements
|
Many robustness and security improvements
|
||||||
|
|
||||||
Ulrich Windl <ulrich.windl@rz.uni-regensburg.de> for the
|
Ulrich Windl <ulrich.windl@rz.uni-regensburg.de> for the
|
||||||
Providing me with information about the Linux 2.2 kernel
|
Information about the Linux 2.2 kernel functionality compared to 2.0
|
||||||
functionality compared to 2.0.
|
|
||||||
|
|
||||||
Doug Woodward <dougw@whistler.com>
|
Doug Woodward <dougw@whistler.com>
|
||||||
Advice on configuring for Solaris 2.8 on x86
|
Advice on configuring for Solaris 2.8 on x86
|
||||||
|
|||||||
13
candm.h
13
candm.h
@@ -99,7 +99,8 @@
|
|||||||
#define REQ_ADD_PEER2 59
|
#define REQ_ADD_PEER2 59
|
||||||
#define REQ_ADD_SERVER3 60
|
#define REQ_ADD_SERVER3 60
|
||||||
#define REQ_ADD_PEER3 61
|
#define REQ_ADD_PEER3 61
|
||||||
#define N_REQUEST_TYPES 62
|
#define REQ_SHUTDOWN 62
|
||||||
|
#define N_REQUEST_TYPES 63
|
||||||
|
|
||||||
/* Structure used to exchange timespecs independent of time_t size */
|
/* Structure used to exchange timespecs independent of time_t size */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -252,6 +253,7 @@ typedef struct {
|
|||||||
#define REQ_ADDSRC_TRUST 0x20
|
#define REQ_ADDSRC_TRUST 0x20
|
||||||
#define REQ_ADDSRC_REQUIRE 0x40
|
#define REQ_ADDSRC_REQUIRE 0x40
|
||||||
#define REQ_ADDSRC_INTERLEAVED 0x80
|
#define REQ_ADDSRC_INTERLEAVED 0x80
|
||||||
|
#define REQ_ADDSRC_BURST 0x100
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IPAddr ip_addr;
|
IPAddr ip_addr;
|
||||||
@@ -367,9 +369,9 @@ typedef struct {
|
|||||||
domain socket.
|
domain socket.
|
||||||
|
|
||||||
Version 6 (no authentication) : changed format of client accesses by index
|
Version 6 (no authentication) : changed format of client accesses by index
|
||||||
(using new request/reply types) and manual timestamp, new fields and flags
|
(using new request/reply types) and manual timestamp, added new fields and
|
||||||
in NTP source request and report, new commands: ntpdata, refresh,
|
flags to NTP source request and report, made length of manual list constant,
|
||||||
serverstats
|
added new commands: ntpdata, refresh, serverstats, shutdown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTO_VERSION_NUMBER 6
|
#define PROTO_VERSION_NUMBER 6
|
||||||
@@ -468,7 +470,8 @@ typedef struct {
|
|||||||
#define RPY_CLIENT_ACCESSES_BY_INDEX2 15
|
#define RPY_CLIENT_ACCESSES_BY_INDEX2 15
|
||||||
#define RPY_NTP_DATA 16
|
#define RPY_NTP_DATA 16
|
||||||
#define RPY_MANUAL_TIMESTAMP2 17
|
#define RPY_MANUAL_TIMESTAMP2 17
|
||||||
#define N_REPLY_TYPES 18
|
#define RPY_MANUAL_LIST2 18
|
||||||
|
#define N_REPLY_TYPES 19
|
||||||
|
|
||||||
/* Status codes */
|
/* Status codes */
|
||||||
#define STT_SUCCESS 0
|
#define STT_SUCCESS 0
|
||||||
|
|||||||
100
client.c
100
client.c
@@ -1109,6 +1109,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||||||
(data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
|
(data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) |
|
||||||
(data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
|
(data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
|
||||||
(data.params.interleaved ? REQ_ADDSRC_INTERLEAVED : 0) |
|
(data.params.interleaved ? REQ_ADDSRC_INTERLEAVED : 0) |
|
||||||
|
(data.params.burst ? REQ_ADDSRC_BURST : 0) |
|
||||||
(data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
|
(data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
|
||||||
(data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
|
(data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
|
||||||
(data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) |
|
(data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) |
|
||||||
@@ -1245,6 +1246,7 @@ give_help(void)
|
|||||||
"cyclelogs\0Close and re-open log files\0"
|
"cyclelogs\0Close and re-open log files\0"
|
||||||
"dump\0Dump all measurements to save files\0"
|
"dump\0Dump all measurements to save files\0"
|
||||||
"rekey\0Re-read keys from key file\0"
|
"rekey\0Re-read keys from key file\0"
|
||||||
|
"shutdown\0Stop daemon\0"
|
||||||
"\0\0"
|
"\0\0"
|
||||||
"Client commands:\0\0"
|
"Client commands:\0\0"
|
||||||
"dns -n|+n\0Disable/enable resolving IP addresses to hostnames\0"
|
"dns -n|+n\0Disable/enable resolving IP addresses to hostnames\0"
|
||||||
@@ -1279,9 +1281,9 @@ command_name_generator(const char *text, int state)
|
|||||||
"maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
|
"maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
|
||||||
"maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online",
|
"maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online",
|
||||||
"polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist",
|
"polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist",
|
||||||
"retries", "rtcdata", "serverstats", "settime", "smoothing", "smoothtime",
|
"retries", "rtcdata", "serverstats", "settime", "shutdown", "smoothing",
|
||||||
"sources", "sources -v", "sourcestats", "sourcestats -v", "timeout",
|
"smoothtime", "sources", "sources -v", "sourcestats", "sourcestats -v",
|
||||||
"tracking", "trimrtc", "waitsync", "writertc",
|
"timeout", "tracking", "trimrtc", "waitsync", "writertc",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static int list_index, len;
|
static int list_index, len;
|
||||||
@@ -1324,18 +1326,16 @@ static int proto_version = PROTO_VERSION_NUMBER;
|
|||||||
static int
|
static int
|
||||||
submit_request(CMD_Request *request, CMD_Reply *reply)
|
submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
{
|
{
|
||||||
int bad_length, bad_sequence, bad_header;
|
|
||||||
int select_status;
|
int select_status;
|
||||||
int recv_status;
|
int recv_status;
|
||||||
int read_length;
|
int read_length;
|
||||||
int expected_length;
|
|
||||||
int command_length;
|
int command_length;
|
||||||
int padding_length;
|
int padding_length;
|
||||||
struct timespec ts_now, ts_start;
|
struct timespec ts_now, ts_start;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int n_attempts, new_attempt;
|
int n_attempts, new_attempt;
|
||||||
double timeout;
|
double timeout;
|
||||||
fd_set rdfd, wrfd, exfd;
|
fd_set rdfd;
|
||||||
|
|
||||||
request->pkt_type = PKT_TYPE_CMD_REQUEST;
|
request->pkt_type = PKT_TYPE_CMD_REQUEST;
|
||||||
request->res1 = 0;
|
request->res1 = 0;
|
||||||
@@ -1347,15 +1347,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
|||||||
new_attempt = 1;
|
new_attempt = 1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if (gettimeofday(&tv, NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (new_attempt) {
|
if (new_attempt) {
|
||||||
new_attempt = 0;
|
new_attempt = 0;
|
||||||
|
|
||||||
if (n_attempts > max_retries)
|
if (n_attempts > max_retries)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UTI_TimevalToTimespec(&tv, &ts_start);
|
UTI_TimevalToTimespec(&tv, &ts_start);
|
||||||
|
|
||||||
UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
|
UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
|
||||||
@@ -1383,9 +1383,6 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
|||||||
DEBUG_LOG("Sent %d bytes", command_length);
|
DEBUG_LOG("Sent %d bytes", command_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UTI_TimevalToTimespec(&tv, &ts_now);
|
UTI_TimevalToTimespec(&tv, &ts_now);
|
||||||
|
|
||||||
/* Check if the clock wasn't stepped back */
|
/* Check if the clock wasn't stepped back */
|
||||||
@@ -1394,22 +1391,27 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
|||||||
|
|
||||||
timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
|
timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
|
||||||
UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
|
UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
|
||||||
UTI_DoubleToTimeval(timeout, &tv);
|
|
||||||
DEBUG_LOG("Timeout %f seconds", timeout);
|
DEBUG_LOG("Timeout %f seconds", timeout);
|
||||||
|
|
||||||
FD_ZERO(&rdfd);
|
/* Avoid calling select() with an invalid timeout */
|
||||||
FD_ZERO(&wrfd);
|
if (timeout <= 0.0) {
|
||||||
FD_ZERO(&exfd);
|
new_attempt = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTI_DoubleToTimeval(timeout, &tv);
|
||||||
|
|
||||||
|
FD_ZERO(&rdfd);
|
||||||
FD_SET(sock_fd, &rdfd);
|
FD_SET(sock_fd, &rdfd);
|
||||||
|
|
||||||
if (quit)
|
if (quit)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
select_status = select(sock_fd + 1, &rdfd, &wrfd, &exfd, &tv);
|
select_status = select(sock_fd + 1, &rdfd, NULL, NULL, &tv);
|
||||||
|
|
||||||
if (select_status < 0) {
|
if (select_status < 0) {
|
||||||
DEBUG_LOG("select failed : %s", strerror(errno));
|
DEBUG_LOG("select failed : %s", strerror(errno));
|
||||||
|
return 0;
|
||||||
} else if (select_status == 0) {
|
} else if (select_status == 0) {
|
||||||
/* Timeout must have elapsed, try a resend? */
|
/* Timeout must have elapsed, try a resend? */
|
||||||
new_attempt = 1;
|
new_attempt = 1;
|
||||||
@@ -1425,34 +1427,18 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
|||||||
DEBUG_LOG("Received %d bytes", recv_status);
|
DEBUG_LOG("Received %d bytes", recv_status);
|
||||||
|
|
||||||
read_length = recv_status;
|
read_length = recv_status;
|
||||||
if (read_length >= offsetof(CMD_Reply, data)) {
|
|
||||||
expected_length = PKL_ReplyLength(reply);
|
|
||||||
} else {
|
|
||||||
expected_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bad_length = (read_length < expected_length ||
|
|
||||||
expected_length < offsetof(CMD_Reply, data));
|
|
||||||
|
|
||||||
if (!bad_length) {
|
/* Check if the header is valid */
|
||||||
bad_sequence = reply->sequence != request->sequence;
|
if (read_length < offsetof(CMD_Reply, data) ||
|
||||||
} else {
|
(reply->version != proto_version &&
|
||||||
bad_sequence = 0;
|
!(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
|
||||||
}
|
ntohs(reply->status) == STT_BADPKTVERSION)) ||
|
||||||
|
reply->pkt_type != PKT_TYPE_CMD_REPLY ||
|
||||||
if (bad_length || bad_sequence) {
|
reply->res1 != 0 ||
|
||||||
continue;
|
reply->res2 != 0 ||
|
||||||
}
|
reply->command != request->command ||
|
||||||
|
reply->sequence != request->sequence) {
|
||||||
bad_header = ((reply->version != proto_version &&
|
DEBUG_LOG("Invalid reply");
|
||||||
!(reply->version >= PROTO_VERSION_MISMATCH_COMPAT_CLIENT &&
|
|
||||||
ntohs(reply->status) == STT_BADPKTVERSION)) ||
|
|
||||||
(reply->pkt_type != PKT_TYPE_CMD_REPLY) ||
|
|
||||||
(reply->res1 != 0) ||
|
|
||||||
(reply->res2 != 0) ||
|
|
||||||
(reply->command != request->command));
|
|
||||||
|
|
||||||
if (bad_header) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,6 +1457,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
|||||||
#error unknown compatibility with PROTO_VERSION - 1
|
#error unknown compatibility with PROTO_VERSION - 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Check that the packet contains all data it is supposed to have.
|
||||||
|
Unknown responses will always pass this test as their expected
|
||||||
|
length is zero. */
|
||||||
|
if (read_length < PKL_ReplyLength(reply)) {
|
||||||
|
DEBUG_LOG("Reply too short");
|
||||||
|
new_attempt = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Good packet received, print out results */
|
/* Good packet received, print out results */
|
||||||
DEBUG_LOG("Reply cmd=%d reply=%d stat=%d",
|
DEBUG_LOG("Reply cmd=%d reply=%d stat=%d",
|
||||||
ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status));
|
ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status));
|
||||||
@@ -1577,6 +1572,9 @@ request_reply(CMD_Request *request, CMD_Reply *reply, int requested_reply, int v
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure an unknown response was not requested */
|
||||||
|
assert(PKL_ReplyLength(reply));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2540,7 +2538,7 @@ process_cmd_manual_list(const char *line)
|
|||||||
struct timespec when;
|
struct timespec when;
|
||||||
|
|
||||||
request.command = htons(REQ_MANUAL_LIST);
|
request.command = htons(REQ_MANUAL_LIST);
|
||||||
if (!request_reply(&request, &reply, RPY_MANUAL_LIST, 0))
|
if (!request_reply(&request, &reply, RPY_MANUAL_LIST2, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
n_samples = ntohl(reply.data.manual_list.n_samples);
|
n_samples = ntohl(reply.data.manual_list.n_samples);
|
||||||
@@ -2548,7 +2546,7 @@ process_cmd_manual_list(const char *line)
|
|||||||
|
|
||||||
print_header("# Date Time(UTC) Slewed Original Residual");
|
print_header("# Date Time(UTC) Slewed Original Residual");
|
||||||
|
|
||||||
for (i = 0; i < n_samples; i++) {
|
for (i = 0; i < n_samples && i < MAX_MANUAL_LIST_SAMPLES; i++) {
|
||||||
sample = &reply.data.manual_list.samples[i];
|
sample = &reply.data.manual_list.samples[i];
|
||||||
UTI_TimespecNetworkToHost(&sample->when, &when);
|
UTI_TimespecNetworkToHost(&sample->when, &when);
|
||||||
|
|
||||||
@@ -2709,6 +2707,14 @@ process_cmd_refresh(CMD_Request *msg, char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_cmd_shutdown(CMD_Request *msg, char *line)
|
||||||
|
{
|
||||||
|
msg->command = htons(REQ_SHUTDOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_cmd_waitsync(char *line)
|
process_cmd_waitsync(char *line)
|
||||||
{
|
{
|
||||||
@@ -3004,6 +3010,8 @@ process_line(char *line)
|
|||||||
} else if (!strcmp(command, "settime")) {
|
} else if (!strcmp(command, "settime")) {
|
||||||
do_normal_submit = 0;
|
do_normal_submit = 0;
|
||||||
ret = process_cmd_settime(line);
|
ret = process_cmd_settime(line);
|
||||||
|
} else if (!strcmp(command, "shutdown")) {
|
||||||
|
process_cmd_shutdown(&tx_message, line);
|
||||||
} else if (!strcmp(command, "smoothing")) {
|
} else if (!strcmp(command, "smoothing")) {
|
||||||
do_normal_submit = 0;
|
do_normal_submit = 0;
|
||||||
ret = process_cmd_smoothing(line);
|
ret = process_cmd_smoothing(line);
|
||||||
|
|||||||
31
cmdmon.c
31
cmdmon.c
@@ -138,6 +138,7 @@ static const char permissions[] = {
|
|||||||
PERMIT_AUTH, /* ADD_PEER2 */
|
PERMIT_AUTH, /* ADD_PEER2 */
|
||||||
PERMIT_AUTH, /* ADD_SERVER3 */
|
PERMIT_AUTH, /* ADD_SERVER3 */
|
||||||
PERMIT_AUTH, /* ADD_PEER3 */
|
PERMIT_AUTH, /* ADD_PEER3 */
|
||||||
|
PERMIT_AUTH, /* SHUTDOWN */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -278,7 +279,6 @@ do_size_checks(void)
|
|||||||
for (i = 1; i < N_REPLY_TYPES; i++) {
|
for (i = 1; i < N_REPLY_TYPES; i++) {
|
||||||
reply.reply = htons(i);
|
reply.reply = htons(i);
|
||||||
reply.status = STT_SUCCESS;
|
reply.status = STT_SUCCESS;
|
||||||
reply.data.manual_list.n_samples = htonl(MAX_MANUAL_LIST_SAMPLES);
|
|
||||||
reply_length = PKL_ReplyLength(&reply);
|
reply_length = PKL_ReplyLength(&reply);
|
||||||
if ((reply_length && reply_length < offsetof(CMD_Reply, data)) ||
|
if ((reply_length && reply_length < offsetof(CMD_Reply, data)) ||
|
||||||
reply_length > sizeof (CMD_Reply))
|
reply_length > sizeof (CMD_Reply))
|
||||||
@@ -801,6 +801,7 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
|
|||||||
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
|
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
|
||||||
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
|
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
|
||||||
params.interleaved = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_INTERLEAVED ? 1 : 0;
|
params.interleaved = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_INTERLEAVED ? 1 : 0;
|
||||||
|
params.burst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_BURST ? 1 : 0;
|
||||||
params.sel_options =
|
params.sel_options =
|
||||||
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SELECT_PREFER : 0) |
|
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SELECT_PREFER : 0) |
|
||||||
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) |
|
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) |
|
||||||
@@ -1068,9 +1069,6 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX2);
|
tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX2);
|
||||||
tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices);
|
tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices);
|
||||||
|
|
||||||
memset(tx_message->data.client_accesses_by_index.clients, 0,
|
|
||||||
sizeof (tx_message->data.client_accesses_by_index.clients));
|
|
||||||
|
|
||||||
for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) {
|
for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) {
|
||||||
if (!CLG_GetClientAccessReportByIndex(i, &report, &now))
|
if (!CLG_GetClientAccessReportByIndex(i, &report, &now))
|
||||||
continue;
|
continue;
|
||||||
@@ -1103,10 +1101,11 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
RPY_ManualListSample *sample;
|
RPY_ManualListSample *sample;
|
||||||
RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];
|
RPT_ManualSamplesReport report[MAX_MANUAL_LIST_SAMPLES];
|
||||||
|
|
||||||
tx_message->reply = htons(RPY_MANUAL_LIST);
|
tx_message->reply = htons(RPY_MANUAL_LIST2);
|
||||||
|
|
||||||
MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples);
|
MNL_ReportSamples(report, MAX_MANUAL_LIST_SAMPLES, &n_samples);
|
||||||
tx_message->data.manual_list.n_samples = htonl(n_samples);
|
tx_message->data.manual_list.n_samples = htonl(n_samples);
|
||||||
|
|
||||||
for (i=0; i<n_samples; i++) {
|
for (i=0; i<n_samples; i++) {
|
||||||
sample = &tx_message->data.manual_list.samples[i];
|
sample = &tx_message->data.manual_list.samples[i];
|
||||||
UTI_TimespecHostToNetwork(&report[i].when, &sample->when);
|
UTI_TimespecHostToNetwork(&report[i].when, &sample->when);
|
||||||
@@ -1238,6 +1237,15 @@ handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
|
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_shutdown(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||||
|
{
|
||||||
|
LOG(LOGS_INFO, "Received shutdown command");
|
||||||
|
SCH_QuitProgram();
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Read a packet and process it */
|
/* Read a packet and process it */
|
||||||
|
|
||||||
@@ -1329,19 +1337,14 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||||||
expected_length = PKL_CommandLength(&rx_message);
|
expected_length = PKL_CommandLength(&rx_message);
|
||||||
rx_command = ntohs(rx_message.command);
|
rx_command = ntohs(rx_message.command);
|
||||||
|
|
||||||
|
memset(&tx_message, 0, sizeof (tx_message));
|
||||||
|
|
||||||
tx_message.version = PROTO_VERSION_NUMBER;
|
tx_message.version = PROTO_VERSION_NUMBER;
|
||||||
tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
|
tx_message.pkt_type = PKT_TYPE_CMD_REPLY;
|
||||||
tx_message.res1 = 0;
|
|
||||||
tx_message.res2 = 0;
|
|
||||||
tx_message.command = rx_message.command;
|
tx_message.command = rx_message.command;
|
||||||
tx_message.reply = htons(RPY_NULL);
|
tx_message.reply = htons(RPY_NULL);
|
||||||
tx_message.status = htons(STT_SUCCESS);
|
tx_message.status = htons(STT_SUCCESS);
|
||||||
tx_message.pad1 = 0;
|
|
||||||
tx_message.pad2 = 0;
|
|
||||||
tx_message.pad3 = 0;
|
|
||||||
tx_message.sequence = rx_message.sequence;
|
tx_message.sequence = rx_message.sequence;
|
||||||
tx_message.pad4 = 0;
|
|
||||||
tx_message.pad5 = 0;
|
|
||||||
|
|
||||||
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
||||||
DEBUG_LOG("Command packet has invalid version (%d != %d)",
|
DEBUG_LOG("Command packet has invalid version (%d != %d)",
|
||||||
@@ -1629,6 +1632,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||||||
handle_ntp_data(&rx_message, &tx_message);
|
handle_ntp_data(&rx_message, &tx_message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case REQ_SHUTDOWN:
|
||||||
|
handle_shutdown(&rx_message, &tx_message);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_LOG("Unhandled command %d", rx_command);
|
DEBUG_LOG("Unhandled command %d", rx_command);
|
||||||
tx_message.status = htons(STT_FAILED);
|
tx_message.status = htons(STT_FAILED);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
|||||||
src->params.online = 1;
|
src->params.online = 1;
|
||||||
src->params.auto_offline = 0;
|
src->params.auto_offline = 0;
|
||||||
src->params.presend_minpoll = SRC_DEFAULT_PRESEND_MINPOLL;
|
src->params.presend_minpoll = SRC_DEFAULT_PRESEND_MINPOLL;
|
||||||
|
src->params.burst = 0;
|
||||||
src->params.iburst = 0;
|
src->params.iburst = 0;
|
||||||
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
|
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
|
||||||
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
|
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
|
||||||
@@ -84,6 +85,8 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
|||||||
|
|
||||||
if (!strcasecmp(cmd, "auto_offline")) {
|
if (!strcasecmp(cmd, "auto_offline")) {
|
||||||
src->params.auto_offline = 1;
|
src->params.auto_offline = 1;
|
||||||
|
} else if (!strcasecmp(cmd, "burst")) {
|
||||||
|
src->params.burst = 1;
|
||||||
} else if (!strcasecmp(cmd, "iburst")) {
|
} else if (!strcasecmp(cmd, "iburst")) {
|
||||||
src->params.iburst = 1;
|
src->params.iburst = 1;
|
||||||
} else if (!strcasecmp(cmd, "offline")) {
|
} else if (!strcasecmp(cmd, "offline")) {
|
||||||
|
|||||||
13
conf.c
13
conf.c
@@ -681,7 +681,7 @@ static void
|
|||||||
parse_refclock(char *line)
|
parse_refclock(char *line)
|
||||||
{
|
{
|
||||||
int n, poll, dpoll, filter_length, pps_rate, min_samples, max_samples, sel_options;
|
int n, poll, dpoll, filter_length, pps_rate, min_samples, max_samples, sel_options;
|
||||||
int max_lock_age, pps_forced;
|
int max_lock_age, pps_forced, stratum, tai;
|
||||||
uint32_t ref_id, lock_ref_id;
|
uint32_t ref_id, lock_ref_id;
|
||||||
double offset, delay, precision, max_dispersion, pulse_width;
|
double offset, delay, precision, max_dispersion, pulse_width;
|
||||||
char *p, *cmd, *name, *param;
|
char *p, *cmd, *name, *param;
|
||||||
@@ -704,6 +704,8 @@ parse_refclock(char *line)
|
|||||||
ref_id = 0;
|
ref_id = 0;
|
||||||
max_lock_age = 2;
|
max_lock_age = 2;
|
||||||
lock_ref_id = 0;
|
lock_ref_id = 0;
|
||||||
|
stratum = 0;
|
||||||
|
tai = 0;
|
||||||
|
|
||||||
if (!*line) {
|
if (!*line) {
|
||||||
command_parse_error();
|
command_parse_error();
|
||||||
@@ -774,6 +776,13 @@ parse_refclock(char *line)
|
|||||||
} else if (!strcasecmp(cmd, "maxdispersion")) {
|
} else if (!strcasecmp(cmd, "maxdispersion")) {
|
||||||
if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1)
|
if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1)
|
||||||
break;
|
break;
|
||||||
|
} else if (!strcasecmp(cmd, "stratum")) {
|
||||||
|
if (sscanf(line, "%d%n", &stratum, &n) != 1 ||
|
||||||
|
stratum >= NTP_MAX_STRATUM || stratum < 0)
|
||||||
|
break;
|
||||||
|
} else if (!strcasecmp(cmd, "tai")) {
|
||||||
|
n = 0;
|
||||||
|
tai = 1;
|
||||||
} else if (!strcasecmp(cmd, "width")) {
|
} else if (!strcasecmp(cmd, "width")) {
|
||||||
if (sscanf(line, "%lf%n", &pulse_width, &n) != 1)
|
if (sscanf(line, "%lf%n", &pulse_width, &n) != 1)
|
||||||
break;
|
break;
|
||||||
@@ -811,6 +820,8 @@ parse_refclock(char *line)
|
|||||||
refclock->min_samples = min_samples;
|
refclock->min_samples = min_samples;
|
||||||
refclock->max_samples = max_samples;
|
refclock->max_samples = max_samples;
|
||||||
refclock->sel_options = sel_options;
|
refclock->sel_options = sel_options;
|
||||||
|
refclock->stratum = stratum;
|
||||||
|
refclock->tai = tai;
|
||||||
refclock->offset = offset;
|
refclock->offset = offset;
|
||||||
refclock->delay = delay;
|
refclock->delay = delay;
|
||||||
refclock->precision = precision;
|
refclock->precision = precision;
|
||||||
|
|||||||
29
configure
vendored
29
configure
vendored
@@ -85,6 +85,7 @@ For better control, use the options below.
|
|||||||
--with-readline-library=DIR Specify where readline lib directory is
|
--with-readline-library=DIR Specify where readline lib directory is
|
||||||
--with-ncurses-library=DIR Specify where ncurses lib directory is
|
--with-ncurses-library=DIR Specify where ncurses lib directory is
|
||||||
--disable-sechash Disable support for hashes other than MD5
|
--disable-sechash Disable support for hashes other than MD5
|
||||||
|
--without-nettle Don't use nettle even if it is available
|
||||||
--without-nss Don't use NSS even if it is available
|
--without-nss Don't use NSS even if it is available
|
||||||
--without-tomcrypt Don't use libtomcrypt even if it is available
|
--without-tomcrypt Don't use libtomcrypt even if it is available
|
||||||
--disable-cmdmon Disable command and monitoring support
|
--disable-cmdmon Disable command and monitoring support
|
||||||
@@ -198,6 +199,7 @@ feat_readline=1
|
|||||||
try_readline=1
|
try_readline=1
|
||||||
try_editline=1
|
try_editline=1
|
||||||
feat_sechash=1
|
feat_sechash=1
|
||||||
|
try_nettle=1
|
||||||
try_nss=1
|
try_nss=1
|
||||||
try_tomcrypt=1
|
try_tomcrypt=1
|
||||||
feat_rtc=1
|
feat_rtc=1
|
||||||
@@ -360,6 +362,9 @@ do
|
|||||||
--disable-sechash )
|
--disable-sechash )
|
||||||
feat_sechash=0
|
feat_sechash=0
|
||||||
;;
|
;;
|
||||||
|
--without-nettle )
|
||||||
|
try_nettle=0
|
||||||
|
;;
|
||||||
--without-nss )
|
--without-nss )
|
||||||
try_nss=0
|
try_nss=0
|
||||||
;;
|
;;
|
||||||
@@ -550,7 +555,11 @@ then
|
|||||||
split_seconds=$ntp_era_split
|
split_seconds=$ntp_era_split
|
||||||
split_days=0
|
split_days=0
|
||||||
else
|
else
|
||||||
split_seconds=`date '+%s'`
|
if [ "x$SOURCE_DATE_EPOCH" != "x" ]; then
|
||||||
|
split_seconds=$SOURCE_DATE_EPOCH
|
||||||
|
else
|
||||||
|
split_seconds=`date '+%s'`
|
||||||
|
fi
|
||||||
if [ "x$split_seconds" = "x" ]; then
|
if [ "x$split_seconds" = "x" ]; then
|
||||||
echo "error: could not get current time, --with-ntp-era option is needed"
|
echo "error: could not get current time, --with-ntp-era option is needed"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -696,6 +705,7 @@ then
|
|||||||
struct scm_ts_pktinfo pktinfo;
|
struct scm_ts_pktinfo pktinfo;
|
||||||
pktinfo.if_index = pktinfo.pkt_length = 0;
|
pktinfo.if_index = pktinfo.pkt_length = 0;
|
||||||
return pktinfo.if_index + pktinfo.pkt_length + HWTSTAMP_FILTER_NTP_ALL +
|
return pktinfo.if_index + pktinfo.pkt_length + HWTSTAMP_FILTER_NTP_ALL +
|
||||||
|
SCM_TIMESTAMPING_PKTINFO +
|
||||||
SOF_TIMESTAMPING_OPT_PKTINFO + SOF_TIMESTAMPING_OPT_TX_SWHW;'; then
|
SOF_TIMESTAMPING_OPT_PKTINFO + SOF_TIMESTAMPING_OPT_TX_SWHW;'; then
|
||||||
add_def HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP 1
|
add_def HAVE_LINUX_TIMESTAMPING_RXFILTER_NTP 1
|
||||||
add_def HAVE_LINUX_TIMESTAMPING_OPT_PKTINFO 1
|
add_def HAVE_LINUX_TIMESTAMPING_OPT_PKTINFO 1
|
||||||
@@ -852,7 +862,22 @@ fi
|
|||||||
HASH_OBJ="hash_intmd5.o"
|
HASH_OBJ="hash_intmd5.o"
|
||||||
HASH_LINK=""
|
HASH_LINK=""
|
||||||
|
|
||||||
if [ $feat_sechash = "1" ] && [ $try_nss = "1" ]; then
|
if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_nettle = "1" ]; then
|
||||||
|
test_cflags="`pkg_config --cflags nettle`"
|
||||||
|
test_link="`pkg_config --libs nettle`"
|
||||||
|
if test_code 'nettle' 'nettle/nettle-meta.h nettle/sha2.h' \
|
||||||
|
"$test_cflags" "$test_link" \
|
||||||
|
'return nettle_hashes[0]->context_size;'
|
||||||
|
then
|
||||||
|
HASH_OBJ="hash_nettle.o"
|
||||||
|
HASH_LINK="$test_link"
|
||||||
|
LIBS="$LIBS $HASH_LINK"
|
||||||
|
MYCPPFLAGS="$MYCPPFLAGS $test_cflags"
|
||||||
|
add_def FEAT_SECHASH
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_nss = "1" ]; then
|
||||||
test_cflags="`pkg_config --cflags nss`"
|
test_cflags="`pkg_config --cflags nss`"
|
||||||
test_link="`pkg_config --libs-only-L nss` -lfreebl3"
|
test_link="`pkg_config --libs-only-L nss` -lfreebl3"
|
||||||
if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \
|
if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \
|
||||||
|
|||||||
@@ -66,33 +66,40 @@ server, or its IP address. The *server* directive supports the following
|
|||||||
options:
|
options:
|
||||||
+
|
+
|
||||||
*minpoll* _poll_:::
|
*minpoll* _poll_:::
|
||||||
Although *chronyd* will trim the rate at which it samples the server during
|
This option specifies the minimum interval between requests sent to the server
|
||||||
normal operation, the user might want to constrain the minimum polling interval.
|
as a power of 2 in seconds. For example, *minpoll 5* would mean that the
|
||||||
This is always defined as a power of 2, so *minpoll 5* would mean that the
|
polling interval should not drop below 32 seconds. The default is 6 (64
|
||||||
polling interval cannot drop below 32 seconds. The default is 6 (64 seconds),
|
seconds), the minimum is -4 (1/16th of a second), and the maximum is 24 (6
|
||||||
the minimum is -4 (1/16th of a second), and the maximum is 24 (6 months). Note
|
months). Note that intervals shorter than 6 (64 seconds) should generally not
|
||||||
that intervals shorter than 6 (64 seconds) should generally not be used with
|
be used with public servers on the Internet, because it might be considered
|
||||||
public servers on the Internet, because it might be considered abuse.
|
abuse.
|
||||||
*maxpoll* _poll_:::
|
*maxpoll* _poll_:::
|
||||||
In a similar way, the user might want to constrain the maximum polling interval.
|
This option specifies the maximum interval between requests sent to the server
|
||||||
Again this is specified as a power of 2, *maxpoll 9* indicates that the polling
|
as a power of 2 in seconds. For example, *maxpoll 9* indicates that the polling
|
||||||
interval must stay at or below 512 seconds. The default is 10 (1024 seconds),
|
interval should stay at or below 9 (512 seconds). The default is 10 (1024
|
||||||
the minimum is 0 (1 second), and the maximum is 24 (6 months).
|
seconds), the minimum is 0 (1 second), and the maximum is 24 (6 months).
|
||||||
*iburst*:::
|
*iburst*:::
|
||||||
If this option is set, the interval between the first four polls will be 2
|
With this option, the interval between the first four requests sent to the
|
||||||
seconds instead of _minpoll_. This is useful to quickly get the first update of
|
server will be 2 seconds instead of the interval specified by the *minpoll*
|
||||||
the clock after *chronyd* is started.
|
option, which allows *chronyd* to make the first update of the clock shortly
|
||||||
*key* _id_:::
|
after start.
|
||||||
|
*burst*:::
|
||||||
|
With this option, *chronyd* will shorten the interval between up to four
|
||||||
|
requests to 2 seconds when it cannot get a good measurement from the server.
|
||||||
|
The number of requests in the burst is limited by the current polling interval
|
||||||
|
to keep the average interval at or above the minimum interval, i.e. the current
|
||||||
|
interval needs to be at least two times longer than the minimum interval in
|
||||||
|
order to allow a burst with two requests.
|
||||||
|
*key* _ID_:::
|
||||||
The NTP protocol supports the inclusion of checksums in the packets, to prevent
|
The NTP protocol supports the inclusion of checksums in the packets, to prevent
|
||||||
computers having their system time upset by rogue packets being sent to them.
|
computers having their system time upset by rogue packets being sent to them.
|
||||||
The checksums are generated as a function of a password, using the
|
The checksums are generated as a function of a password, using the
|
||||||
cryptographic hash function set in the key file, which is specified by the
|
cryptographic hash function set in the key file, which is specified by the
|
||||||
<<keyfile,*keyfile*>> directive.
|
<<keyfile,*keyfile*>> directive.
|
||||||
+
|
+
|
||||||
If the key option is present, *chronyd* will attempt to use authenticated
|
The *key* option specifies which key (with an ID in the range 1 through 2^32-1)
|
||||||
packets when communicating with this server. The key number used will be the
|
should *chronyd* use to authenticate requests sent to the server and verify its
|
||||||
single argument to the key option (an unsigned integer in the range 1 through
|
responses. The server must have the same key for this number configured,
|
||||||
2^32-1). The server must have the same password for this key number configured,
|
|
||||||
otherwise no relationship between the computers will be possible.
|
otherwise no relationship between the computers will be possible.
|
||||||
*maxdelay* _delay_:::
|
*maxdelay* _delay_:::
|
||||||
*chronyd* uses the network round-trip delay to the server to determine how
|
*chronyd* uses the network round-trip delay to the server to determine how
|
||||||
@@ -113,7 +120,7 @@ option. For example, *maxdelay 0.3* would indicate that measurements with a
|
|||||||
round-trip delay of 0.3 seconds or more should be ignored. The default value is
|
round-trip delay of 0.3 seconds or more should be ignored. The default value is
|
||||||
3 seconds and the maximum value is 1000 seconds.
|
3 seconds and the maximum value is 1000 seconds.
|
||||||
*maxdelayratio* _ratio_:::
|
*maxdelayratio* _ratio_:::
|
||||||
This option is similar to the maxdelay option above. *chronyd* keeps a record
|
This option is similar to the *maxdelay* option above. *chronyd* keeps a record
|
||||||
of the minimum round-trip delay amongst the previous measurements that it has
|
of the minimum round-trip delay amongst the previous measurements that it has
|
||||||
buffered. If a measurement has a round trip delay that is greater than the
|
buffered. If a measurement has a round trip delay that is greater than the
|
||||||
maxdelayratio times the minimum delay, it will be rejected.
|
maxdelayratio times the minimum delay, it will be rejected.
|
||||||
@@ -123,14 +130,14 @@ minimum delay amongst the previous measurements to the standard deviation of
|
|||||||
the previous measurements that is greater than the specified ratio, it will be
|
the previous measurements that is greater than the specified ratio, it will be
|
||||||
rejected. The default is 10.0.
|
rejected. The default is 10.0.
|
||||||
*mindelay* _delay_:::
|
*mindelay* _delay_:::
|
||||||
This options specifies a fixed minimum round-trip delay to be used instead of
|
This option specifies a fixed minimum round-trip delay to be used instead of
|
||||||
the minimum amongst the previous measurements. This can be useful in networks
|
the minimum amongst the previous measurements. This can be useful in networks
|
||||||
with static configuration to improve the stability of corrections for
|
with static configuration to improve the stability of corrections for
|
||||||
asymmetric jitter, weighting of the measurements, and the *maxdelayratio* and
|
asymmetric jitter, weighting of the measurements, and the *maxdelayratio* and
|
||||||
*maxdelaydevratio* tests. The value should be set accurately in order to have a
|
*maxdelaydevratio* tests. The value should be set accurately in order to have a
|
||||||
positive effect on the synchronisation.
|
positive effect on the synchronisation.
|
||||||
*asymmetry* _ratio_:::
|
*asymmetry* _ratio_:::
|
||||||
This options specifies the asymmetry of the network jitter on the path to the
|
This option specifies the asymmetry of the network jitter on the path to the
|
||||||
source, which is used to correct the measured offset according to the delay.
|
source, which is used to correct the measured offset according to the delay.
|
||||||
The asymmetry can be between -0.5 and +0.5. A negative value means the delay of
|
The asymmetry can be between -0.5 and +0.5. A negative value means the delay of
|
||||||
packets sent to the source is more variable than the delay of packets sent from
|
packets sent to the source is more variable than the delay of packets sent from
|
||||||
@@ -154,14 +161,15 @@ option can be specified. *chronyd* will not try to poll the server until it is
|
|||||||
enabled to do so (by using the <<chronyc.adoc#online,*online*>> command in
|
enabled to do so (by using the <<chronyc.adoc#online,*online*>> command in
|
||||||
*chronyc*).
|
*chronyc*).
|
||||||
*auto_offline*:::
|
*auto_offline*:::
|
||||||
If this option is set, the server will be assumed to have gone offline when 2
|
With this option, the server will be assumed to have gone offline when two
|
||||||
requests have been sent to it without receiving a response. This option avoids
|
requests have been sent to it without receiving a response. This option avoids
|
||||||
the need to run the <<chronyc.adoc#offline,*offline*>> command from *chronyc*
|
the need to run the <<chronyc.adoc#offline,*offline*>> command from *chronyc*
|
||||||
when disconnecting the network link. (It will still be necessary to use the
|
when disconnecting the network link, if it is safe to assume that the requests
|
||||||
<<chronyc.adoc#online,*online*>> command when the link has been established, to
|
and responses will not be dropped in the network, e.g. in a trusted local
|
||||||
enable measurements to start.)
|
network. (It will still be necessary to use the <<chronyc.adoc#online,*online*>>
|
||||||
|
command when the link has been established, to enable measurements to start.)
|
||||||
*prefer*:::
|
*prefer*:::
|
||||||
Prefer this source over sources without prefer option.
|
Prefer this source over sources without the *prefer* option.
|
||||||
*noselect*:::
|
*noselect*:::
|
||||||
Never select this source. This is particularly useful for monitoring.
|
Never select this source. This is particularly useful for monitoring.
|
||||||
*trust*:::
|
*trust*:::
|
||||||
@@ -516,6 +524,9 @@ is included in the maximum assumed error which is used in the source selection
|
|||||||
algorithm. Increasing the delay is useful to avoid having no majority in the
|
algorithm. Increasing the delay is useful to avoid having no majority in the
|
||||||
source selection or to make it prefer other sources. The default is 1e-9 (1
|
source selection or to make it prefer other sources. The default is 1e-9 (1
|
||||||
nanosecond).
|
nanosecond).
|
||||||
|
*stratum* _stratum_:::
|
||||||
|
This option sets the NTP stratum of the refclock. This can be useful when the
|
||||||
|
refclock provides time with a stratum other than 0. The default is 0.
|
||||||
*precision* _precision_:::
|
*precision* _precision_:::
|
||||||
This option sets the precision of the reference clock (in seconds). The default
|
This option sets the precision of the reference clock (in seconds). The default
|
||||||
value is the estimated precision of the system clock.
|
value is the estimated precision of the system clock.
|
||||||
@@ -546,6 +557,12 @@ but not very precise, reference clock to be safely combined with
|
|||||||
unauthenticated NTP sources in order to improve the accuracy of the clock. They
|
unauthenticated NTP sources in order to improve the accuracy of the clock. They
|
||||||
can be selected and used for synchronisation only if they agree with the
|
can be selected and used for synchronisation only if they agree with the
|
||||||
trusted and required source.
|
trusted and required source.
|
||||||
|
*tai*:::
|
||||||
|
This option indicates that the reference clock keeps time in TAI instead of UTC
|
||||||
|
and that *chronyd* should correct its offset by the current TAI-UTC offset. The
|
||||||
|
<<leapsectz,*leapsectz*>> directive must be used with this option and the
|
||||||
|
database must be kept up to date in order for this correction to work as
|
||||||
|
expected. This option does not make sense with PPS refclocks.
|
||||||
*minsamples* _samples_:::
|
*minsamples* _samples_:::
|
||||||
Set the minimum number of samples kept for this source. This overrides the
|
Set the minimum number of samples kept for this source. This overrides the
|
||||||
<<minsamples,*minsamples*>> directive.
|
<<minsamples,*minsamples*>> directive.
|
||||||
@@ -862,6 +879,11 @@ It is also useful when the system clock is required to have correct TAI-UTC
|
|||||||
offset. Note that the offset is set only when leap seconds are handled by the
|
offset. Note that the offset is set only when leap seconds are handled by the
|
||||||
kernel, i.e. <<leapsecmode,*leapsecmode*>> is set to *system*.
|
kernel, i.e. <<leapsecmode,*leapsecmode*>> is set to *system*.
|
||||||
+
|
+
|
||||||
|
The specified timezone is not used as an exclusive source of information about
|
||||||
|
leap seconds. If a majority of time sources announce on the last day of June or
|
||||||
|
December that a leap second should be inserted or deleted, it will be accepted
|
||||||
|
even if it is not included in the timezone.
|
||||||
|
+
|
||||||
An example of the directive is:
|
An example of the directive is:
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@@ -1985,12 +2007,18 @@ format of the file is shown below:
|
|||||||
+
|
+
|
||||||
Each line consists of an ID, name of an authentication hash function (optional),
|
Each line consists of an ID, name of an authentication hash function (optional),
|
||||||
and a password. The ID can be any unsigned integer in the range 1 through
|
and a password. The ID can be any unsigned integer in the range 1 through
|
||||||
2^32-1. The default hash function is *MD5*. Depending on how *chronyd*
|
2^32-1. The default hash function is *MD5*, which is always supported.
|
||||||
was compiled, other supported functions might be *SHA1*, *SHA256*, *SHA384*,
|
+
|
||||||
*SHA512*, *RMD128*, *RMD160*, *RMD256*, *RMD320*, *TIGER*, and *WHIRLPOOL*. The
|
If *chronyd* was built with enabled support for hashing using a crypto library
|
||||||
password can be specified as a string of characters not containing white space
|
(nettle, nss, or libtomcrypt), the following functions are available: *MD5*,
|
||||||
with an optional *ASCII:* prefix, or as a hexadecimal number with the *HEX:*
|
*SHA1*, *SHA256*, *SHA384*, *SHA512*. Depending on which library and version is
|
||||||
prefix. The maximum length of the line is 2047 characters.
|
*chronyd* using, some or all of the following functions may also be available:
|
||||||
|
*SHA3-224*, *SHA3-256*, *SHA3-384*, *SHA3-512*, *RMD128*, *RMD160*, *RMD256*,
|
||||||
|
*RMD320*, *TIGER*, *WHIRLPOOL*.
|
||||||
|
+
|
||||||
|
The password can be specified as a string of characters not containing white
|
||||||
|
space with an optional *ASCII:* prefix, or as a hexadecimal number with the
|
||||||
|
*HEX:* prefix. The maximum length of the line is 2047 characters.
|
||||||
+
|
+
|
||||||
The password is used with the hash function to generate and verify a message
|
The password is used with the hash function to generate and verify a message
|
||||||
authentication code (MAC) in NTP packets. It is recommended to use SHA1, or
|
authentication code (MAC) in NTP packets. It is recommended to use SHA1, or
|
||||||
|
|||||||
@@ -1128,6 +1128,10 @@ running.
|
|||||||
The *rekey* command causes *chronyd* to re-read the key file specified in the
|
The *rekey* command causes *chronyd* to re-read the key file specified in the
|
||||||
configuration file by the <<chrony.conf.adoc#keyfile,*keyfile*>> directive.
|
configuration file by the <<chrony.conf.adoc#keyfile,*keyfile*>> directive.
|
||||||
|
|
||||||
|
[[rekey]]*shutdown*::
|
||||||
|
The *shutdown* command causes *chronyd* to exit. This is equivalent to sending
|
||||||
|
the process the SIGTERM signal.
|
||||||
|
|
||||||
=== Client commands
|
=== Client commands
|
||||||
|
|
||||||
[[dns]]*dns* _option_::
|
[[dns]]*dns* _option_::
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ range of privileged system calls on behalf of the parent.
|
|||||||
*-F* _level_::
|
*-F* _level_::
|
||||||
This option configures a system call filter when *chronyd* is compiled with
|
This option configures a system call filter when *chronyd* is compiled with
|
||||||
support for the Linux secure computing (seccomp) facility. In level 1 the
|
support for the Linux secure computing (seccomp) facility. In level 1 the
|
||||||
process is killed when a forbidden system call is made, in level -1 the SYSSIG
|
process is killed when a forbidden system call is made, in level -1 the SIGSYS
|
||||||
signal is thrown instead and in level 0 the filter is disabled (default 0).
|
signal is thrown instead and in level 0 the filter is disabled (default 0).
|
||||||
+
|
+
|
||||||
It's recommended to enable the filter only when it's known to work on the
|
It's recommended to enable the filter only when it's known to work on the
|
||||||
@@ -157,11 +157,13 @@ This option will lock *chronyd* into RAM so that it will never be paged out.
|
|||||||
This mode is only supported on Linux.
|
This mode is only supported on Linux.
|
||||||
|
|
||||||
*-x*::
|
*-x*::
|
||||||
This option disables the control of the system clock. *chronyd* will not make
|
This option disables the control of the system clock. *chronyd* will not try to
|
||||||
any adjustments of the clock, but it will still track its offset and frequency
|
make any adjustments of the clock. It will assume the clock is free running and
|
||||||
relative to the estimated true time, and be able to operate as an NTP server.
|
still track its offset and frequency relative to the estimated true time. This
|
||||||
This allows *chronyd* to run without the capability to adjust or set the system
|
option allows *chronyd* to run without the capability to adjust or set the
|
||||||
clock (e.g. in some containers).
|
system clock (e.g. in some containers) in order to operate as an NTP server. It
|
||||||
|
is not recommended to run *chronyd* (with or without *-x*) when another process
|
||||||
|
is controlling the system clock.
|
||||||
|
|
||||||
*-v*::
|
*-v*::
|
||||||
With this option *chronyd* will print version number to the terminal and exit.
|
With this option *chronyd* will print version number to the terminal and exit.
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
export LC_ALL=C
|
export LC_ALL=C
|
||||||
|
|
||||||
|
[ "$2" != "up" ] && [ "$2" != "down" ] && exit 0
|
||||||
|
|
||||||
# Check if there is a default route
|
# Check if there is a default route
|
||||||
|
|
||||||
if /sbin/ip route list 2> /dev/null | grep -q '^default'; then
|
if /sbin/ip route list 2> /dev/null | grep -q '^default'; then
|
||||||
|
|||||||
120
hash_nettle.c
Normal file
120
hash_nettle.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Miroslav Lichvar 2018
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Routines implementing crypto hashing using the nettle library.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "sysincl.h"
|
||||||
|
|
||||||
|
#include <nettle/nettle-meta.h>
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
struct hash {
|
||||||
|
const char *name;
|
||||||
|
const char *int_name;
|
||||||
|
const struct nettle_hash *nettle_hash;
|
||||||
|
void *context;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct hash hashes[] = {
|
||||||
|
{ "MD5", "md5", NULL, NULL },
|
||||||
|
{ "RMD160", "ripemd160", NULL, NULL },
|
||||||
|
{ "SHA1", "sha1", NULL, NULL },
|
||||||
|
{ "SHA256", "sha256", NULL, NULL },
|
||||||
|
{ "SHA384", "sha384", NULL, NULL },
|
||||||
|
{ "SHA512", "sha512", NULL, NULL },
|
||||||
|
{ "SHA3-224", "sha3_224", NULL, NULL },
|
||||||
|
{ "SHA3-256", "sha3_256", NULL, NULL },
|
||||||
|
{ "SHA3-384", "sha3_384", NULL, NULL },
|
||||||
|
{ "SHA3-512", "sha3_512", NULL, NULL },
|
||||||
|
{ NULL, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
HSH_GetHashId(const char *name)
|
||||||
|
{
|
||||||
|
int id, nid;
|
||||||
|
|
||||||
|
for (id = 0; hashes[id].name; id++) {
|
||||||
|
if (!strcmp(name, hashes[id].name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hashes[id].name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hashes[id].context)
|
||||||
|
return id;
|
||||||
|
|
||||||
|
for (nid = 0; nettle_hashes[nid]; nid++) {
|
||||||
|
if (!strcmp(hashes[id].int_name, nettle_hashes[nid]->name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nettle_hashes[nid] || !nettle_hashes[nid]->context_size || !nettle_hashes[nid]->init)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hashes[id].nettle_hash = nettle_hashes[nid];
|
||||||
|
hashes[id].context = Malloc(hashes[id].nettle_hash->context_size);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
|
||||||
|
const unsigned char *in2, unsigned int in2_len,
|
||||||
|
unsigned char *out, unsigned int out_len)
|
||||||
|
{
|
||||||
|
const struct nettle_hash *hash;
|
||||||
|
void *context;
|
||||||
|
|
||||||
|
hash = hashes[id].nettle_hash;
|
||||||
|
context = hashes[id].context;
|
||||||
|
|
||||||
|
if (out_len > hash->digest_size)
|
||||||
|
out_len = hash->digest_size;
|
||||||
|
|
||||||
|
hash->init(context);
|
||||||
|
hash->update(context, in1_len, in1);
|
||||||
|
if (in2)
|
||||||
|
hash->update(context, in2_len, in2);
|
||||||
|
hash->digest(context, out_len, out);
|
||||||
|
|
||||||
|
return out_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HSH_Finalise(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; hashes[i].name; i++) {
|
||||||
|
if (hashes[i].context)
|
||||||
|
Free(hashes[i].context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,6 +62,12 @@ static const struct hash hashes[] = {
|
|||||||
#ifdef LTC_SHA512
|
#ifdef LTC_SHA512
|
||||||
{ "SHA512", "sha512", &sha512_desc },
|
{ "SHA512", "sha512", &sha512_desc },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LTC_SHA3
|
||||||
|
{ "SHA3-224", "sha3-224", &sha3_224_desc },
|
||||||
|
{ "SHA3-256", "sha3-256", &sha3_256_desc },
|
||||||
|
{ "SHA3-384", "sha3-384", &sha3_384_desc },
|
||||||
|
{ "SHA3-512", "sha3-512", &sha3_512_desc },
|
||||||
|
#endif
|
||||||
#ifdef LTC_TIGER
|
#ifdef LTC_TIGER
|
||||||
{ "TIGER", "tiger", &tiger_desc },
|
{ "TIGER", "tiger", &tiger_desc },
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
30
logging.c
30
logging.c
@@ -79,11 +79,11 @@ LOG_Initialise(void)
|
|||||||
void
|
void
|
||||||
LOG_Finalise(void)
|
LOG_Finalise(void)
|
||||||
{
|
{
|
||||||
if (system_log) {
|
if (system_log)
|
||||||
closelog();
|
closelog();
|
||||||
} else {
|
|
||||||
|
if (file_log)
|
||||||
fclose(file_log);
|
fclose(file_log);
|
||||||
}
|
|
||||||
|
|
||||||
LOG_CycleLogFiles();
|
LOG_CycleLogFiles();
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ static void log_message(int fatal, LOG_Severity severity, const char *message)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
syslog(priority, fatal ? "Fatal error : %s" : "%s", message);
|
syslog(priority, fatal ? "Fatal error : %s" : "%s", message);
|
||||||
} else {
|
} else if (file_log) {
|
||||||
fprintf(file_log, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
fprintf(file_log, fatal ? "Fatal error : %s\n" : "%s\n", message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ void LOG_Message(LOG_Severity severity,
|
|||||||
time_t t;
|
time_t t;
|
||||||
struct tm stm;
|
struct tm stm;
|
||||||
|
|
||||||
if (!system_log) {
|
if (!system_log && file_log) {
|
||||||
/* Don't clutter up syslog with timestamps and internal debugging info */
|
/* Don't clutter up syslog with timestamps and internal debugging info */
|
||||||
time(&t);
|
time(&t);
|
||||||
stm = *gmtime(&t);
|
stm = *gmtime(&t);
|
||||||
@@ -160,16 +160,14 @@ void LOG_Message(LOG_Severity severity,
|
|||||||
case LOGS_FATAL:
|
case LOGS_FATAL:
|
||||||
log_message(1, severity, buf);
|
log_message(1, severity, buf);
|
||||||
|
|
||||||
/* With syslog, send the message also to the grandparent
|
/* Send the message also to the foreground process if it is
|
||||||
process or write it to stderr if not detached */
|
still running, or stderr if it is still open */
|
||||||
if (system_log) {
|
if (parent_fd > 0) {
|
||||||
if (parent_fd > 0) {
|
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
|
||||||
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
|
; /* Not much we can do here */
|
||||||
; /* Not much we can do here */
|
} else if (system_log && parent_fd == 0) {
|
||||||
} else if (parent_fd == 0) {
|
system_log = 0;
|
||||||
system_log = 0;
|
log_message(1, severity, buf);
|
||||||
log_message(1, severity, buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -220,6 +218,8 @@ void
|
|||||||
LOG_SetParentFd(int fd)
|
LOG_SetParentFd(int fd)
|
||||||
{
|
{
|
||||||
parent_fd = fd;
|
parent_fd = fd;
|
||||||
|
if (file_log == stderr)
|
||||||
|
file_log = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ extern void LOG_OpenFileLog(const char *log_file);
|
|||||||
/* Log messages to syslog instead of stderr */
|
/* Log messages to syslog instead of stderr */
|
||||||
extern void LOG_OpenSystemLog(void);
|
extern void LOG_OpenSystemLog(void);
|
||||||
|
|
||||||
/* Send fatal message also to the foreground process */
|
/* Stop using stderr and send fatal message to the foreground process */
|
||||||
extern void LOG_SetParentFd(int fd);
|
extern void LOG_SetParentFd(int fd);
|
||||||
|
|
||||||
/* Close the pipe to the foreground process so it can exit */
|
/* Close the pipe to the foreground process so it can exit */
|
||||||
|
|||||||
29
main.c
29
main.c
@@ -292,6 +292,8 @@ write_pidfile(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
#define DEV_NULL "/dev/null"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
go_daemon(void)
|
go_daemon(void)
|
||||||
{
|
{
|
||||||
@@ -352,6 +354,13 @@ go_daemon(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG_SetParentFd(pipefd[1]);
|
LOG_SetParentFd(pipefd[1]);
|
||||||
|
|
||||||
|
/* Open /dev/null as new stdin/out/err */
|
||||||
|
errno = 0;
|
||||||
|
if (open(DEV_NULL, O_RDONLY) != STDIN_FILENO ||
|
||||||
|
open(DEV_NULL, O_WRONLY) != STDOUT_FILENO ||
|
||||||
|
open(DEV_NULL, O_RDWR) != STDERR_FILENO)
|
||||||
|
LOG_FATAL("Could not open %s : %s", DEV_NULL, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,6 +533,16 @@ int main
|
|||||||
/* Write our pidfile to prevent other chronyds running */
|
/* Write our pidfile to prevent other chronyds running */
|
||||||
write_pidfile();
|
write_pidfile();
|
||||||
|
|
||||||
|
if (!user)
|
||||||
|
user = CNF_GetUser();
|
||||||
|
|
||||||
|
pw = getpwnam(user);
|
||||||
|
if (!pw)
|
||||||
|
LOG_FATAL("Could not get user/group ID of %s", user);
|
||||||
|
|
||||||
|
/* Create directories for sockets, log files, and dump files */
|
||||||
|
CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
|
||||||
|
|
||||||
PRV_Initialise();
|
PRV_Initialise();
|
||||||
LCL_Initialise();
|
LCL_Initialise();
|
||||||
SCH_Initialise();
|
SCH_Initialise();
|
||||||
@@ -551,16 +570,6 @@ int main
|
|||||||
SYS_LockMemory();
|
SYS_LockMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
user = CNF_GetUser();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pw = getpwnam(user)) == NULL)
|
|
||||||
LOG_FATAL("Could not get %s uid/gid", user);
|
|
||||||
|
|
||||||
/* Create all directories before dropping root */
|
|
||||||
CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
|
|
||||||
|
|
||||||
/* Drop root privileges if the specified user has a non-zero UID */
|
/* Drop root privileges if the specified user has a non-zero UID */
|
||||||
if (!geteuid() && (pw->pw_uid || pw->pw_gid))
|
if (!geteuid() && (pw->pw_uid || pw->pw_gid))
|
||||||
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
SYS_DropRoot(pw->pw_uid, pw->pw_gid);
|
||||||
|
|||||||
14
nameserv.c
14
nameserv.c
@@ -53,7 +53,19 @@ DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs)
|
|||||||
max_addrs = MIN(max_addrs, DNS_MAX_ADDRESSES);
|
max_addrs = MIN(max_addrs, DNS_MAX_ADDRESSES);
|
||||||
|
|
||||||
memset(&hints, 0, sizeof (hints));
|
memset(&hints, 0, sizeof (hints));
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
|
switch (address_family) {
|
||||||
|
case IPADDR_INET4:
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
break;
|
||||||
|
#ifdef FEAT_IPV6
|
||||||
|
case IPADDR_INET6:
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
}
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
result = getaddrinfo(name, NULL, &hints, &res);
|
result = getaddrinfo(name, NULL, &hints, &res);
|
||||||
|
|||||||
163
ntp_core.c
163
ntp_core.c
@@ -88,6 +88,7 @@ struct NCR_Instance_Record {
|
|||||||
SCH_TimeoutID tx_timeout_id; /* Timeout ID for next transmission */
|
SCH_TimeoutID tx_timeout_id; /* Timeout ID for next transmission */
|
||||||
int tx_suspended; /* Boolean indicating we can't transmit yet */
|
int tx_suspended; /* Boolean indicating we can't transmit yet */
|
||||||
|
|
||||||
|
int auto_burst; /* If 1, initiate a burst on each poll */
|
||||||
int auto_offline; /* If 1, automatically go offline if server/peer
|
int auto_offline; /* If 1, automatically go offline if server/peer
|
||||||
isn't responding */
|
isn't responding */
|
||||||
|
|
||||||
@@ -149,14 +150,11 @@ struct NCR_Instance_Record {
|
|||||||
be used for synchronisation */
|
be used for synchronisation */
|
||||||
int valid_timestamps;
|
int valid_timestamps;
|
||||||
|
|
||||||
/* Flag indicating the timestamps below were updated since last request */
|
/* Receive and transmit timestamps from the last valid response */
|
||||||
int updated_timestamps;
|
|
||||||
|
|
||||||
/* Receive and transmit timestamps from the last received packet */
|
|
||||||
NTP_int64 remote_ntp_rx;
|
NTP_int64 remote_ntp_rx;
|
||||||
NTP_int64 remote_ntp_tx;
|
NTP_int64 remote_ntp_tx;
|
||||||
|
|
||||||
/* Local timestamp when the last packet was received from the
|
/* Local timestamp when the last valid response was received from the
|
||||||
source. We have to be prepared to tinker with this if the local
|
source. We have to be prepared to tinker with this if the local
|
||||||
clock has its frequency adjusted before we repond. The value we
|
clock has its frequency adjusted before we repond. The value we
|
||||||
store here is what our own local time was when the same arrived.
|
store here is what our own local time was when the same arrived.
|
||||||
@@ -183,6 +181,15 @@ struct NCR_Instance_Record {
|
|||||||
int prev_local_poll;
|
int prev_local_poll;
|
||||||
unsigned int prev_tx_count;
|
unsigned int prev_tx_count;
|
||||||
|
|
||||||
|
/* Flag indicating the two timestamps below were updated since the
|
||||||
|
last transmission */
|
||||||
|
int updated_init_timestamps;
|
||||||
|
|
||||||
|
/* Timestamps used for (re)starting the symmetric protocol, when we
|
||||||
|
need to respond to a packet which is not a valid response */
|
||||||
|
NTP_int64 init_remote_ntp_tx;
|
||||||
|
NTP_Local_Timestamp init_local_rx;
|
||||||
|
|
||||||
/* The instance record in the main source management module. This
|
/* The instance record in the main source management module. This
|
||||||
performs the statistical analysis on the samples we generate */
|
performs the statistical analysis on the samples we generate */
|
||||||
|
|
||||||
@@ -230,6 +237,10 @@ static ARR_Instance broadcasts;
|
|||||||
#define IBURST_GOOD_SAMPLES 4
|
#define IBURST_GOOD_SAMPLES 4
|
||||||
#define IBURST_TOTAL_SAMPLES SOURCE_REACH_BITS
|
#define IBURST_TOTAL_SAMPLES SOURCE_REACH_BITS
|
||||||
|
|
||||||
|
/* Number of samples in automatic burst */
|
||||||
|
#define BURST_GOOD_SAMPLES 1
|
||||||
|
#define MAX_BURST_TOTAL_SAMPLES 4
|
||||||
|
|
||||||
/* Time to wait after sending packet to 'warm up' link */
|
/* Time to wait after sending packet to 'warm up' link */
|
||||||
#define WARM_UP_DELAY 2.0
|
#define WARM_UP_DELAY 2.0
|
||||||
|
|
||||||
@@ -551,6 +562,7 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
|||||||
result->max_delay_ratio = CLAMP(0.0, params->max_delay_ratio, MAX_MAXDELAYRATIO);
|
result->max_delay_ratio = CLAMP(0.0, params->max_delay_ratio, MAX_MAXDELAYRATIO);
|
||||||
result->max_delay_dev_ratio = CLAMP(0.0, params->max_delay_dev_ratio, MAX_MAXDELAYDEVRATIO);
|
result->max_delay_dev_ratio = CLAMP(0.0, params->max_delay_dev_ratio, MAX_MAXDELAYDEVRATIO);
|
||||||
result->offset_correction = params->offset;
|
result->offset_correction = params->offset;
|
||||||
|
result->auto_burst = params->burst;
|
||||||
result->auto_offline = params->auto_offline;
|
result->auto_offline = params->auto_offline;
|
||||||
result->poll_target = params->poll_target;
|
result->poll_target = params->poll_target;
|
||||||
|
|
||||||
@@ -652,7 +664,6 @@ NCR_ResetInstance(NCR_Instance instance)
|
|||||||
|
|
||||||
instance->valid_rx = 0;
|
instance->valid_rx = 0;
|
||||||
instance->valid_timestamps = 0;
|
instance->valid_timestamps = 0;
|
||||||
instance->updated_timestamps = 0;
|
|
||||||
UTI_ZeroNtp64(&instance->remote_ntp_rx);
|
UTI_ZeroNtp64(&instance->remote_ntp_rx);
|
||||||
UTI_ZeroNtp64(&instance->remote_ntp_tx);
|
UTI_ZeroNtp64(&instance->remote_ntp_tx);
|
||||||
UTI_ZeroNtp64(&instance->local_ntp_rx);
|
UTI_ZeroNtp64(&instance->local_ntp_rx);
|
||||||
@@ -662,6 +673,10 @@ NCR_ResetInstance(NCR_Instance instance)
|
|||||||
zero_local_timestamp(&instance->prev_local_tx);
|
zero_local_timestamp(&instance->prev_local_tx);
|
||||||
instance->prev_local_poll = 0;
|
instance->prev_local_poll = 0;
|
||||||
instance->prev_tx_count = 0;
|
instance->prev_tx_count = 0;
|
||||||
|
|
||||||
|
instance->updated_init_timestamps = 0;
|
||||||
|
UTI_ZeroNtp64(&instance->init_remote_ntp_tx);
|
||||||
|
zero_local_timestamp(&instance->init_local_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -890,8 +905,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */
|
NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */
|
||||||
NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet
|
NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet
|
||||||
RESULT : TX time of this packet */
|
RESULT : TX time of this packet */
|
||||||
NTP_int64 *local_ntp_rx, /* RESULT : receive timestamp from this packet */
|
NTP_int64 *local_ntp_rx, /* The receive timestamp from the previous packet
|
||||||
NTP_int64 *local_ntp_tx, /* RESULT : transmit timestamp from this packet */
|
RESULT : receive timestamp from this packet */
|
||||||
|
NTP_int64 *local_ntp_tx, /* The transmit timestamp from the previous packet
|
||||||
|
RESULT : transmit timestamp from this packet */
|
||||||
NTP_Remote_Address *where_to, /* Where to address the reponse to */
|
NTP_Remote_Address *where_to, /* Where to address the reponse to */
|
||||||
NTP_Local_Address *from /* From what address to send it */
|
NTP_Local_Address *from /* From what address to send it */
|
||||||
)
|
)
|
||||||
@@ -914,8 +931,8 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
version = NTP_VERSION;
|
version = NTP_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow interleaved mode only if there was a prior transmission */
|
/* Check if the packet can be formed in the interleaved mode */
|
||||||
if (interleaved && (!local_tx || UTI_IsZeroTimespec(&local_tx->ts)))
|
if (interleaved && (!remote_ntp_rx || !local_tx || UTI_IsZeroTimespec(&local_tx->ts)))
|
||||||
interleaved = 0;
|
interleaved = 0;
|
||||||
|
|
||||||
smooth_time = 0;
|
smooth_time = 0;
|
||||||
@@ -989,14 +1006,21 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
/* Originate - this comes from the last packet the source sent us */
|
/* Originate - this comes from the last packet the source sent us */
|
||||||
message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx;
|
message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx;
|
||||||
|
|
||||||
/* Prepare random bits which will be added to the receive timestamp */
|
do {
|
||||||
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
/* Prepare random bits which will be added to the receive timestamp */
|
||||||
|
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
||||||
|
|
||||||
/* Receive - this is when we received the last packet from the source.
|
/* Receive - this is when we received the last packet from the source.
|
||||||
This timestamp will have been adjusted so that it will now look to
|
This timestamp will have been adjusted so that it will now look to
|
||||||
the source like we have been running on our latest estimate of
|
the source like we have been running on our latest estimate of
|
||||||
frequency all along */
|
frequency all along */
|
||||||
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
||||||
|
|
||||||
|
/* Do not send a packet with a non-zero receive timestamp equal to the
|
||||||
|
originate timestamp or previous receive timestamp */
|
||||||
|
} while (!UTI_IsZeroNtp64(&message.receive_ts) &&
|
||||||
|
UTI_IsEqualAnyNtp64(&message.receive_ts, &message.originate_ts,
|
||||||
|
local_ntp_rx, NULL));
|
||||||
} else {
|
} else {
|
||||||
UTI_ZeroNtp64(&message.originate_ts);
|
UTI_ZeroNtp64(&message.originate_ts);
|
||||||
UTI_ZeroNtp64(&message.receive_ts);
|
UTI_ZeroNtp64(&message.receive_ts);
|
||||||
@@ -1055,10 +1079,16 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
&message.transmit_ts, &ts_fuzz);
|
&message.transmit_ts, &ts_fuzz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoid sending messages with non-zero transmit timestamp equal to the
|
/* Do not send a packet with a non-zero transmit timestamp which is
|
||||||
receive timestamp to allow reliable detection of the interleaved mode */
|
equal to any of the following timestamps:
|
||||||
} while (!UTI_CompareNtp64(&message.transmit_ts, &message.receive_ts) &&
|
- receive (to allow reliable detection of the interleaved mode)
|
||||||
!UTI_IsZeroNtp64(&message.transmit_ts));
|
- originate (to prevent the packet from being its own valid response
|
||||||
|
in the symmetric mode)
|
||||||
|
- previous transmit (to invalidate responses to the previous packet)
|
||||||
|
(the precision must be at least -30 to prevent an infinite loop!) */
|
||||||
|
} while (!UTI_IsZeroNtp64(&message.transmit_ts) &&
|
||||||
|
UTI_IsEqualAnyNtp64(&message.transmit_ts, &message.receive_ts,
|
||||||
|
&message.originate_ts, local_ntp_tx));
|
||||||
|
|
||||||
ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
|
ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
|
||||||
|
|
||||||
@@ -1084,7 +1114,7 @@ transmit_timeout(void *arg)
|
|||||||
{
|
{
|
||||||
NCR_Instance inst = (NCR_Instance) arg;
|
NCR_Instance inst = (NCR_Instance) arg;
|
||||||
NTP_Local_Address local_addr;
|
NTP_Local_Address local_addr;
|
||||||
int interleaved, sent;
|
int interleaved, initial, sent;
|
||||||
|
|
||||||
inst->tx_timeout_id = 0;
|
inst->tx_timeout_id = 0;
|
||||||
|
|
||||||
@@ -1093,10 +1123,20 @@ transmit_timeout(void *arg)
|
|||||||
/* With online burst switch to online before last packet */
|
/* With online burst switch to online before last packet */
|
||||||
if (inst->burst_total_samples_to_go <= 1)
|
if (inst->burst_total_samples_to_go <= 1)
|
||||||
inst->opmode = MD_ONLINE;
|
inst->opmode = MD_ONLINE;
|
||||||
|
break;
|
||||||
case MD_BURST_WAS_OFFLINE:
|
case MD_BURST_WAS_OFFLINE:
|
||||||
if (inst->burst_total_samples_to_go <= 0)
|
if (inst->burst_total_samples_to_go <= 0)
|
||||||
take_offline(inst);
|
take_offline(inst);
|
||||||
break;
|
break;
|
||||||
|
case MD_ONLINE:
|
||||||
|
/* Start a new burst if the burst option is enabled and the average
|
||||||
|
polling interval including the burst will not fall below the
|
||||||
|
minimum polling interval */
|
||||||
|
if (inst->auto_burst && inst->local_poll > inst->minpoll && inst->local_poll > 1)
|
||||||
|
NCR_InitiateSampleBurst(inst, BURST_GOOD_SAMPLES,
|
||||||
|
MIN(1 << (inst->local_poll - inst->minpoll),
|
||||||
|
MAX_BURST_TOTAL_SAMPLES));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1137,6 +1177,19 @@ transmit_timeout(void *arg)
|
|||||||
(inst->mode == MODE_ACTIVE &&
|
(inst->mode == MODE_ACTIVE &&
|
||||||
inst->prev_tx_count == 1 && inst->tx_count == 0));
|
inst->prev_tx_count == 1 && inst->tx_count == 0));
|
||||||
|
|
||||||
|
/* In symmetric mode, if no valid response was received since the previous
|
||||||
|
transmission, respond to the last received packet even if it failed some
|
||||||
|
specific NTP tests. This is necessary for starting and restarting the
|
||||||
|
protocol, e.g. when a packet was lost. */
|
||||||
|
initial = inst->mode == MODE_ACTIVE && !inst->valid_rx &&
|
||||||
|
!UTI_IsZeroNtp64(&inst->init_remote_ntp_tx);
|
||||||
|
|
||||||
|
/* Prepare for the response */
|
||||||
|
inst->valid_rx = 0;
|
||||||
|
inst->updated_init_timestamps = 0;
|
||||||
|
if (initial)
|
||||||
|
inst->valid_timestamps = 0;
|
||||||
|
|
||||||
/* Check whether we need to 'warm up' the link to the other end by
|
/* Check whether we need to 'warm up' the link to the other end by
|
||||||
sending an NTP exchange to ensure both ends' ARP caches are
|
sending an NTP exchange to ensure both ends' ARP caches are
|
||||||
primed or whether we need to send two packets first to ensure a
|
primed or whether we need to send two packets first to ensure a
|
||||||
@@ -1148,18 +1201,16 @@ transmit_timeout(void *arg)
|
|||||||
inst->presend_done--;
|
inst->presend_done--;
|
||||||
}
|
}
|
||||||
|
|
||||||
sent = transmit_packet(inst->mode, interleaved, inst->local_poll,
|
/* Send the request (which may also be a response in the symmetric mode) */
|
||||||
inst->version,
|
sent = transmit_packet(inst->mode, interleaved, inst->local_poll, inst->version,
|
||||||
inst->auth_mode, inst->auth_key_id,
|
inst->auth_mode, inst->auth_key_id,
|
||||||
&inst->remote_ntp_rx, &inst->remote_ntp_tx,
|
initial ? NULL : &inst->remote_ntp_rx,
|
||||||
&inst->local_rx, &inst->local_tx,
|
initial ? &inst->init_remote_ntp_tx : &inst->remote_ntp_tx,
|
||||||
&inst->local_ntp_rx, &inst->local_ntp_tx,
|
initial ? &inst->init_local_rx : &inst->local_rx,
|
||||||
&inst->remote_addr,
|
&inst->local_tx, &inst->local_ntp_rx, &inst->local_ntp_tx,
|
||||||
&local_addr);
|
&inst->remote_addr, &local_addr);
|
||||||
|
|
||||||
++inst->tx_count;
|
++inst->tx_count;
|
||||||
inst->valid_rx = 0;
|
|
||||||
inst->updated_timestamps = 0;
|
|
||||||
if (sent)
|
if (sent)
|
||||||
inst->report.total_tx_count++;
|
inst->report.total_tx_count++;
|
||||||
|
|
||||||
@@ -1442,6 +1493,7 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
NTP_Local_Timestamp local_receive, local_transmit;
|
NTP_Local_Timestamp local_receive, local_transmit;
|
||||||
double remote_interval, local_interval, response_time;
|
double remote_interval, local_interval, response_time;
|
||||||
double delay_time, precision;
|
double delay_time, precision;
|
||||||
|
int updated_timestamps;
|
||||||
|
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
|
|
||||||
@@ -1459,7 +1511,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
The test values are 1 when passed and 0 when failed. */
|
The test values are 1 when passed and 0 when failed. */
|
||||||
|
|
||||||
/* Test 1 checks for duplicate packet */
|
/* Test 1 checks for duplicate packet */
|
||||||
test1 = !!UTI_CompareNtp64(&message->transmit_ts, &inst->remote_ntp_tx);
|
test1 = UTI_CompareNtp64(&message->receive_ts, &inst->remote_ntp_rx) ||
|
||||||
|
UTI_CompareNtp64(&message->transmit_ts, &inst->remote_ntp_tx);
|
||||||
|
|
||||||
/* Test 2 checks for bogus packet in the basic and interleaved modes. This
|
/* Test 2 checks for bogus packet in the basic and interleaved modes. This
|
||||||
ensures the source is responding to the latest packet we sent to it. */
|
ensures the source is responding to the latest packet we sent to it. */
|
||||||
@@ -1644,21 +1697,34 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
The authentication test (test5) is required to prevent DoS attacks using
|
The authentication test (test5) is required to prevent DoS attacks using
|
||||||
unauthenticated packets on authenticated symmetric associations. */
|
unauthenticated packets on authenticated symmetric associations. */
|
||||||
if ((inst->mode == MODE_CLIENT && valid_packet && !inst->valid_rx) ||
|
if ((inst->mode == MODE_CLIENT && valid_packet && !inst->valid_rx) ||
|
||||||
(inst->mode == MODE_ACTIVE && (valid_packet || !inst->valid_rx) &&
|
(inst->mode == MODE_ACTIVE && valid_packet &&
|
||||||
test5 && !UTI_IsZeroNtp64(&message->transmit_ts) &&
|
(!inst->valid_rx ||
|
||||||
(!inst->updated_timestamps || (valid_packet && !inst->valid_rx) ||
|
|
||||||
UTI_CompareNtp64(&inst->remote_ntp_tx, &message->transmit_ts) < 0))) {
|
UTI_CompareNtp64(&inst->remote_ntp_tx, &message->transmit_ts) < 0))) {
|
||||||
inst->remote_ntp_rx = message->receive_ts;
|
inst->remote_ntp_rx = message->receive_ts;
|
||||||
inst->remote_ntp_tx = message->transmit_ts;
|
inst->remote_ntp_tx = message->transmit_ts;
|
||||||
inst->local_rx = *rx_ts;
|
inst->local_rx = *rx_ts;
|
||||||
inst->valid_timestamps = synced_packet;
|
inst->valid_timestamps = synced_packet;
|
||||||
inst->updated_timestamps = 1;
|
|
||||||
|
UTI_ZeroNtp64(&inst->init_remote_ntp_tx);
|
||||||
|
zero_local_timestamp(&inst->init_local_rx);
|
||||||
|
inst->updated_init_timestamps = 0;
|
||||||
|
updated_timestamps = 2;
|
||||||
|
|
||||||
/* Don't use the same set of timestamps for the next sample */
|
/* Don't use the same set of timestamps for the next sample */
|
||||||
if (interleaved_packet)
|
if (interleaved_packet)
|
||||||
inst->prev_local_tx = inst->local_tx;
|
inst->prev_local_tx = inst->local_tx;
|
||||||
else
|
else
|
||||||
zero_local_timestamp(&inst->prev_local_tx);
|
zero_local_timestamp(&inst->prev_local_tx);
|
||||||
|
} else if (inst->mode == MODE_ACTIVE &&
|
||||||
|
test1 && !UTI_IsZeroNtp64(&message->transmit_ts) && test5 &&
|
||||||
|
(!inst->updated_init_timestamps ||
|
||||||
|
UTI_CompareNtp64(&inst->init_remote_ntp_tx, &message->transmit_ts) < 0)) {
|
||||||
|
inst->init_remote_ntp_tx = message->transmit_ts;
|
||||||
|
inst->init_local_rx = *rx_ts;
|
||||||
|
inst->updated_init_timestamps = 1;
|
||||||
|
updated_timestamps = 1;
|
||||||
|
} else {
|
||||||
|
updated_timestamps = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accept at most one response per request. The NTP specification recommends
|
/* Accept at most one response per request. The NTP specification recommends
|
||||||
@@ -1694,10 +1760,11 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
DEBUG_LOG("remote_interval=%.9f local_interval=%.9f response_time=%.9f txs=%c rxs=%c",
|
DEBUG_LOG("remote_interval=%.9f local_interval=%.9f response_time=%.9f txs=%c rxs=%c",
|
||||||
remote_interval, local_interval, response_time,
|
remote_interval, local_interval, response_time,
|
||||||
tss_chars[local_transmit.source], tss_chars[local_receive.source]);
|
tss_chars[local_transmit.source], tss_chars[local_receive.source]);
|
||||||
DEBUG_LOG("test123=%d%d%d test567=%d%d%d testABCD=%d%d%d%d kod_rate=%d interleaved=%d presend=%d valid=%d good=%d updated=%d",
|
DEBUG_LOG("test123=%d%d%d test567=%d%d%d testABCD=%d%d%d%d kod_rate=%d interleaved=%d"
|
||||||
|
" presend=%d valid=%d good=%d updated=%d",
|
||||||
test1, test2, test3, test5, test6, test7, testA, testB, testC, testD,
|
test1, test2, test3, test5, test6, test7, testA, testB, testC, testD,
|
||||||
kod_rate, interleaved_packet, inst->presend_done, valid_packet, good_packet,
|
kod_rate, interleaved_packet, inst->presend_done, valid_packet, good_packet,
|
||||||
!UTI_CompareTimespecs(&inst->local_rx.ts, &rx_ts->ts));
|
updated_timestamps);
|
||||||
|
|
||||||
if (valid_packet) {
|
if (valid_packet) {
|
||||||
inst->remote_poll = message->poll;
|
inst->remote_poll = message->poll;
|
||||||
@@ -1988,7 +2055,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
NTP_Mode pkt_mode, my_mode;
|
NTP_Mode pkt_mode, my_mode;
|
||||||
NTP_int64 *local_ntp_rx, *local_ntp_tx;
|
NTP_int64 *local_ntp_rx, *local_ntp_tx;
|
||||||
NTP_Local_Timestamp local_tx, *tx_ts;
|
NTP_Local_Timestamp local_tx, *tx_ts;
|
||||||
int valid_auth, log_index, interleaved, poll;
|
int pkt_version, valid_auth, log_index, interleaved, poll;
|
||||||
AuthenticationMode auth_mode;
|
AuthenticationMode auth_mode;
|
||||||
uint32_t key_id;
|
uint32_t key_id;
|
||||||
|
|
||||||
@@ -2009,6 +2076,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkt_mode = NTP_LVM_TO_MODE(message->lvm);
|
pkt_mode = NTP_LVM_TO_MODE(message->lvm);
|
||||||
|
pkt_version = NTP_LVM_TO_VERSION(message->lvm);
|
||||||
|
|
||||||
switch (pkt_mode) {
|
switch (pkt_mode) {
|
||||||
case MODE_ACTIVE:
|
case MODE_ACTIVE:
|
||||||
@@ -2019,6 +2087,15 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
/* Reply with server packet */
|
/* Reply with server packet */
|
||||||
my_mode = MODE_SERVER;
|
my_mode = MODE_SERVER;
|
||||||
break;
|
break;
|
||||||
|
case MODE_UNDEFINED:
|
||||||
|
/* Check if it is an NTPv1 client request (NTPv1 packets have a reserved
|
||||||
|
field instead of the mode field and the actual mode is determined from
|
||||||
|
the port numbers). Don't ever respond with a mode 0 packet! */
|
||||||
|
if (pkt_version == 1 && remote_addr->port != NTP_PORT) {
|
||||||
|
my_mode = MODE_SERVER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through */
|
||||||
default:
|
default:
|
||||||
/* Discard */
|
/* Discard */
|
||||||
DEBUG_LOG("NTP packet discarded pkt_mode=%d", pkt_mode);
|
DEBUG_LOG("NTP packet discarded pkt_mode=%d", pkt_mode);
|
||||||
@@ -2064,7 +2141,8 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
if (log_index >= 0) {
|
if (log_index >= 0) {
|
||||||
CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx);
|
CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx);
|
||||||
interleaved = !UTI_IsZeroNtp64(local_ntp_rx) &&
|
interleaved = !UTI_IsZeroNtp64(local_ntp_rx) &&
|
||||||
!UTI_CompareNtp64(&message->originate_ts, local_ntp_rx);
|
!UTI_CompareNtp64(&message->originate_ts, local_ntp_rx) &&
|
||||||
|
UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts);
|
||||||
|
|
||||||
if (interleaved) {
|
if (interleaved) {
|
||||||
UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts);
|
UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts);
|
||||||
@@ -2081,7 +2159,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
|||||||
poll = MAX(poll, message->poll);
|
poll = MAX(poll, message->poll);
|
||||||
|
|
||||||
/* Send a reply */
|
/* Send a reply */
|
||||||
transmit_packet(my_mode, interleaved, poll, NTP_LVM_TO_VERSION(message->lvm),
|
transmit_packet(my_mode, interleaved, poll, pkt_version,
|
||||||
auth_mode, key_id, &message->receive_ts, &message->transmit_ts,
|
auth_mode, key_id, &message->receive_ts, &message->transmit_ts,
|
||||||
rx_ts, tx_ts, local_ntp_rx, NULL, remote_addr, local_addr);
|
rx_ts, tx_ts, local_ntp_rx, NULL, remote_addr, local_addr);
|
||||||
|
|
||||||
@@ -2189,6 +2267,9 @@ NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double dof
|
|||||||
if (!UTI_IsZeroTimespec(&inst->prev_local_tx.ts))
|
if (!UTI_IsZeroTimespec(&inst->prev_local_tx.ts))
|
||||||
UTI_AdjustTimespec(&inst->prev_local_tx.ts, when, &inst->prev_local_tx.ts, &delta, dfreq,
|
UTI_AdjustTimespec(&inst->prev_local_tx.ts, when, &inst->prev_local_tx.ts, &delta, dfreq,
|
||||||
doffset);
|
doffset);
|
||||||
|
if (!UTI_IsZeroTimespec(&inst->init_local_rx.ts))
|
||||||
|
UTI_AdjustTimespec(&inst->init_local_rx.ts, when, &inst->init_local_rx.ts, &delta, dfreq,
|
||||||
|
doffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
8
ntp_io.c
8
ntp_io.c
@@ -318,6 +318,9 @@ close_socket(int sock_fd)
|
|||||||
if (sock_fd == INVALID_SOCK_FD)
|
if (sock_fd == INVALID_SOCK_FD)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_TIMESTAMPING
|
||||||
|
NIO_Linux_NotifySocketClosing(sock_fd);
|
||||||
|
#endif
|
||||||
SCH_RemoveFileHandler(sock_fd);
|
SCH_RemoveFileHandler(sock_fd);
|
||||||
close(sock_fd);
|
close(sock_fd);
|
||||||
}
|
}
|
||||||
@@ -685,6 +688,11 @@ read_from_socket(int sock_fd, int event, void *anything)
|
|||||||
unsigned int i, n;
|
unsigned int i, n;
|
||||||
int status, flags = 0;
|
int status, flags = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_TIMESTAMPING
|
||||||
|
if (NIO_Linux_ProcessEvent(sock_fd, event))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
hdr = ARR_GetElements(recv_headers);
|
hdr = ARR_GetElements(recv_headers);
|
||||||
n = ARR_GetSize(recv_headers);
|
n = ARR_GetSize(recv_headers);
|
||||||
assert(n >= 1);
|
assert(n >= 1);
|
||||||
|
|||||||
157
ntp_io_linux.c
157
ntp_io_linux.c
@@ -94,6 +94,27 @@ static int ts_tx_flags;
|
|||||||
/* Flag indicating the socket options can't be changed in control messages */
|
/* Flag indicating the socket options can't be changed in control messages */
|
||||||
static int permanent_ts_options;
|
static int permanent_ts_options;
|
||||||
|
|
||||||
|
/* When sending client requests to a close and fast server, it is possible that
|
||||||
|
a response will be received before the HW transmit timestamp of the request
|
||||||
|
itself. To avoid processing of the response without the HW timestamp, we
|
||||||
|
monitor events returned by select() and suspend reading of packets from the
|
||||||
|
receive queue for up to 200 microseconds. As the requests are normally
|
||||||
|
separated by at least 200 milliseconds, it is sufficient to monitor and
|
||||||
|
suspend one socket at a time. */
|
||||||
|
static int monitored_socket;
|
||||||
|
static int suspended_socket;
|
||||||
|
static SCH_TimeoutID resume_timeout_id;
|
||||||
|
|
||||||
|
#define RESUME_TIMEOUT 200.0e-6
|
||||||
|
|
||||||
|
/* Unbound socket keeping the kernel RX timestamping permanently enabled
|
||||||
|
in order to avoid a race condition between receiving a server response
|
||||||
|
and the kernel actually starting to timestamp received packets after
|
||||||
|
enabling the timestamping and sending a request */
|
||||||
|
static int dummy_rxts_socket;
|
||||||
|
|
||||||
|
#define INVALID_SOCK_FD -3
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -252,7 +273,7 @@ update_interface_speed(struct Interface *iface)
|
|||||||
{
|
{
|
||||||
struct ethtool_cmd cmd;
|
struct ethtool_cmd cmd;
|
||||||
struct ifreq req;
|
struct ifreq req;
|
||||||
int sock_fd;
|
int sock_fd, link_speed;
|
||||||
|
|
||||||
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (sock_fd < 0)
|
if (sock_fd < 0)
|
||||||
@@ -273,7 +294,12 @@ update_interface_speed(struct Interface *iface)
|
|||||||
|
|
||||||
close(sock_fd);
|
close(sock_fd);
|
||||||
|
|
||||||
iface->link_speed = ethtool_cmd_speed(&cmd);
|
link_speed = ethtool_cmd_speed(&cmd);
|
||||||
|
|
||||||
|
if (iface->link_speed != link_speed) {
|
||||||
|
iface->link_speed = link_speed;
|
||||||
|
DEBUG_LOG("Updated speed of %s to %d Mb/s", iface->name, link_speed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -301,6 +327,29 @@ check_timestamping_option(int option)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_dummy_socket(void)
|
||||||
|
{
|
||||||
|
int sock_fd, events = 0;
|
||||||
|
|
||||||
|
if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0
|
||||||
|
#ifdef FEAT_IPV6
|
||||||
|
&& (sock_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return INVALID_SOCK_FD;
|
||||||
|
|
||||||
|
if (!NIO_Linux_SetTimestampSocketOptions(sock_fd, 1, &events)) {
|
||||||
|
close(sock_fd);
|
||||||
|
return INVALID_SOCK_FD;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTI_FdSetCloexec(sock_fd);
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
NIO_Linux_Initialise(void)
|
NIO_Linux_Initialise(void)
|
||||||
{
|
{
|
||||||
@@ -350,6 +399,10 @@ NIO_Linux_Initialise(void)
|
|||||||
|
|
||||||
/* Kernels before 4.7 ignore timestamping flags set in control messages */
|
/* Kernels before 4.7 ignore timestamping flags set in control messages */
|
||||||
permanent_ts_options = !SYS_Linux_CheckKernelVersion(4, 7);
|
permanent_ts_options = !SYS_Linux_CheckKernelVersion(4, 7);
|
||||||
|
|
||||||
|
monitored_socket = INVALID_SOCK_FD;
|
||||||
|
suspended_socket = INVALID_SOCK_FD;
|
||||||
|
dummy_rxts_socket = INVALID_SOCK_FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -360,6 +413,9 @@ NIO_Linux_Finalise(void)
|
|||||||
struct Interface *iface;
|
struct Interface *iface;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
if (dummy_rxts_socket != INVALID_SOCK_FD)
|
||||||
|
close(dummy_rxts_socket);
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(interfaces); i++) {
|
for (i = 0; i < ARR_GetSize(interfaces); i++) {
|
||||||
iface = ARR_GetElement(interfaces, i);
|
iface = ARR_GetElement(interfaces, i);
|
||||||
HCL_DestroyInstance(iface->clock);
|
HCL_DestroyInstance(iface->clock);
|
||||||
@@ -406,6 +462,73 @@ NIO_Linux_SetTimestampSocketOptions(int sock_fd, int client_only, int *events)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
resume_socket(int sock_fd)
|
||||||
|
{
|
||||||
|
if (monitored_socket == sock_fd)
|
||||||
|
monitored_socket = INVALID_SOCK_FD;
|
||||||
|
|
||||||
|
if (sock_fd == INVALID_SOCK_FD || sock_fd != suspended_socket)
|
||||||
|
return;
|
||||||
|
|
||||||
|
suspended_socket = INVALID_SOCK_FD;
|
||||||
|
|
||||||
|
SCH_SetFileHandlerEvent(sock_fd, SCH_FILE_INPUT, 1);
|
||||||
|
|
||||||
|
DEBUG_LOG("Resumed RX processing %s timeout fd=%d",
|
||||||
|
resume_timeout_id ? "before" : "on", sock_fd);
|
||||||
|
|
||||||
|
if (resume_timeout_id) {
|
||||||
|
SCH_RemoveTimeout(resume_timeout_id);
|
||||||
|
resume_timeout_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
resume_timeout(void *arg)
|
||||||
|
{
|
||||||
|
resume_timeout_id = 0;
|
||||||
|
resume_socket(suspended_socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
suspend_socket(int sock_fd)
|
||||||
|
{
|
||||||
|
resume_socket(suspended_socket);
|
||||||
|
|
||||||
|
suspended_socket = sock_fd;
|
||||||
|
|
||||||
|
SCH_SetFileHandlerEvent(suspended_socket, SCH_FILE_INPUT, 0);
|
||||||
|
resume_timeout_id = SCH_AddTimeoutByDelay(RESUME_TIMEOUT, resume_timeout, NULL);
|
||||||
|
|
||||||
|
DEBUG_LOG("Suspended RX processing fd=%d", sock_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
NIO_Linux_ProcessEvent(int sock_fd, int event)
|
||||||
|
{
|
||||||
|
if (sock_fd != monitored_socket)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (event == SCH_FILE_INPUT) {
|
||||||
|
suspend_socket(monitored_socket);
|
||||||
|
monitored_socket = INVALID_SOCK_FD;
|
||||||
|
|
||||||
|
/* Don't process the message yet */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static struct Interface *
|
static struct Interface *
|
||||||
get_interface(int if_index)
|
get_interface(int if_index)
|
||||||
{
|
{
|
||||||
@@ -614,6 +737,11 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_LOG("HW clock not found for interface %d", ts_if_index);
|
DEBUG_LOG("HW clock not found for interface %d", ts_if_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If a HW transmit timestamp was received, resume processing
|
||||||
|
of non-error messages on this socket */
|
||||||
|
if (is_tx)
|
||||||
|
resume_socket(local_addr->sock_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_ts->source == NTP_TS_DAEMON && !UTI_IsZeroTimespec(&ts3.ts[0]) &&
|
if (local_ts->source == NTP_TS_DAEMON && !UTI_IsZeroTimespec(&ts3.ts[0]) &&
|
||||||
@@ -638,6 +766,14 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the kernel is slow with enabling RX timestamping, open a dummy
|
||||||
|
socket to keep the kernel RX timestamping permanently enabled */
|
||||||
|
if (!is_tx && local_ts->source == NTP_TS_DAEMON && ts_flags) {
|
||||||
|
DEBUG_LOG("Missing kernel RX timestamp");
|
||||||
|
if (dummy_rxts_socket == INVALID_SOCK_FD)
|
||||||
|
dummy_rxts_socket = open_dummy_socket();
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the message if it's not received from the error queue */
|
/* Return the message if it's not received from the error queue */
|
||||||
if (!is_tx)
|
if (!is_tx)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -682,6 +818,15 @@ NIO_Linux_RequestTxTimestamp(struct msghdr *msg, int cmsglen, int sock_fd)
|
|||||||
{
|
{
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
|
if (!ts_flags)
|
||||||
|
return cmsglen;
|
||||||
|
|
||||||
|
/* If a HW transmit timestamp is requested on a client socket, monitor
|
||||||
|
events on the socket in order to avoid processing of a fast response
|
||||||
|
without the HW timestamp of the request */
|
||||||
|
if (ts_tx_flags & SOF_TIMESTAMPING_TX_HARDWARE && !NIO_IsServerSocket(sock_fd))
|
||||||
|
monitored_socket = sock_fd;
|
||||||
|
|
||||||
/* Check if TX timestamping is disabled on this socket */
|
/* Check if TX timestamping is disabled on this socket */
|
||||||
if (permanent_ts_options || !NIO_IsServerSocket(sock_fd))
|
if (permanent_ts_options || !NIO_IsServerSocket(sock_fd))
|
||||||
return cmsglen;
|
return cmsglen;
|
||||||
@@ -701,3 +846,11 @@ NIO_Linux_RequestTxTimestamp(struct msghdr *msg, int cmsglen, int sock_fd)
|
|||||||
|
|
||||||
return cmsglen;
|
return cmsglen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
NIO_Linux_NotifySocketClosing(int sock_fd)
|
||||||
|
{
|
||||||
|
resume_socket(sock_fd);
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,13 +24,22 @@
|
|||||||
This is the header file for the Linux-specific NTP socket I/O bits.
|
This is the header file for the Linux-specific NTP socket I/O bits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef GOT_NTP_IO_LINUX_H
|
||||||
|
#define GOT_NTP_IO_LINUX_H
|
||||||
|
|
||||||
extern void NIO_Linux_Initialise(void);
|
extern void NIO_Linux_Initialise(void);
|
||||||
|
|
||||||
extern void NIO_Linux_Finalise(void);
|
extern void NIO_Linux_Finalise(void);
|
||||||
|
|
||||||
extern int NIO_Linux_SetTimestampSocketOptions(int sock_fd, int client_only, int *events);
|
extern int NIO_Linux_SetTimestampSocketOptions(int sock_fd, int client_only, int *events);
|
||||||
|
|
||||||
|
extern int NIO_Linux_ProcessEvent(int sock_fd, int event);
|
||||||
|
|
||||||
extern int NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
|
extern int NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
|
||||||
NTP_Local_Timestamp *local_ts, struct msghdr *hdr, int length);
|
NTP_Local_Timestamp *local_ts, struct msghdr *hdr, int length);
|
||||||
|
|
||||||
extern int NIO_Linux_RequestTxTimestamp(struct msghdr *msg, int cmsglen, int sock_fd);
|
extern int NIO_Linux_RequestTxTimestamp(struct msghdr *msg, int cmsglen, int sock_fd);
|
||||||
|
|
||||||
|
extern void NIO_Linux_NotifySocketClosing(int sock_fd);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ read_write_socket(int sock_fd, int event, void *anything)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Disable output and wait for a response */
|
/* Disable output and wait for a response */
|
||||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT);
|
SCH_SetFileHandlerEvent(sock_fd, SCH_FILE_OUTPUT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == SCH_FILE_INPUT) {
|
if (event == SCH_FILE_INPUT) {
|
||||||
@@ -283,7 +283,7 @@ read_write_socket(int sock_fd, int event, void *anything)
|
|||||||
/* Move the head and enable output for the next packet */
|
/* Move the head and enable output for the next packet */
|
||||||
queue_head = NEXT_QUEUE_INDEX(queue_head);
|
queue_head = NEXT_QUEUE_INDEX(queue_head);
|
||||||
if (!IS_QUEUE_EMPTY())
|
if (!IS_QUEUE_EMPTY())
|
||||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT | SCH_FILE_OUTPUT);
|
SCH_SetFileHandlerEvent(sock_fd, SCH_FILE_OUTPUT, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,7 +369,7 @@ NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_Remote_Address *r
|
|||||||
|
|
||||||
/* Enable output if there was no pending request */
|
/* Enable output if there was no pending request */
|
||||||
if (IS_QUEUE_EMPTY())
|
if (IS_QUEUE_EMPTY())
|
||||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT | SCH_FILE_OUTPUT);
|
SCH_SetFileHandlerEvent(sock_fd, SCH_FILE_OUTPUT, 1);
|
||||||
|
|
||||||
queue_tail = NEXT_QUEUE_INDEX(queue_tail);
|
queue_tail = NEXT_QUEUE_INDEX(queue_tail);
|
||||||
|
|
||||||
|
|||||||
19
pktlength.c
19
pktlength.c
@@ -118,6 +118,7 @@ static const struct request_length request_lengths[] = {
|
|||||||
{ 0, 0 }, /* ADD_PEER2 */
|
{ 0, 0 }, /* ADD_PEER2 */
|
||||||
REQ_LENGTH_ENTRY(ntp_source, null), /* ADD_SERVER3 */
|
REQ_LENGTH_ENTRY(ntp_source, null), /* ADD_SERVER3 */
|
||||||
REQ_LENGTH_ENTRY(ntp_source, null), /* ADD_PEER3 */
|
REQ_LENGTH_ENTRY(ntp_source, null), /* ADD_PEER3 */
|
||||||
|
REQ_LENGTH_ENTRY(null, null), /* SHUTDOWN */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t reply_lengths[] = {
|
static const uint16_t reply_lengths[] = {
|
||||||
@@ -132,13 +133,14 @@ static const uint16_t reply_lengths[] = {
|
|||||||
0, /* SUBNETS_ACCESSED - not supported */
|
0, /* SUBNETS_ACCESSED - not supported */
|
||||||
0, /* CLIENT_ACCESSES - not supported */
|
0, /* CLIENT_ACCESSES - not supported */
|
||||||
0, /* CLIENT_ACCESSES_BY_INDEX - not supported */
|
0, /* CLIENT_ACCESSES_BY_INDEX - not supported */
|
||||||
0, /* MANUAL_LIST - variable length */
|
0, /* MANUAL_LIST - not supported */
|
||||||
RPY_LENGTH_ENTRY(activity), /* ACTIVITY */
|
RPY_LENGTH_ENTRY(activity), /* ACTIVITY */
|
||||||
RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */
|
RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */
|
||||||
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS */
|
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS */
|
||||||
RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */
|
RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */
|
||||||
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */
|
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */
|
||||||
RPY_LENGTH_ENTRY(manual_timestamp), /* MANUAL_TIMESTAMP2 */
|
RPY_LENGTH_ENTRY(manual_timestamp), /* MANUAL_TIMESTAMP2 */
|
||||||
|
RPY_LENGTH_ENTRY(manual_list), /* MANUAL_LIST2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -195,21 +197,6 @@ PKL_ReplyLength(CMD_Reply *r)
|
|||||||
if (type < 1 || type >= N_REPLY_TYPES)
|
if (type < 1 || type >= N_REPLY_TYPES)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Length of MANUAL_LIST depends on number of samples stored in it */
|
|
||||||
if (type == RPY_MANUAL_LIST) {
|
|
||||||
uint32_t ns;
|
|
||||||
|
|
||||||
if (r->status != htons(STT_SUCCESS))
|
|
||||||
return offsetof(CMD_Reply, data);
|
|
||||||
|
|
||||||
ns = ntohl(r->data.manual_list.n_samples);
|
|
||||||
if (ns > MAX_MANUAL_LIST_SAMPLES)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return offsetof(CMD_Reply, data.manual_list.samples) +
|
|
||||||
ns * sizeof (RPY_ManualListSample);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reply_lengths[type];
|
return reply_lengths[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
refclock.c
48
refclock.c
@@ -79,6 +79,8 @@ struct RCL_Instance_Record {
|
|||||||
int pps_rate;
|
int pps_rate;
|
||||||
int pps_active;
|
int pps_active;
|
||||||
int max_lock_age;
|
int max_lock_age;
|
||||||
|
int stratum;
|
||||||
|
int tai;
|
||||||
struct MedianFilter filter;
|
struct MedianFilter filter;
|
||||||
uint32_t ref_id;
|
uint32_t ref_id;
|
||||||
uint32_t lock_ref;
|
uint32_t lock_ref;
|
||||||
@@ -181,13 +183,13 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
inst->driver = &RCL_PHC_driver;
|
inst->driver = &RCL_PHC_driver;
|
||||||
} else {
|
} else {
|
||||||
LOG_FATAL("unknown refclock driver %s", params->driver_name);
|
LOG_FATAL("unknown refclock driver %s", params->driver_name);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inst->driver->init && !inst->driver->poll) {
|
if (!inst->driver->init && !inst->driver->poll)
|
||||||
LOG_FATAL("refclock driver %s is not compiled in", params->driver_name);
|
LOG_FATAL("refclock driver %s is not compiled in", params->driver_name);
|
||||||
return 0;
|
|
||||||
}
|
if (params->tai && !CNF_GetLeapSecTimezone())
|
||||||
|
LOG_FATAL("refclock tai option requires leapsectz");
|
||||||
|
|
||||||
inst->data = NULL;
|
inst->data = NULL;
|
||||||
inst->driver_parameter = params->driver_parameter;
|
inst->driver_parameter = params->driver_parameter;
|
||||||
@@ -200,6 +202,8 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
inst->pps_rate = params->pps_rate;
|
inst->pps_rate = params->pps_rate;
|
||||||
inst->pps_active = 0;
|
inst->pps_active = 0;
|
||||||
inst->max_lock_age = params->max_lock_age;
|
inst->max_lock_age = params->max_lock_age;
|
||||||
|
inst->stratum = params->stratum;
|
||||||
|
inst->tai = params->tai;
|
||||||
inst->lock_ref = params->lock_ref_id;
|
inst->lock_ref = params->lock_ref_id;
|
||||||
inst->offset = params->offset;
|
inst->offset = params->offset;
|
||||||
inst->delay = params->delay;
|
inst->delay = params->delay;
|
||||||
@@ -251,11 +255,8 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->driver->init)
|
if (inst->driver->init && !inst->driver->init(inst))
|
||||||
if (!inst->driver->init(inst)) {
|
LOG_FATAL("refclock %s initialisation failed", params->driver_name);
|
||||||
LOG_FATAL("refclock %s initialisation failed", params->driver_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
|
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
|
||||||
|
|
||||||
@@ -356,6 +357,28 @@ RCL_GetDriverOption(RCL_Instance instance, char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
convert_tai_offset(struct timespec *sample_time, double *offset)
|
||||||
|
{
|
||||||
|
struct timespec tai_ts, utc_ts;
|
||||||
|
int tai_offset;
|
||||||
|
|
||||||
|
/* Get approximate TAI-UTC offset for the reference time in TAI */
|
||||||
|
UTI_AddDoubleToTimespec(sample_time, *offset, &tai_ts);
|
||||||
|
tai_offset = REF_GetTaiOffset(&tai_ts);
|
||||||
|
|
||||||
|
/* Get TAI-UTC offset for the reference time in UTC +/- 1 second */
|
||||||
|
UTI_AddDoubleToTimespec(&tai_ts, -tai_offset, &utc_ts);
|
||||||
|
tai_offset = REF_GetTaiOffset(&utc_ts);
|
||||||
|
|
||||||
|
if (!tai_offset)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*offset -= tai_offset;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap)
|
RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap)
|
||||||
{
|
{
|
||||||
@@ -385,6 +408,11 @@ RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance->tai && !convert_tai_offset(sample_time, &offset)) {
|
||||||
|
DEBUG_LOG("refclock sample ignored unknown TAI offset");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
|
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
|
||||||
instance->pps_active = 0;
|
instance->pps_active = 0;
|
||||||
|
|
||||||
@@ -635,7 +663,7 @@ poll_timeout(void *arg)
|
|||||||
/* Handle special case when PPS is used with local stratum */
|
/* Handle special case when PPS is used with local stratum */
|
||||||
stratum = pps_stratum(inst, &sample_time);
|
stratum = pps_stratum(inst, &sample_time);
|
||||||
else
|
else
|
||||||
stratum = 0;
|
stratum = inst->stratum;
|
||||||
|
|
||||||
SRC_UpdateReachability(inst->source, 1);
|
SRC_UpdateReachability(inst->source, 1);
|
||||||
SRC_AccumulateSample(inst->source, &sample_time, offset,
|
SRC_AccumulateSample(inst->source, &sample_time, offset,
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ typedef struct {
|
|||||||
int max_samples;
|
int max_samples;
|
||||||
int sel_options;
|
int sel_options;
|
||||||
int max_lock_age;
|
int max_lock_age;
|
||||||
|
int stratum;
|
||||||
|
int tai;
|
||||||
uint32_t ref_id;
|
uint32_t ref_id;
|
||||||
uint32_t lock_ref_id;
|
uint32_t lock_ref_id;
|
||||||
double offset;
|
double offset;
|
||||||
|
|||||||
12
reference.c
12
reference.c
@@ -1356,6 +1356,18 @@ int REF_IsLeapSecondClose(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
REF_GetTaiOffset(struct timespec *ts)
|
||||||
|
{
|
||||||
|
int tai_offset;
|
||||||
|
|
||||||
|
get_tz_leap(ts->tv_sec, &tai_offset);
|
||||||
|
|
||||||
|
return tai_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
REF_GetTrackingReport(RPT_TrackingReport *rep)
|
REF_GetTrackingReport(RPT_TrackingReport *rep)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -184,6 +184,9 @@ extern void REF_DisableLocal(void);
|
|||||||
and is better to discard any measurements */
|
and is better to discard any measurements */
|
||||||
extern int REF_IsLeapSecondClose(void);
|
extern int REF_IsLeapSecondClose(void);
|
||||||
|
|
||||||
|
/* Return TAI-UTC offset corresponding to a time in UTC if available */
|
||||||
|
extern int REF_GetTaiOffset(struct timespec *ts);
|
||||||
|
|
||||||
extern void REF_GetTrackingReport(RPT_TrackingReport *rep);
|
extern void REF_GetTrackingReport(RPT_TrackingReport *rep);
|
||||||
|
|
||||||
#endif /* GOT_REFERENCE_H */
|
#endif /* GOT_REFERENCE_H */
|
||||||
|
|||||||
9
sched.c
9
sched.c
@@ -219,13 +219,16 @@ SCH_RemoveFileHandler(int fd)
|
|||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SCH_SetFileHandlerEvents(int fd, int events)
|
SCH_SetFileHandlerEvent(int fd, int event, int enable)
|
||||||
{
|
{
|
||||||
FileHandlerEntry *ptr;
|
FileHandlerEntry *ptr;
|
||||||
|
|
||||||
assert(events);
|
|
||||||
ptr = ARR_GetElement(file_handlers, fd);
|
ptr = ARR_GetElement(file_handlers, fd);
|
||||||
ptr->events = events;
|
|
||||||
|
if (enable)
|
||||||
|
ptr->events |= event;
|
||||||
|
else
|
||||||
|
ptr->events &= ~event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
2
sched.h
2
sched.h
@@ -60,7 +60,7 @@ extern void SCH_Finalise(void);
|
|||||||
/* Register a handler for when select goes true on a file descriptor */
|
/* Register a handler for when select goes true on a file descriptor */
|
||||||
extern void SCH_AddFileHandler(int fd, int events, SCH_FileHandler handler, SCH_ArbitraryArgument arg);
|
extern void SCH_AddFileHandler(int fd, int events, SCH_FileHandler handler, SCH_ArbitraryArgument arg);
|
||||||
extern void SCH_RemoveFileHandler(int fd);
|
extern void SCH_RemoveFileHandler(int fd);
|
||||||
extern void SCH_SetFileHandlerEvents(int fd, int events);
|
extern void SCH_SetFileHandlerEvent(int fd, int event, int enable);
|
||||||
|
|
||||||
/* Get the time stamp taken after a file descriptor became ready or a timeout expired */
|
/* Get the time stamp taken after a file descriptor became ready or a timeout expired */
|
||||||
extern void SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw);
|
extern void SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw);
|
||||||
|
|||||||
10
sources.c
10
sources.c
@@ -665,6 +665,16 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Include extra dispersion in the root distance of sources that don't
|
||||||
|
have new samples (the last sample is older than span of all samples) */
|
||||||
|
if (first_sample_ago < 2.0 * si->last_sample_ago) {
|
||||||
|
double extra_disp = LCL_GetMaxClockError() *
|
||||||
|
(2.0 * si->last_sample_ago - first_sample_ago);
|
||||||
|
si->root_distance += extra_disp;
|
||||||
|
si->lo_limit -= extra_disp;
|
||||||
|
si->hi_limit += extra_disp;
|
||||||
|
}
|
||||||
|
|
||||||
/* Require the root distance to be below the allowed maximum */
|
/* Require the root distance to be below the allowed maximum */
|
||||||
if (si->root_distance > max_distance) {
|
if (si->root_distance > max_distance) {
|
||||||
sources[i]->status = SRC_BAD_DISTANCE;
|
sources[i]->status = SRC_BAD_DISTANCE;
|
||||||
|
|||||||
@@ -51,6 +51,9 @@
|
|||||||
#define MIN_SKEW 1.0e-12
|
#define MIN_SKEW 1.0e-12
|
||||||
#define MAX_SKEW 1.0e+02
|
#define MAX_SKEW 1.0e+02
|
||||||
|
|
||||||
|
/* The minimum standard deviation */
|
||||||
|
#define MIN_STDDEV 1.0e-9
|
||||||
|
|
||||||
/* The asymmetry of network jitter when all jitter is in one direction */
|
/* The asymmetry of network jitter when all jitter is in one direction */
|
||||||
#define MAX_ASYMMETRY 0.5
|
#define MAX_ASYMMETRY 0.5
|
||||||
|
|
||||||
@@ -571,7 +574,7 @@ SST_DoNewRegression(SST_Stats inst)
|
|||||||
inst->estimated_offset = est_intercept;
|
inst->estimated_offset = est_intercept;
|
||||||
inst->offset_time = inst->sample_times[inst->last_sample];
|
inst->offset_time = inst->sample_times[inst->last_sample];
|
||||||
inst->estimated_offset_sd = est_intercept_sd;
|
inst->estimated_offset_sd = est_intercept_sd;
|
||||||
inst->std_dev = sqrt(est_var);
|
inst->std_dev = MAX(MIN_STDDEV, sqrt(est_var));
|
||||||
inst->nruns = nruns;
|
inst->nruns = nruns;
|
||||||
|
|
||||||
inst->skew = CLAMP(MIN_SKEW, inst->skew, MAX_SKEW);
|
inst->skew = CLAMP(MIN_SKEW, inst->skew, MAX_SKEW);
|
||||||
@@ -884,7 +887,7 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
|
|||||||
char line[1024];
|
char line[1024];
|
||||||
double weight;
|
double weight;
|
||||||
|
|
||||||
assert(!inst->n_samples);
|
SST_ResetInstance(inst);
|
||||||
|
|
||||||
if (fgets(line, sizeof(line), in) &&
|
if (fgets(line, sizeof(line), in) &&
|
||||||
sscanf(line, "%d", &inst->n_samples) == 1 &&
|
sscanf(line, "%d", &inst->n_samples) == 1 &&
|
||||||
@@ -933,7 +936,6 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
inst->last_sample = inst->n_samples - 1;
|
inst->last_sample = inst->n_samples - 1;
|
||||||
inst->runs_samples = 0;
|
|
||||||
|
|
||||||
find_min_delay_sample(inst);
|
find_min_delay_sample(inst);
|
||||||
SST_DoNewRegression(inst);
|
SST_DoNewRegression(inst);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ typedef struct {
|
|||||||
int online;
|
int online;
|
||||||
int auto_offline;
|
int auto_offline;
|
||||||
int presend_minpoll;
|
int presend_minpoll;
|
||||||
|
int burst;
|
||||||
int iburst;
|
int iburst;
|
||||||
int min_stratum;
|
int min_stratum;
|
||||||
int poll_target;
|
int poll_target;
|
||||||
|
|||||||
2
sys.c
2
sys.c
@@ -97,7 +97,7 @@ SYS_Finalise(void)
|
|||||||
void SYS_DropRoot(uid_t uid, gid_t gid)
|
void SYS_DropRoot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
#if defined(LINUX) && defined (FEAT_PRIVDROP)
|
||||||
SYS_Linux_DropRoot(uid, gid);
|
SYS_Linux_DropRoot(uid, gid, !null_driver);
|
||||||
#elif defined(SOLARIS) && defined(FEAT_PRIVDROP)
|
#elif defined(SOLARIS) && defined(FEAT_PRIVDROP)
|
||||||
SYS_Solaris_DropRoot(uid, gid);
|
SYS_Solaris_DropRoot(uid, gid);
|
||||||
#elif (defined(NETBSD) || defined(FREEBSD)) && defined(FEAT_PRIVDROP)
|
#elif (defined(NETBSD) || defined(FREEBSD)) && defined(FEAT_PRIVDROP)
|
||||||
|
|||||||
27
sys_linux.c
27
sys_linux.c
@@ -380,6 +380,18 @@ test_step_offset(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
report_time_adjust_blockers(void)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_PRIVDROP
|
||||||
|
if (CAP_IS_SUPPORTED(CAP_SYS_TIME) && cap_get_bound(CAP_SYS_TIME))
|
||||||
|
return;
|
||||||
|
LOG(LOGS_WARN, "CAP_SYS_TIME not present");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Initialisation code for this module */
|
/* Initialisation code for this module */
|
||||||
|
|
||||||
@@ -388,6 +400,8 @@ SYS_Linux_Initialise(void)
|
|||||||
{
|
{
|
||||||
get_version_specific_details();
|
get_version_specific_details();
|
||||||
|
|
||||||
|
report_time_adjust_blockers();
|
||||||
|
|
||||||
reset_adjtime_offset();
|
reset_adjtime_offset();
|
||||||
|
|
||||||
if (have_setoffset && !test_step_offset()) {
|
if (have_setoffset && !test_step_offset()) {
|
||||||
@@ -415,9 +429,9 @@ SYS_Linux_Finalise(void)
|
|||||||
|
|
||||||
#ifdef FEAT_PRIVDROP
|
#ifdef FEAT_PRIVDROP
|
||||||
void
|
void
|
||||||
SYS_Linux_DropRoot(uid_t uid, gid_t gid)
|
SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
|
||||||
{
|
{
|
||||||
const char *cap_text;
|
char cap_text[256];
|
||||||
cap_t cap;
|
cap_t cap;
|
||||||
|
|
||||||
if (prctl(PR_SET_KEEPCAPS, 1)) {
|
if (prctl(PR_SET_KEEPCAPS, 1)) {
|
||||||
@@ -426,9 +440,12 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid)
|
|||||||
|
|
||||||
UTI_DropRoot(uid, gid);
|
UTI_DropRoot(uid, gid);
|
||||||
|
|
||||||
/* Keep CAP_NET_BIND_SERVICE only if NTP port can be opened */
|
/* Keep CAP_NET_BIND_SERVICE only if a server NTP port can be opened
|
||||||
cap_text = CNF_GetNTPPort() ?
|
and keep CAP_SYS_TIME only if the clock control is enabled */
|
||||||
"cap_net_bind_service,cap_sys_time=ep" : "cap_sys_time=ep";
|
if (snprintf(cap_text, sizeof (cap_text), "%s %s",
|
||||||
|
CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "",
|
||||||
|
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
|
||||||
|
assert(0);
|
||||||
|
|
||||||
if ((cap = cap_from_text(cap_text)) == NULL) {
|
if ((cap = cap_from_text(cap_text)) == NULL) {
|
||||||
LOG_FATAL("cap_from_text() failed");
|
LOG_FATAL("cap_from_text() failed");
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ extern void SYS_Linux_Initialise(void);
|
|||||||
|
|
||||||
extern void SYS_Linux_Finalise(void);
|
extern void SYS_Linux_Finalise(void);
|
||||||
|
|
||||||
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid);
|
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);
|
||||||
|
|
||||||
extern void SYS_Linux_EnableSystemCallFilter(int level);
|
extern void SYS_Linux_EnableSystemCallFilter(int level);
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ for opts in \
|
|||||||
"--host-system=Linux" \
|
"--host-system=Linux" \
|
||||||
"--host-system=NetBSD" \
|
"--host-system=NetBSD" \
|
||||||
"--host-system=FreeBSD" \
|
"--host-system=FreeBSD" \
|
||||||
"--without-nss" \
|
"--without-nettle" \
|
||||||
"--without-tomcrypt --without-nss"
|
"--without-nettle --without-nss" \
|
||||||
|
"--without-nettle --without-nss --without-tomcrypt"
|
||||||
do
|
do
|
||||||
./configure $opts
|
./configure $opts
|
||||||
scan-build make "$@" || exit 1
|
scan-build make "$@" || exit 1
|
||||||
|
|||||||
@@ -8,11 +8,20 @@ limit=1000
|
|||||||
refclock_jitter=$jitter
|
refclock_jitter=$jitter
|
||||||
min_sync_time=45
|
min_sync_time=45
|
||||||
max_sync_time=70
|
max_sync_time=70
|
||||||
client_conf="refclock SHM 0"
|
chronyc_start=70
|
||||||
|
client_conf="refclock SHM 0 stratum 3 delay 1e-3 refid GPS"
|
||||||
|
chronyc_conf="tracking"
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
check_source_selection || test_fail
|
check_source_selection || test_fail
|
||||||
check_sync || test_fail
|
check_sync || test_fail
|
||||||
|
check_chronyc_output "^Reference ID.*47505300 \(GPS\)
|
||||||
|
Stratum.*: 4
|
||||||
|
.*
|
||||||
|
Root delay : 0.001000000 seconds
|
||||||
|
.*
|
||||||
|
Update interval : 16\.. seconds
|
||||||
|
.*$" || test_fail
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -4,14 +4,30 @@
|
|||||||
|
|
||||||
test_start "chronyc"
|
test_start "chronyc"
|
||||||
|
|
||||||
chronyc_conf="tracking
|
refclock_jitter=$jitter
|
||||||
|
client_conf="
|
||||||
|
refclock SHM 0 noselect
|
||||||
|
smoothtime 400 0.001 leaponly"
|
||||||
|
|
||||||
|
chronyc_conf="activity
|
||||||
|
tracking
|
||||||
sources
|
sources
|
||||||
sourcestats"
|
sourcestats
|
||||||
|
manual list
|
||||||
|
smoothing
|
||||||
|
waitsync
|
||||||
|
rtcdata"
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
|
|
||||||
check_chronyc_output "^Reference ID : C0A87B01 \(192\.168\.123\.1\)
|
check_chronyc_output "^200 OK
|
||||||
|
1 sources online
|
||||||
|
0 sources offline
|
||||||
|
0 sources doing burst \(return to online\)
|
||||||
|
0 sources doing burst \(return to offline\)
|
||||||
|
0 sources with unknown address
|
||||||
|
Reference ID : C0A87B01 \(192\.168\.123\.1\)
|
||||||
Stratum : 2
|
Stratum : 2
|
||||||
Ref time \(UTC\) : Fri Jan 01 00:1.:.. 2010
|
Ref time \(UTC\) : Fri Jan 01 00:1.:.. 2010
|
||||||
System time : 0\.0000..... seconds (slow|fast) of NTP time
|
System time : 0\.0000..... seconds (slow|fast) of NTP time
|
||||||
@@ -24,14 +40,27 @@ Root delay : 0\.000...... seconds
|
|||||||
Root dispersion : 0\.000...... seconds
|
Root dispersion : 0\.000...... seconds
|
||||||
Update interval : [0-9]+\.. seconds
|
Update interval : [0-9]+\.. seconds
|
||||||
Leap status : Normal
|
Leap status : Normal
|
||||||
210 Number of sources = 1
|
210 Number of sources = 2
|
||||||
MS Name/IP address Stratum Poll Reach LastRx Last sample
|
MS Name/IP address Stratum Poll Reach LastRx Last sample
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
#\? SHM0 0 4 377 [0-9]+ [0-9 +-]+[un]s\[[0-9 +-]+[un]s\] \+/-[ 0-9]+[un]s
|
||||||
\^\* 192\.168\.123\.1 1 [67] 377 [0-9]+ [0-9 +-]+[un]s\[[0-9 +-]+[un]s\] \+/-[ 0-9]+[un]s
|
\^\* 192\.168\.123\.1 1 [67] 377 [0-9]+ [0-9 +-]+[un]s\[[0-9 +-]+[un]s\] \+/-[ 0-9]+[un]s
|
||||||
210 Number of sources = 1
|
210 Number of sources = 2
|
||||||
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
|
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
|
||||||
==============================================================================
|
==============================================================================
|
||||||
192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s$" \
|
SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||||
|
192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s
|
||||||
|
210 n_samples = 0
|
||||||
|
# Date Time\(UTC\) Slewed Original Residual
|
||||||
|
=======================================================
|
||||||
|
Active : Yes \(leap second only\)
|
||||||
|
Offset : \+0\.000000000 seconds
|
||||||
|
Frequency : \+0\.000000 ppm
|
||||||
|
Wander : \+0\.000000 ppm per second
|
||||||
|
Last update : [0-9]+\.. seconds ago
|
||||||
|
Remaining time : 0\.0 seconds
|
||||||
|
try: 1, refid: C0A87B01, correction: 0\.000......, skew: .\....
|
||||||
|
513 RTC driver not running$" \
|
||||||
|| test_fail
|
|| test_fail
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ test_start "smoothtime option"
|
|||||||
|
|
||||||
server_strata=2
|
server_strata=2
|
||||||
server_conf="smoothtime 400 0.001"
|
server_conf="smoothtime 400 0.001"
|
||||||
min_sync_time=250
|
server_server_options="minpoll 8"
|
||||||
max_sync_time=1000
|
min_sync_time=600
|
||||||
|
max_sync_time=800
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
@@ -22,6 +23,7 @@ server_conf="refclock SHM 0 dpoll 4 poll 6
|
|||||||
smoothtime 2000 1
|
smoothtime 2000 1
|
||||||
maxjitter 10.0"
|
maxjitter 10.0"
|
||||||
time_offset=-10
|
time_offset=-10
|
||||||
|
server_server_options=""
|
||||||
client_server_options="minpoll 6 maxpoll 6"
|
client_server_options="minpoll 6 maxpoll 6"
|
||||||
client_conf="corrtimeratio 100"
|
client_conf="corrtimeratio 100"
|
||||||
min_sync_time=8000
|
min_sync_time=8000
|
||||||
|
|||||||
42
test/simulation/124-tai
Executable file
42
test/simulation/124-tai
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. ./test.common
|
||||||
|
test_start "tai option"
|
||||||
|
|
||||||
|
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 31 2008 23:50:00' +'%s')
|
||||||
|
|
||||||
|
leap=$[10 * 60]
|
||||||
|
limit=$[20 * 60]
|
||||||
|
min_sync_time=2
|
||||||
|
max_sync_time=15
|
||||||
|
refclock_jitter=1e-6
|
||||||
|
servers=0
|
||||||
|
|
||||||
|
refclock_offset="(+ -34 (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||||
|
client_conf="
|
||||||
|
refclock SHM 0 dpoll 0 poll 0 tai
|
||||||
|
leapsectz right/UTC
|
||||||
|
leapsecmode ignore
|
||||||
|
maxchange 1e-3 1 0"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Jan 01 2009 00:10:00' +'%s')
|
||||||
|
|
||||||
|
time_offset=-1000
|
||||||
|
refclock_offset="(+ -34)"
|
||||||
|
client_conf="
|
||||||
|
refclock SHM 0 dpoll 0 poll 0 tai
|
||||||
|
leapsectz right/UTC
|
||||||
|
makestep 1 1
|
||||||
|
maxchange 1e-3 1 0"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
test_pass
|
||||||
29
test/simulation/125-packetloss
Executable file
29
test/simulation/125-packetloss
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. ./test.common
|
||||||
|
|
||||||
|
test_start "packet loss"
|
||||||
|
|
||||||
|
# Drop 33% of packets by default and 100% on the 3->1 path
|
||||||
|
base_delay=$(cat <<-EOF | tr -d '\n'
|
||||||
|
(+ 1e-4
|
||||||
|
(* -1 (equal 0.33 (uniform) 1.0))
|
||||||
|
(* -1 (equal 0.1 from 3) (equal 0.1 to 1)))
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
clients=2
|
||||||
|
peers=2
|
||||||
|
jitter=1e-5
|
||||||
|
limit=20000
|
||||||
|
max_sync_time=10000
|
||||||
|
|
||||||
|
for options in "maxpoll 8" "maxpoll 8 xleave"; do
|
||||||
|
client_server_options=$options
|
||||||
|
client_peer_options=$options
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
done
|
||||||
|
|
||||||
|
test_pass
|
||||||
29
test/simulation/126-burst
Executable file
29
test/simulation/126-burst
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. ./test.common
|
||||||
|
|
||||||
|
test_start "burst option"
|
||||||
|
|
||||||
|
# Pass every fourth packet on the 2->1 path
|
||||||
|
base_delay=$(cat <<-EOF | tr -d '\n'
|
||||||
|
(+ 1e-4
|
||||||
|
(* -1
|
||||||
|
(equal 0.1 from 2)
|
||||||
|
(equal 0.1 to 1)
|
||||||
|
(equal 0.1 (min (% (sum 1) 4) 1) 1)))
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
client_server_options="burst polltarget 1"
|
||||||
|
min_sync_time=700
|
||||||
|
max_sync_time=730
|
||||||
|
client_max_min_out_interval=2.2
|
||||||
|
client_min_mean_out_interval=150.0
|
||||||
|
|
||||||
|
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
|
||||||
@@ -71,6 +71,9 @@ default_freq_rms_limit=1e-5
|
|||||||
default_min_sync_time=120
|
default_min_sync_time=120
|
||||||
default_max_sync_time=210
|
default_max_sync_time=210
|
||||||
|
|
||||||
|
default_client_min_mean_out_interval=0.0
|
||||||
|
default_client_max_min_out_interval=inf
|
||||||
|
|
||||||
# Initialize test settings from their defaults
|
# Initialize test settings from their defaults
|
||||||
for defopt in $(declare | grep '^default_'); do
|
for defopt in $(declare | grep '^default_'); do
|
||||||
defoptname=${defopt%%=*}
|
defoptname=${defopt%%=*}
|
||||||
@@ -251,6 +254,7 @@ check_chronyd_exit() {
|
|||||||
test_message 3 0 "node $i:"
|
test_message 3 0 "node $i:"
|
||||||
|
|
||||||
tail -n 1 tmp/log.$i | grep -q 'chronyd exiting' && \
|
tail -n 1 tmp/log.$i | grep -q 'chronyd exiting' && \
|
||||||
|
! grep -q 'Adjustment.*exceeds.*exiting' tmp/log.$i && \
|
||||||
test_ok || test_bad
|
test_ok || test_bad
|
||||||
[ $? -eq 0 ] || ret=1
|
[ $? -eq 0 ] || ret=1
|
||||||
done
|
done
|
||||||
@@ -302,10 +306,12 @@ check_packet_interval() {
|
|||||||
([ $i -gt $servers ] || \
|
([ $i -gt $servers ] || \
|
||||||
check_stat $mean_in_interval 0.0 $mean_out_interval 10*$jitter) && \
|
check_stat $mean_in_interval 0.0 $mean_out_interval 10*$jitter) && \
|
||||||
([ $i -le $[$servers * $server_strata] ] || \
|
([ $i -le $[$servers * $server_strata] ] || \
|
||||||
check_stat $mean_out_interval 0.0 $mean_in_interval 10*$jitter) && \
|
check_stat $mean_out_interval $client_min_mean_out_interval \
|
||||||
|
$mean_in_interval 10*$jitter) && \
|
||||||
([ $i -le $[$servers * $server_strata] ] || \
|
([ $i -le $[$servers * $server_strata] ] || \
|
||||||
check_stat $min_out_interval \
|
check_stat $min_out_interval \
|
||||||
$([ $servers -gt 1 ] && echo 0.18 || echo 1.8) inf) && \
|
$([ $servers -gt 1 ] && echo 0.18 || echo 1.8) \
|
||||||
|
$client_max_min_out_interval) && \
|
||||||
test_ok || test_bad
|
test_ok || test_bad
|
||||||
|
|
||||||
[ $? -eq 0 ] || ret=1
|
[ $? -eq 0 ] || ret=1
|
||||||
|
|||||||
123
test/unit/hash.c
Normal file
123
test/unit/hash.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Miroslav Lichvar 2018
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <sysincl.h>
|
||||||
|
#include <hash.h>
|
||||||
|
#include <logging.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
struct hash_test {
|
||||||
|
const char *name;
|
||||||
|
const unsigned char out[MAX_HASH_LENGTH];
|
||||||
|
unsigned int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
test_unit(void)
|
||||||
|
{
|
||||||
|
unsigned char data1[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
unsigned char data2[] = "12345678910";
|
||||||
|
unsigned char out[MAX_HASH_LENGTH];
|
||||||
|
struct hash_test tests[] = {
|
||||||
|
{ "MD5", "\xfc\x24\x97\x1b\x52\x66\xdc\x46\xef\xe0\xe8\x08\x46\x89\xb6\x88", 16 },
|
||||||
|
{ "SHA1", "\xd8\x85\xb3\x86\xce\xea\x93\xeb\x92\xcd\x7b\x94\xb9\x8d\xc2\x8e"
|
||||||
|
"\x3e\x31\x13\xdd", 20},
|
||||||
|
{ "SHA256", "\x0e\x35\x14\xe7\x15\x7a\x1d\xdd\xea\x11\x78\xd3\x41\xf6\xb9\x3e"
|
||||||
|
"\xa0\x42\x96\x73\x3c\x54\x74\x0b\xfa\x6b\x9e\x29\x59\xad\x69\xd3", 32 },
|
||||||
|
{ "SHA384", "\x2c\xeb\xbd\x4d\x95\xed\xad\x03\xed\x80\xc4\xf3\xa6\x10\x21\xde"
|
||||||
|
"\x40\x69\x54\xed\x42\x70\xb8\x95\xb0\x6f\x01\x1d\x04\xdf\x57\xbc"
|
||||||
|
"\x1d\xb5\x85\xbf\x4f\x03\x88\xd5\x83\x93\xbc\x81\x90\xb0\xa9\x9b", 48 },
|
||||||
|
{ "SHA512", "\x20\xba\xec\xcb\x68\x98\x33\x5b\x70\x26\x63\x13\xe2\xf7\x0e\x67"
|
||||||
|
"\x08\xf3\x77\x4f\xbd\xeb\xc4\xa8\xc5\x94\xe2\x39\x40\x7e\xed\x0b"
|
||||||
|
"\x69\x0e\x18\xa5\xa2\x03\x73\xe7\x1d\x20\x7d\x3f\xc8\x70\x2d\x64"
|
||||||
|
"\x9e\x89\x6d\x20\x6a\x4a\x5a\x46\xe7\x4f\x2c\xf9\x0f\x0a\x54\xdc", 64 },
|
||||||
|
{ "SHA3-224", "\x3b\xa2\x22\x28\xdd\x26\x18\xec\x3b\xb9\x25\x39\x5e\xbd\x94\x25"
|
||||||
|
"\xd4\x20\x8a\x76\x76\xc0\x3c\x5d\x9e\x0a\x06\x46", 28},
|
||||||
|
{ "SHA3-256", "\x26\xd1\x19\xb2\xc1\x64\xc8\xb8\x10\xd8\xa8\x1c\xb6\xa4\x0d\x29"
|
||||||
|
"\x09\xc9\x8e\x2e\x2d\xde\x7a\x74\x8c\x43\x70\xb8\xaa\x0f\x09\x17", 32 },
|
||||||
|
{ "SHA3-384", "\x6a\x64\xb9\x89\x08\x29\xd0\xa7\x4b\x84\xba\xa6\x65\xf5\xe7\x54"
|
||||||
|
"\xe2\x18\x12\xc3\x63\x34\xc6\xba\x26\xf5\x6e\x99\xe2\x54\xcc\x9d"
|
||||||
|
"\x01\x10\x9d\xee\x35\x38\x04\x83\xe5\x71\x70\xd8\xc8\x99\x96\xd8", 48 },
|
||||||
|
{ "SHA3-512", "\xa8\xe3\x2b\x65\x1f\x87\x90\x73\x19\xc8\xa0\x3f\xe3\x85\x60\x3c"
|
||||||
|
"\x39\xfc\xcb\xc1\x29\xe1\x23\x7d\x8b\x56\x54\xe3\x08\x9d\xf9\x74"
|
||||||
|
"\x78\x69\x2e\x3c\x7e\x51\x1e\x9d\xab\x09\xbe\xe7\x6b\x1a\xa1\x22"
|
||||||
|
"\x93\xb1\x2b\x82\x9d\x1e\xcf\xa8\x99\xc5\xec\x7b\x1d\x89\x07\x2b", 64 },
|
||||||
|
{ "RMD128", "\x6f\xd7\x1f\x37\x47\x0f\xbd\x42\x57\xc8\xbb\xee\xba\x65\xf9\x35", 16 },
|
||||||
|
{ "RMD160", "\x7a\x88\xec\xc7\x09\xc5\x65\x34\x11\x24\xe3\xf9\xf7\xa5\xbf\xc6"
|
||||||
|
"\x01\xe2\xc9\x32", 20},
|
||||||
|
{ "RMD256", "\x59\xdf\xd4\xcb\xc9\xbe\x7c\x27\x08\xa7\x23\xf7\xb3\x0c\xf0\x0d"
|
||||||
|
"\xa0\xcf\x5b\x18\x16\x51\x56\x6d\xda\x7b\x87\x24\x9d\x83\x35\xe1", 32 },
|
||||||
|
{ "RMD320", "\x68\x98\x10\xf4\xb6\x79\xb6\x15\xf1\x48\x2d\x73\xd0\x23\x84\x01"
|
||||||
|
"\xbf\xaa\x67\xcf\x1e\x35\x5c\xbf\xe9\xb8\xaf\xe1\xee\x0d\xf0\x6b"
|
||||||
|
"\xe2\x3a\x9a\x3a\xa7\x56\xad\x70", 40},
|
||||||
|
{ "TIGER", "\x1c\xcd\x68\x74\xca\xd6\xd5\x17\xba\x3e\x82\xaf\xbd\x70\xdc\x66"
|
||||||
|
"\x99\xaa\xae\x16\x72\x59\xd1\x64", 24},
|
||||||
|
{ "WHIRLPOOL", "\xe3\xcd\xe6\xbf\xe1\x8c\xe4\x4d\xc8\xb4\xa5\x7c\x36\x8d\xc8\x8a"
|
||||||
|
"\x8b\xad\x52\x24\xc0\x4e\x99\x5b\x7e\x86\x94\x2d\x10\x56\x12\xa3"
|
||||||
|
"\x29\x2a\x65\x0f\x9e\x07\xbc\x15\x21\x14\xe6\x07\xfc\xe6\xb9\x2f"
|
||||||
|
"\x13\xe2\x57\xe9\x0a\xb0\xd2\xf4\xa3\x20\x36\x9c\x88\x92\x8e\xc9", 64 },
|
||||||
|
{ "", "", 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int length;
|
||||||
|
int i, j, hash_id;
|
||||||
|
|
||||||
|
for (i = 0; tests[i].name[0] != '\0'; i++) {
|
||||||
|
hash_id = HSH_GetHashId(tests[i].name);
|
||||||
|
if (hash_id < 0) {
|
||||||
|
TEST_CHECK(strcmp(tests[i].name, "MD5"));
|
||||||
|
#ifdef FEAT_SECHASH
|
||||||
|
TEST_CHECK(strcmp(tests[i].name, "SHA1"));
|
||||||
|
TEST_CHECK(strcmp(tests[i].name, "SHA256"));
|
||||||
|
TEST_CHECK(strcmp(tests[i].name, "SHA384"));
|
||||||
|
TEST_CHECK(strcmp(tests[i].name, "SHA512"));
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG("testing %s", tests[i].name);
|
||||||
|
|
||||||
|
for (j = 0; j <= sizeof (out); j++) {
|
||||||
|
TEST_CHECK(HSH_GetHashId(tests[i].name) == hash_id);
|
||||||
|
TEST_CHECK(HSH_GetHashId("nosuchhash") < 0);
|
||||||
|
|
||||||
|
memset(out, 0, sizeof (out));
|
||||||
|
length = HSH_Hash(hash_id, data1, sizeof (data1) - 1, data2, sizeof (data2) - 1,
|
||||||
|
out, j);
|
||||||
|
|
||||||
|
if (j >= tests[i].length)
|
||||||
|
TEST_CHECK(length == tests[i].length);
|
||||||
|
else
|
||||||
|
TEST_CHECK(length == 0 || length == j);
|
||||||
|
|
||||||
|
TEST_CHECK(!memcmp(out, tests[i].out, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 10000; j++) {
|
||||||
|
length = HSH_Hash(hash_id, data1, random() % sizeof (data1),
|
||||||
|
random() % 2 ? data2 : NULL, random() % sizeof (data2),
|
||||||
|
out, sizeof (out));
|
||||||
|
TEST_CHECK(length == tests[i].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HSH_Finalise();
|
||||||
|
}
|
||||||
@@ -36,6 +36,7 @@ static int req_length, res_length;
|
|||||||
#define NIO_CloseServerSocket(fd) assert(fd == 100)
|
#define NIO_CloseServerSocket(fd) assert(fd == 100)
|
||||||
#define NIO_OpenClientSocket(addr) ((addr)->ip_addr.family != IPADDR_UNSPEC ? 101 : 0)
|
#define NIO_OpenClientSocket(addr) ((addr)->ip_addr.family != IPADDR_UNSPEC ? 101 : 0)
|
||||||
#define NIO_CloseClientSocket(fd) assert(fd == 101)
|
#define NIO_CloseClientSocket(fd) assert(fd == 101)
|
||||||
|
#define NIO_IsServerSocket(fd) (fd == 100)
|
||||||
#define NIO_SendPacket(msg, to, from, len, process_tx) (memcpy(&req_buffer, msg, len), req_length = len, 1)
|
#define NIO_SendPacket(msg, to, from, len, process_tx) (memcpy(&req_buffer, msg, len), req_length = len, 1)
|
||||||
#define SCH_AddTimeoutByDelay(delay, handler, arg) (1 ? 102 : (handler(arg), 1))
|
#define SCH_AddTimeoutByDelay(delay, handler, arg) (1 ? 102 : (handler(arg), 1))
|
||||||
#define SCH_AddTimeoutInClass(delay, separation, randomness, class, handler, arg) \
|
#define SCH_AddTimeoutInClass(delay, separation, randomness, class, handler, arg) \
|
||||||
@@ -43,6 +44,7 @@ static int req_length, res_length;
|
|||||||
#define SCH_RemoveTimeout(id) assert(!id || id == 102)
|
#define SCH_RemoveTimeout(id) assert(!id || id == 102)
|
||||||
#define LCL_ReadRawTime(ts) (*ts = current_time)
|
#define LCL_ReadRawTime(ts) (*ts = current_time)
|
||||||
#define LCL_ReadCookedTime(ts, err) do {double *p = err; *ts = current_time; if (p) *p = 0.0;} while (0)
|
#define LCL_ReadCookedTime(ts, err) do {double *p = err; *ts = current_time; if (p) *p = 0.0;} while (0)
|
||||||
|
#define LCL_GetSysPrecisionAsLog() (random() % 10 - 30)
|
||||||
#define SRC_UpdateReachability(inst, reach)
|
#define SRC_UpdateReachability(inst, reach)
|
||||||
#define SRC_ResetReachability(inst)
|
#define SRC_ResetReachability(inst)
|
||||||
|
|
||||||
@@ -55,8 +57,6 @@ add_timeout_in_class(double min_delay, double separation, double randomness,
|
|||||||
|
|
||||||
#include <ntp_core.c>
|
#include <ntp_core.c>
|
||||||
|
|
||||||
static NCR_Instance inst;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
advance_time(double x)
|
advance_time(double x)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ advance_time(double x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_request(void)
|
send_request(NCR_Instance inst)
|
||||||
{
|
{
|
||||||
NTP_Local_Address local_addr;
|
NTP_Local_Address local_addr;
|
||||||
NTP_Local_Timestamp local_ts;
|
NTP_Local_Timestamp local_ts;
|
||||||
@@ -74,19 +74,48 @@ send_request(void)
|
|||||||
|
|
||||||
transmit_timeout(inst);
|
transmit_timeout(inst);
|
||||||
TEST_CHECK(!inst->valid_rx);
|
TEST_CHECK(!inst->valid_rx);
|
||||||
TEST_CHECK(!inst->updated_timestamps);
|
|
||||||
TEST_CHECK(prev_tx_count + 1 == inst->report.total_tx_count);
|
TEST_CHECK(prev_tx_count + 1 == inst->report.total_tx_count);
|
||||||
|
|
||||||
advance_time(1e-4);
|
advance_time(1e-5);
|
||||||
|
|
||||||
|
if (random() % 2) {
|
||||||
|
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||||
|
local_addr.if_index = INVALID_IF_INDEX;
|
||||||
|
local_addr.sock_fd = 101;
|
||||||
|
local_ts.ts = current_time;
|
||||||
|
local_ts.err = 0.0;
|
||||||
|
local_ts.source = NTP_TS_KERNEL;
|
||||||
|
|
||||||
|
NCR_ProcessTxKnown(inst, &local_addr, &local_ts, &req_buffer.ntp_pkt, req_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_request(NTP_Remote_Address *remote_addr)
|
||||||
|
{
|
||||||
|
NTP_Local_Address local_addr;
|
||||||
|
NTP_Local_Timestamp local_ts;
|
||||||
|
|
||||||
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||||
local_addr.if_index = INVALID_IF_INDEX;
|
local_addr.if_index = INVALID_IF_INDEX;
|
||||||
local_addr.sock_fd = 101;
|
local_addr.sock_fd = 100;
|
||||||
local_ts.ts = current_time;
|
local_ts.ts = current_time;
|
||||||
local_ts.err = 0.0;
|
local_ts.err = 0.0;
|
||||||
local_ts.source = NTP_TS_DAEMON;
|
local_ts.source = NTP_TS_KERNEL;
|
||||||
|
|
||||||
NCR_ProcessTxKnown(inst, &local_addr, &local_ts, &req_buffer.ntp_pkt, req_length);
|
res_length = 0;
|
||||||
|
NCR_ProcessRxUnknown(remote_addr, &local_addr, &local_ts,
|
||||||
|
&req_buffer.ntp_pkt, req_length);
|
||||||
|
res_length = req_length;
|
||||||
|
res_buffer = req_buffer;
|
||||||
|
|
||||||
|
advance_time(1e-5);
|
||||||
|
|
||||||
|
if (random() % 2) {
|
||||||
|
local_ts.ts = current_time;
|
||||||
|
NCR_ProcessTxUnknown(remote_addr, &local_addr, &local_ts,
|
||||||
|
&res_buffer.ntp_pkt, res_length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -165,30 +194,36 @@ send_response(int interleaved, int authenticated, int allow_update, int valid_ts
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_response(int valid, int updated)
|
process_response(NCR_Instance inst, int good, int valid, int updated_sync, int updated_init)
|
||||||
{
|
{
|
||||||
NTP_Local_Address local_addr;
|
NTP_Local_Address local_addr;
|
||||||
NTP_Local_Timestamp local_ts;
|
NTP_Local_Timestamp local_ts;
|
||||||
NTP_Packet *res;
|
NTP_Packet *res;
|
||||||
uint32_t prev_rx_count, prev_valid_count;
|
uint32_t prev_rx_count, prev_valid_count;
|
||||||
struct timespec prev_rx_ts;
|
struct timespec prev_rx_ts, prev_init_rx_ts;
|
||||||
int prev_open_socket;
|
int prev_open_socket, ret;
|
||||||
|
|
||||||
res = &res_buffer.ntp_pkt;
|
res = &res_buffer.ntp_pkt;
|
||||||
|
|
||||||
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||||
local_addr.if_index = INVALID_IF_INDEX;
|
local_addr.if_index = INVALID_IF_INDEX;
|
||||||
local_addr.sock_fd = NTP_LVM_TO_MODE(res->lvm) == MODE_ACTIVE ? 100 : 101;
|
local_addr.sock_fd = NTP_LVM_TO_MODE(res->lvm) != MODE_SERVER ? 100 : 101;
|
||||||
local_ts.ts = current_time;
|
local_ts.ts = current_time;
|
||||||
local_ts.err = 0.0;
|
local_ts.err = 0.0;
|
||||||
local_ts.source = NTP_TS_DAEMON;
|
local_ts.source = NTP_TS_KERNEL;
|
||||||
|
|
||||||
prev_rx_count = inst->report.total_rx_count;
|
prev_rx_count = inst->report.total_rx_count;
|
||||||
prev_valid_count = inst->report.total_valid_count;
|
prev_valid_count = inst->report.total_valid_count;
|
||||||
prev_rx_ts = inst->local_rx.ts;
|
prev_rx_ts = inst->local_rx.ts;
|
||||||
|
prev_init_rx_ts = inst->init_local_rx.ts;
|
||||||
prev_open_socket = inst->local_addr.sock_fd != INVALID_SOCK_FD;
|
prev_open_socket = inst->local_addr.sock_fd != INVALID_SOCK_FD;
|
||||||
|
|
||||||
NCR_ProcessRxKnown(inst, &local_addr, &local_ts, res, res_length);
|
ret = NCR_ProcessRxKnown(inst, &local_addr, &local_ts, res, res_length);
|
||||||
|
|
||||||
|
if (good > 0)
|
||||||
|
TEST_CHECK(ret);
|
||||||
|
else if (!good)
|
||||||
|
TEST_CHECK(!ret);
|
||||||
|
|
||||||
if (prev_open_socket)
|
if (prev_open_socket)
|
||||||
TEST_CHECK(prev_rx_count + 1 == inst->report.total_rx_count);
|
TEST_CHECK(prev_rx_count + 1 == inst->report.total_rx_count);
|
||||||
@@ -200,23 +235,51 @@ process_response(int valid, int updated)
|
|||||||
else
|
else
|
||||||
TEST_CHECK(prev_valid_count == inst->report.total_valid_count);
|
TEST_CHECK(prev_valid_count == inst->report.total_valid_count);
|
||||||
|
|
||||||
if (updated)
|
if (updated_sync)
|
||||||
TEST_CHECK(UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
TEST_CHECK(UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
||||||
else
|
else
|
||||||
TEST_CHECK(!UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
TEST_CHECK(!UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
||||||
|
|
||||||
|
if (updated_init > 0)
|
||||||
|
TEST_CHECK(UTI_CompareTimespecs(&inst->init_local_rx.ts, &prev_init_rx_ts));
|
||||||
|
else if (!updated_init)
|
||||||
|
TEST_CHECK(!UTI_CompareTimespecs(&inst->init_local_rx.ts, &prev_init_rx_ts));
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
TEST_CHECK(UTI_IsZeroTimespec(&inst->init_local_rx.ts));
|
||||||
|
TEST_CHECK(UTI_IsZeroNtp64(&inst->init_remote_ntp_tx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_replay(NCR_Instance inst, NTP_Receive_Buffer *packet_queue,
|
||||||
|
int queue_length, int updated_init)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
res_buffer = packet_queue[random() % queue_length];
|
||||||
|
} while (!UTI_CompareNtp64(&res_buffer.ntp_pkt.transmit_ts,
|
||||||
|
&inst->remote_ntp_tx));
|
||||||
|
process_response(inst, 0, 0, 0, updated_init);
|
||||||
|
advance_time(1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PACKET_QUEUE_LENGTH 10
|
||||||
|
|
||||||
void
|
void
|
||||||
test_unit(void)
|
test_unit(void)
|
||||||
{
|
{
|
||||||
char source_line[] = "127.0.0.1";
|
char source_line[] = "127.0.0.1 maxdelaydevratio 1e6";
|
||||||
char conf[][100] = {
|
char conf[][100] = {
|
||||||
|
"allow",
|
||||||
"port 0",
|
"port 0",
|
||||||
|
"local",
|
||||||
"keyfile ntp_core.keys"
|
"keyfile ntp_core.keys"
|
||||||
};
|
};
|
||||||
int i, j, interleaved, authenticated, valid, updated, has_updated;
|
int i, j, k, interleaved, authenticated, valid, updated, has_updated;
|
||||||
CPS_NTP_Source source;
|
CPS_NTP_Source source;
|
||||||
NTP_Remote_Address remote_addr;
|
NTP_Remote_Address remote_addr;
|
||||||
|
NCR_Instance inst1, inst2;
|
||||||
|
NTP_Receive_Buffer packet_queue[PACKET_QUEUE_LENGTH];
|
||||||
|
|
||||||
CNF_Initialise(0, 0);
|
CNF_Initialise(0, 0);
|
||||||
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
|
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
|
||||||
@@ -231,12 +294,16 @@ test_unit(void)
|
|||||||
REF_Initialise();
|
REF_Initialise();
|
||||||
KEY_Initialise();
|
KEY_Initialise();
|
||||||
|
|
||||||
|
CNF_SetupAccessRestrictions();
|
||||||
|
|
||||||
|
CPS_ParseNTPSourceAdd(source_line, &source);
|
||||||
|
|
||||||
for (i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
CPS_ParseNTPSourceAdd(source_line, &source);
|
|
||||||
if (random() % 2)
|
if (random() % 2)
|
||||||
source.params.interleaved = 1;
|
source.params.interleaved = 1;
|
||||||
if (random() % 2)
|
if (random() % 2)
|
||||||
source.params.authkey = 1;
|
source.params.authkey = 1;
|
||||||
|
source.params.version = random() % 4 + 1;
|
||||||
|
|
||||||
UTI_ZeroTimespec(¤t_time);
|
UTI_ZeroTimespec(¤t_time);
|
||||||
advance_time(TST_GetRandomDouble(1.0, 1e9));
|
advance_time(TST_GetRandomDouble(1.0, 1e9));
|
||||||
@@ -244,48 +311,125 @@ test_unit(void)
|
|||||||
TST_GetRandomAddress(&remote_addr.ip_addr, IPADDR_UNSPEC, -1);
|
TST_GetRandomAddress(&remote_addr.ip_addr, IPADDR_UNSPEC, -1);
|
||||||
remote_addr.port = 123;
|
remote_addr.port = 123;
|
||||||
|
|
||||||
inst = NCR_GetInstance(&remote_addr, random() % 2 ? NTP_SERVER : NTP_PEER, &source.params);
|
inst1 = NCR_GetInstance(&remote_addr, random() % 2 ? NTP_SERVER : NTP_PEER, &source.params);
|
||||||
NCR_StartInstance(inst);
|
NCR_StartInstance(inst1);
|
||||||
has_updated = 0;
|
has_updated = 0;
|
||||||
|
|
||||||
for (j = 0; j < 50; j++) {
|
for (j = 0; j < 50; j++) {
|
||||||
DEBUG_LOG("iteration %d, %d", i, j);
|
DEBUG_LOG("client/peer test iteration %d/%d", i, j);
|
||||||
|
|
||||||
interleaved = random() % 2 && (inst->mode != MODE_CLIENT ||
|
interleaved = random() % 2 && (inst1->mode != MODE_CLIENT ||
|
||||||
inst->tx_count < MAX_CLIENT_INTERLEAVED_TX);
|
inst1->tx_count < MAX_CLIENT_INTERLEAVED_TX);
|
||||||
authenticated = random() % 2;
|
authenticated = random() % 2;
|
||||||
valid = (!interleaved || (source.params.interleaved && has_updated)) &&
|
valid = (!interleaved || (source.params.interleaved && has_updated)) &&
|
||||||
(!source.params.authkey || authenticated);
|
(!source.params.authkey || authenticated);
|
||||||
updated = (valid || inst->mode == MODE_ACTIVE) &&
|
updated = (valid || inst1->mode == MODE_ACTIVE) &&
|
||||||
(!source.params.authkey || authenticated);
|
(!source.params.authkey || authenticated);
|
||||||
has_updated = has_updated || updated;
|
has_updated = has_updated || updated;
|
||||||
|
if (inst1->mode == MODE_CLIENT)
|
||||||
|
updated = 0;
|
||||||
|
|
||||||
send_request();
|
send_request(inst1);
|
||||||
|
|
||||||
send_response(interleaved, authenticated, 1, 0, 1);
|
send_response(interleaved, authenticated, 1, 0, 1);
|
||||||
process_response(0, inst->mode == MODE_CLIENT ? 0 : updated);
|
DEBUG_LOG("response 1");
|
||||||
|
process_response(inst1, 0, 0, 0, updated);
|
||||||
|
|
||||||
if (source.params.authkey) {
|
if (source.params.authkey) {
|
||||||
send_response(interleaved, authenticated, 1, 1, 0);
|
send_response(interleaved, authenticated, 1, 1, 0);
|
||||||
process_response(0, 0);
|
DEBUG_LOG("response 2");
|
||||||
|
process_response(inst1, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
send_response(interleaved, authenticated, 1, 1, 1);
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
process_response(valid, updated);
|
DEBUG_LOG("response 3");
|
||||||
process_response(0, 0);
|
process_response(inst1, -1, valid, valid, updated);
|
||||||
|
DEBUG_LOG("response 4");
|
||||||
|
process_response(inst1, 0, 0, 0, 0);
|
||||||
|
|
||||||
advance_time(-1.0);
|
advance_time(-1.0);
|
||||||
|
|
||||||
send_response(interleaved, authenticated, 1, 1, 1);
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
process_response(0, 0);
|
DEBUG_LOG("response 5");
|
||||||
|
process_response(inst1, 0, 0, 0, updated && valid);
|
||||||
|
|
||||||
advance_time(1.0);
|
advance_time(1.0);
|
||||||
|
|
||||||
send_response(interleaved, authenticated, 1, 1, 1);
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
process_response(0, inst->mode == MODE_CLIENT ? 0 : updated);
|
DEBUG_LOG("response 6");
|
||||||
|
process_response(inst1, 0, 0, valid && updated, updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
NCR_DestroyInstance(inst);
|
NCR_DestroyInstance(inst1);
|
||||||
|
|
||||||
|
inst1 = NCR_GetInstance(&remote_addr, random() % 2 ? NTP_SERVER : NTP_PEER, &source.params);
|
||||||
|
NCR_StartInstance(inst1);
|
||||||
|
|
||||||
|
for (j = 0; j < 20; j++) {
|
||||||
|
DEBUG_LOG("server test iteration %d/%d", i, j);
|
||||||
|
|
||||||
|
send_request(inst1);
|
||||||
|
process_request(&remote_addr);
|
||||||
|
process_response(inst1, 1, 1, 1, 0);
|
||||||
|
advance_time(1 << inst1->local_poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
NCR_DestroyInstance(inst1);
|
||||||
|
|
||||||
|
inst1 = NCR_GetInstance(&remote_addr, NTP_PEER, &source.params);
|
||||||
|
NCR_StartInstance(inst1);
|
||||||
|
inst2 = NCR_GetInstance(&remote_addr, NTP_PEER, &source.params);
|
||||||
|
NCR_StartInstance(inst2);
|
||||||
|
|
||||||
|
res_length = req_length = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < 20; j++) {
|
||||||
|
DEBUG_LOG("peer replay test iteration %d/%d", i, j);
|
||||||
|
|
||||||
|
send_request(inst1);
|
||||||
|
res_buffer = req_buffer;
|
||||||
|
assert(!res_length || res_length == req_length);
|
||||||
|
res_length = req_length;
|
||||||
|
|
||||||
|
TEST_CHECK(inst1->valid_timestamps == (j > 0));
|
||||||
|
|
||||||
|
DEBUG_LOG("response 1->2");
|
||||||
|
process_response(inst2, j > source.params.interleaved, j > 0, j > 0, 1);
|
||||||
|
|
||||||
|
packet_queue[(j * 2) % PACKET_QUEUE_LENGTH] = res_buffer;
|
||||||
|
|
||||||
|
for (k = 0; k < j % 4 + 1; k++) {
|
||||||
|
DEBUG_LOG("replay ?->1 %d", k);
|
||||||
|
process_replay(inst1, packet_queue, MIN(j * 2 + 1, PACKET_QUEUE_LENGTH), k ? -1 : 1);
|
||||||
|
DEBUG_LOG("replay ?->2 %d", k);
|
||||||
|
process_replay(inst2, packet_queue, MIN(j * 2 + 1, PACKET_QUEUE_LENGTH), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
advance_time(1 << (source.params.minpoll - 1));
|
||||||
|
|
||||||
|
send_request(inst2);
|
||||||
|
res_buffer = req_buffer;
|
||||||
|
assert(res_length == req_length);
|
||||||
|
|
||||||
|
TEST_CHECK(inst2->valid_timestamps == (j > 0));
|
||||||
|
|
||||||
|
DEBUG_LOG("response 2->1");
|
||||||
|
process_response(inst1, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
packet_queue[(j * 2 + 1) % PACKET_QUEUE_LENGTH] = res_buffer;
|
||||||
|
|
||||||
|
for (k = 0; k < j % 4 + 1; k++) {
|
||||||
|
DEBUG_LOG("replay ?->1 %d", k);
|
||||||
|
process_replay(inst1, packet_queue, MIN(j * 2 + 2, PACKET_QUEUE_LENGTH), k ? -1 : 1);
|
||||||
|
DEBUG_LOG("replay ?->2 %d", k);
|
||||||
|
process_replay(inst2, packet_queue, MIN(j * 2 + 2, PACKET_QUEUE_LENGTH), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
advance_time(1 << (source.params.minpoll - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
NCR_DestroyInstance(inst1);
|
||||||
|
NCR_DestroyInstance(inst2);
|
||||||
}
|
}
|
||||||
|
|
||||||
KEY_Finalise();
|
KEY_Finalise();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
void test_unit(void) {
|
void test_unit(void) {
|
||||||
NTP_int64 ntp_ts, ntp_fuzz;
|
NTP_int64 ntp_ts, ntp_fuzz;
|
||||||
struct timespec ts, ts2;
|
struct timespec ts, ts2;
|
||||||
|
struct timeval tv;
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
double x, y;
|
double x, y;
|
||||||
Float f;
|
Float f;
|
||||||
@@ -40,6 +41,32 @@ void test_unit(void) {
|
|||||||
TEST_CHECK(UTI_DoubleToNtp32(1000000) == htonl(0xffffffff));
|
TEST_CHECK(UTI_DoubleToNtp32(1000000) == htonl(0xffffffff));
|
||||||
TEST_CHECK(UTI_DoubleToNtp32(-1.0) == htonl(0));
|
TEST_CHECK(UTI_DoubleToNtp32(-1.0) == htonl(0));
|
||||||
|
|
||||||
|
UTI_DoubleToTimeval(0.4e-6, &tv);
|
||||||
|
TEST_CHECK(tv.tv_sec == 0);
|
||||||
|
TEST_CHECK(tv.tv_usec == 0);
|
||||||
|
UTI_DoubleToTimeval(-0.4e-6, &tv);
|
||||||
|
TEST_CHECK(tv.tv_sec == 0);
|
||||||
|
TEST_CHECK(tv.tv_usec == 0);
|
||||||
|
UTI_DoubleToTimeval(0.5e-6, &tv);
|
||||||
|
TEST_CHECK(tv.tv_sec == 0);
|
||||||
|
TEST_CHECK(tv.tv_usec == 1);
|
||||||
|
UTI_DoubleToTimeval(-0.5e-6, &tv);
|
||||||
|
TEST_CHECK(tv.tv_sec == -1);
|
||||||
|
TEST_CHECK(tv.tv_usec == 999999);
|
||||||
|
|
||||||
|
UTI_DoubleToTimespec(0.9e-9, &ts);
|
||||||
|
TEST_CHECK(ts.tv_sec == 0);
|
||||||
|
TEST_CHECK(ts.tv_nsec == 0);
|
||||||
|
UTI_DoubleToTimespec(1.0e-9, &ts);
|
||||||
|
TEST_CHECK(ts.tv_sec == 0);
|
||||||
|
TEST_CHECK(ts.tv_nsec == 1);
|
||||||
|
UTI_DoubleToTimespec(-0.9e-9, &ts);
|
||||||
|
TEST_CHECK(ts.tv_sec == 0);
|
||||||
|
TEST_CHECK(ts.tv_nsec == 0);
|
||||||
|
UTI_DoubleToTimespec(-1.0e-9, &ts);
|
||||||
|
TEST_CHECK(ts.tv_sec == -1);
|
||||||
|
TEST_CHECK(ts.tv_nsec == 999999999);
|
||||||
|
|
||||||
ntp_ts.hi = htonl(JAN_1970);
|
ntp_ts.hi = htonl(JAN_1970);
|
||||||
ntp_ts.lo = 0xffffffff;
|
ntp_ts.lo = 0xffffffff;
|
||||||
UTI_Ntp64ToTimespec(&ntp_ts, &ts);
|
UTI_Ntp64ToTimespec(&ntp_ts, &ts);
|
||||||
@@ -109,6 +136,11 @@ void test_unit(void) {
|
|||||||
TEST_CHECK(UTI_CompareNtp64(&ntp_ts, &ntp_fuzz) < 0);
|
TEST_CHECK(UTI_CompareNtp64(&ntp_ts, &ntp_fuzz) < 0);
|
||||||
TEST_CHECK(UTI_CompareNtp64(&ntp_fuzz, &ntp_ts) > 0);
|
TEST_CHECK(UTI_CompareNtp64(&ntp_fuzz, &ntp_ts) > 0);
|
||||||
|
|
||||||
|
TEST_CHECK(UTI_IsEqualAnyNtp64(&ntp_ts, &ntp_ts, NULL, NULL));
|
||||||
|
TEST_CHECK(UTI_IsEqualAnyNtp64(&ntp_ts, NULL, &ntp_ts, NULL));
|
||||||
|
TEST_CHECK(UTI_IsEqualAnyNtp64(&ntp_ts, NULL, NULL, &ntp_ts));
|
||||||
|
TEST_CHECK(!UTI_IsEqualAnyNtp64(&ntp_ts, &ntp_fuzz, &ntp_fuzz, &ntp_fuzz));
|
||||||
|
|
||||||
ts.tv_sec = 1;
|
ts.tv_sec = 1;
|
||||||
ts.tv_nsec = 2;
|
ts.tv_nsec = 2;
|
||||||
ts2.tv_sec = 1;
|
ts2.tv_sec = 1;
|
||||||
|
|||||||
41
util.c
41
util.c
@@ -119,13 +119,11 @@ UTI_TimevalToDouble(struct timeval *tv)
|
|||||||
void
|
void
|
||||||
UTI_DoubleToTimeval(double a, struct timeval *b)
|
UTI_DoubleToTimeval(double a, struct timeval *b)
|
||||||
{
|
{
|
||||||
long int_part;
|
|
||||||
double frac_part;
|
double frac_part;
|
||||||
int_part = (long)(a);
|
|
||||||
frac_part = 1.0e6 * (a - (double)(int_part));
|
b->tv_sec = a;
|
||||||
frac_part = frac_part > 0 ? frac_part + 0.5 : frac_part - 0.5;
|
frac_part = 1.0e6 * (a - b->tv_sec);
|
||||||
b->tv_sec = int_part;
|
b->tv_usec = frac_part > 0 ? frac_part + 0.5 : frac_part - 0.5;
|
||||||
b->tv_usec = (long)frac_part;
|
|
||||||
UTI_NormaliseTimeval(b);
|
UTI_NormaliseTimeval(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,16 +366,14 @@ UTI_IPToRefid(IPAddr *ip)
|
|||||||
case IPADDR_INET4:
|
case IPADDR_INET4:
|
||||||
return ip->addr.in4;
|
return ip->addr.in4;
|
||||||
case IPADDR_INET6:
|
case IPADDR_INET6:
|
||||||
if (MD5_hash < 0) {
|
if (MD5_hash < 0)
|
||||||
MD5_hash = HSH_GetHashId("MD5");
|
MD5_hash = HSH_GetHashId("MD5");
|
||||||
assert(MD5_hash >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HSH_Hash(MD5_hash, (unsigned const char *)ip->addr.in6, sizeof
|
if (MD5_hash < 0 ||
|
||||||
(ip->addr.in6), NULL, 0, buf, 16) != 16) {
|
HSH_Hash(MD5_hash, (const unsigned char *)ip->addr.in6, sizeof (ip->addr.in6),
|
||||||
assert(0);
|
NULL, 0, buf, sizeof (buf)) != sizeof (buf))
|
||||||
return 0;
|
LOG_FATAL("Could not get MD5");
|
||||||
};
|
|
||||||
return (uint32_t)buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
|
return (uint32_t)buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -728,6 +724,23 @@ UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3)
|
||||||
|
{
|
||||||
|
if (b1 && a->lo == b1->lo && a->hi == b1->hi)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (b2 && a->lo == b2->lo && a->hi == b2->hi)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (b3 && a->lo == b3->lo && a->hi == b3->hi)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
/* Seconds part of NTP timestamp correponding to the origin of the time_t format */
|
/* Seconds part of NTP timestamp correponding to the origin of the time_t format */
|
||||||
#define JAN_1970 0x83aa7e80UL
|
#define JAN_1970 0x83aa7e80UL
|
||||||
|
|
||||||
|
|||||||
4
util.h
4
util.h
@@ -136,6 +136,10 @@ extern int UTI_IsZeroNtp64(NTP_int64 *ts);
|
|||||||
b, and 1 if a is after b. */
|
b, and 1 if a is after b. */
|
||||||
extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b);
|
extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b);
|
||||||
|
|
||||||
|
/* Compare an NTP timestamp with up to three other timestamps. Returns 0
|
||||||
|
if a is not equal to any of b1, b2, and b3, 1 otherwise. */
|
||||||
|
extern int UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3);
|
||||||
|
|
||||||
/* Convert a timespec into an NTP timestamp */
|
/* Convert a timespec into an NTP timestamp */
|
||||||
extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
|
extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user