mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 15:15:07 -05:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c507975c | ||
|
|
b4235abd36 | ||
|
|
1966085a97 | ||
|
|
e31e7af48f | ||
|
|
adb9123fc3 | ||
|
|
b0f7efd59e | ||
|
|
e28dfada8c | ||
|
|
ac0b28cce6 | ||
|
|
48b16ae66c | ||
|
|
061579ec28 | ||
|
|
f2f834e7e7 | ||
|
|
a7802e9a76 |
5
README
5
README
@@ -16,7 +16,7 @@ and systems that do not run continuosly, or run on a virtual machine.
|
|||||||
|
|
||||||
Typical accuracy between two machines synchronised over the Internet is
|
Typical accuracy between two machines synchronised over the Internet is
|
||||||
within a few milliseconds; on a LAN, accuracy is typically in tens of
|
within a few milliseconds; on a LAN, accuracy is typically in tens of
|
||||||
microseconds. With hardware timestamping or a hardware reference clock
|
microseconds. With hardware timestamping, or a hardware reference clock,
|
||||||
sub-microsecond accuracy may be possible.
|
sub-microsecond accuracy may be possible.
|
||||||
|
|
||||||
Two programs are included in chrony, chronyd is a daemon that can be
|
Two programs are included in chrony, chronyd is a daemon that can be
|
||||||
@@ -203,6 +203,9 @@ Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
|||||||
Frank Otto <sandwichmacher@web.de>
|
Frank Otto <sandwichmacher@web.de>
|
||||||
Handling arbitrary HZ values
|
Handling arbitrary HZ values
|
||||||
|
|
||||||
|
Denny Page <dennypage@me.com>
|
||||||
|
Advice on support for hardware timestamping
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
9
client.c
9
client.c
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
|
* Copyright (C) Lonnie Abelbeck 2016
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2016
|
* Copyright (C) Miroslav Lichvar 2009-2016
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -2723,7 +2724,8 @@ process_cmd_waitsync(char *line)
|
|||||||
max_skew_ppm = 0.0;
|
max_skew_ppm = 0.0;
|
||||||
interval = 10.0;
|
interval = 10.0;
|
||||||
|
|
||||||
sscanf(line, "%d %lf %lf %lf", &max_tries, &max_correction, &max_skew_ppm, &interval);
|
if (sscanf(line, "%d %lf %lf %lf", &max_tries, &max_correction, &max_skew_ppm, &interval))
|
||||||
|
;
|
||||||
|
|
||||||
/* Don't allow shorter interval than 0.1 seconds */
|
/* Don't allow shorter interval than 0.1 seconds */
|
||||||
if (interval < 0.1)
|
if (interval < 0.1)
|
||||||
@@ -2831,7 +2833,8 @@ process_cmd_keygen(char *line)
|
|||||||
snprintf(hash_name, sizeof (hash_name), "MD5");
|
snprintf(hash_name, sizeof (hash_name), "MD5");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sscanf(line, "%u %16s %d", &id, hash_name, &bits);
|
if (sscanf(line, "%u %16s %d", &id, hash_name, &bits))
|
||||||
|
;
|
||||||
|
|
||||||
length = CLAMP(10, (bits + 7) / 8, sizeof (key));
|
length = CLAMP(10, (bits + 7) / 8, sizeof (key));
|
||||||
if (HSH_GetHashId(hash_name) < 0) {
|
if (HSH_GetHashId(hash_name) < 0) {
|
||||||
@@ -3094,7 +3097,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2016 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2017 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
|
|||||||
2
conf.c
2
conf.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2016
|
* Copyright (C) Miroslav Lichvar 2009-2017
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
3
configure
vendored
3
configure
vendored
@@ -4,7 +4,8 @@
|
|||||||
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
#
|
#
|
||||||
# Copyright (C) Richard P. Curnow 1997-2003
|
# Copyright (C) Richard P. Curnow 1997-2003
|
||||||
# Copyright (C) Miroslav Lichvar 2009, 2012-2015
|
# Copyright (C) Bryan Christianson 2016
|
||||||
|
# Copyright (C) Miroslav Lichvar 2009, 2012-2016
|
||||||
#
|
#
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// This file is part of chrony
|
// This file is part of chrony
|
||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
|
// Copyright (C) Miroslav Lichvar 2009-2017
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -105,7 +106,7 @@ If the user knows that round trip delays above a certain level should cause the
|
|||||||
measurement to be ignored, this level can be defined with the *maxdelay*
|
measurement to be ignored, this level can be defined with the *maxdelay*
|
||||||
option. For example, *maxdelay 0.3* would indicate that measurements with a
|
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.
|
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
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// This file is part of chrony
|
// This file is part of chrony
|
||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2016
|
// Copyright (C) Miroslav Lichvar 2009-2016
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
2
local.c
2
local.c
@@ -144,6 +144,8 @@ calculate_sys_precision(void)
|
|||||||
best *= 2;
|
best *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(precision_log >= -30);
|
||||||
|
|
||||||
DEBUG_LOG(LOGF_Local, "Clock precision %.9f (%d)", precision_quantum, precision_log);
|
DEBUG_LOG(LOGF_Local, "Clock precision %.9f (%d)", precision_quantum, precision_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
main.c
3
main.c
@@ -325,7 +325,8 @@ go_daemon(void)
|
|||||||
if (r) {
|
if (r) {
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
/* Print the error message from the child */
|
/* Print the error message from the child */
|
||||||
fprintf(stderr, "%.1024s\n", message);
|
message[sizeof (message) - 1] = '\0';
|
||||||
|
fprintf(stderr, "%s\n", message);
|
||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
} else
|
} else
|
||||||
|
|||||||
117
ntp_core.c
117
ntp_core.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2016
|
* Copyright (C) Miroslav Lichvar 2009-2017
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -243,6 +243,11 @@ static ARR_Instance broadcasts;
|
|||||||
/* Maximum acceptable delay in transmission for timestamp correction */
|
/* Maximum acceptable delay in transmission for timestamp correction */
|
||||||
#define MAX_TX_DELAY 1.0
|
#define MAX_TX_DELAY 1.0
|
||||||
|
|
||||||
|
/* Maximum allowed values of maxdelay parameters */
|
||||||
|
#define MAX_MAX_DELAY 1.0e3
|
||||||
|
#define MAX_MAX_DELAY_RATIO 1.0e6
|
||||||
|
#define MAX_MAX_DELAY_DEV_RATIO 1.0e6
|
||||||
|
|
||||||
/* Minimum and maximum allowed poll interval */
|
/* Minimum and maximum allowed poll interval */
|
||||||
#define MIN_POLL 0
|
#define MIN_POLL 0
|
||||||
#define MAX_POLL 24
|
#define MAX_POLL 24
|
||||||
@@ -513,9 +518,9 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
|||||||
if (result->presend_minpoll <= MAX_POLL && result->mode != MODE_CLIENT)
|
if (result->presend_minpoll <= MAX_POLL && result->mode != MODE_CLIENT)
|
||||||
result->presend_minpoll = MAX_POLL + 1;
|
result->presend_minpoll = MAX_POLL + 1;
|
||||||
|
|
||||||
result->max_delay = params->max_delay;
|
result->max_delay = CLAMP(0.0, params->max_delay, MAX_MAX_DELAY);
|
||||||
result->max_delay_ratio = params->max_delay_ratio;
|
result->max_delay_ratio = CLAMP(0.0, params->max_delay_ratio, MAX_MAX_DELAY_RATIO);
|
||||||
result->max_delay_dev_ratio = params->max_delay_dev_ratio;
|
result->max_delay_dev_ratio = CLAMP(0.0, params->max_delay_dev_ratio, MAX_MAX_DELAY_DEV_RATIO);
|
||||||
result->offset_correction = params->offset;
|
result->offset_correction = params->offset;
|
||||||
result->auto_offline = params->auto_offline;
|
result->auto_offline = params->auto_offline;
|
||||||
result->poll_target = params->poll_target;
|
result->poll_target = params->poll_target;
|
||||||
@@ -951,57 +956,63 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||||||
frequency all along */
|
frequency all along */
|
||||||
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
||||||
|
|
||||||
/* Prepare random bits which will be added to the transmit timestamp. */
|
do {
|
||||||
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
/* Prepare random bits which will be added to the transmit timestamp */
|
||||||
|
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
||||||
|
|
||||||
/* Transmit - this our local time right now! Also, we might need to
|
/* Transmit - this our local time right now! Also, we might need to
|
||||||
store this for our own use later, next time we receive a message
|
store this for our own use later, next time we receive a message
|
||||||
from the source we're sending to now. */
|
from the source we're sending to now. */
|
||||||
LCL_ReadCookedTime(&local_transmit, &local_transmit_err);
|
LCL_ReadCookedTime(&local_transmit, &local_transmit_err);
|
||||||
|
|
||||||
if (smooth_time)
|
if (smooth_time)
|
||||||
UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
|
UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
|
||||||
|
|
||||||
length = NTP_NORMAL_PACKET_LENGTH;
|
length = NTP_NORMAL_PACKET_LENGTH;
|
||||||
|
|
||||||
/* Authenticate the packet if needed */
|
/* Authenticate the packet */
|
||||||
|
|
||||||
if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
|
if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
|
||||||
/* Pre-compensate the transmit time by approx. how long it will
|
/* Pre-compensate the transmit time by approximately how long it will
|
||||||
take to generate the authentication data. */
|
take to generate the authentication data */
|
||||||
local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
|
local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
|
||||||
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
|
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
|
||||||
UTI_NormaliseTimespec(&local_transmit);
|
UTI_NormaliseTimespec(&local_transmit);
|
||||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||||
&message.transmit_ts, &ts_fuzz);
|
&message.transmit_ts, &ts_fuzz);
|
||||||
|
|
||||||
if (auth_mode == AUTH_SYMMETRIC) {
|
if (auth_mode == AUTH_SYMMETRIC) {
|
||||||
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
|
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
|
||||||
offsetof(NTP_Packet, auth_keyid),
|
offsetof(NTP_Packet, auth_keyid),
|
||||||
(unsigned char *)&message.auth_data,
|
(unsigned char *)&message.auth_data,
|
||||||
sizeof (message.auth_data));
|
sizeof (message.auth_data));
|
||||||
if (!auth_len) {
|
if (!auth_len) {
|
||||||
DEBUG_LOG(LOGF_NtpCore, "Could not generate auth data with key %"PRIu32, key_id);
|
DEBUG_LOG(LOGF_NtpCore, "Could not generate auth data with key %"PRIu32, key_id);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.auth_keyid = htonl(key_id);
|
||||||
|
mac_len = sizeof (message.auth_keyid) + auth_len;
|
||||||
|
|
||||||
|
/* Truncate MACs in NTPv4 packets to allow deterministic parsing
|
||||||
|
of extension fields (RFC 7822) */
|
||||||
|
if (version == 4 && mac_len > NTP_MAX_V4_MAC_LENGTH)
|
||||||
|
mac_len = NTP_MAX_V4_MAC_LENGTH;
|
||||||
|
|
||||||
|
length += mac_len;
|
||||||
|
} else if (auth_mode == AUTH_MSSNTP) {
|
||||||
|
/* MS-SNTP packets are signed (asynchronously) by ntp_signd */
|
||||||
|
return NSD_SignAndSendPacket(key_id, &message, where_to, from, length);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
message.auth_keyid = htonl(key_id);
|
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||||
mac_len = sizeof (message.auth_keyid) + auth_len;
|
&message.transmit_ts, &ts_fuzz);
|
||||||
|
|
||||||
/* Truncate MACs in NTPv4 packets to allow deterministic parsing
|
|
||||||
of extension fields (RFC 7822) */
|
|
||||||
if (version == 4 && mac_len > NTP_MAX_V4_MAC_LENGTH)
|
|
||||||
mac_len = NTP_MAX_V4_MAC_LENGTH;
|
|
||||||
|
|
||||||
length += mac_len;
|
|
||||||
} else if (auth_mode == AUTH_MSSNTP) {
|
|
||||||
/* MS-SNTP packets are signed (asynchronously) by ntp_signd */
|
|
||||||
return NSD_SignAndSendPacket(key_id, &message, where_to, from, length);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
/* Avoid sending messages with non-zero transmit timestamp equal to the
|
||||||
&message.transmit_ts, &ts_fuzz);
|
receive timestamp to allow reliable detection of the interleaved mode */
|
||||||
}
|
} while (!UTI_CompareNtp64(&message.transmit_ts, &message.receive_ts) &&
|
||||||
|
!UTI_IsZeroNtp64(&message.transmit_ts));
|
||||||
|
|
||||||
ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
|
ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL);
|
||||||
|
|
||||||
@@ -2106,9 +2117,9 @@ NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
|
|||||||
void
|
void
|
||||||
NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
|
NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
|
||||||
{
|
{
|
||||||
inst->max_delay = new_max_delay;
|
inst->max_delay = CLAMP(0.0, new_max_delay, MAX_MAX_DELAY);
|
||||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
|
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
|
||||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
|
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -2116,9 +2127,9 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
|
|||||||
void
|
void
|
||||||
NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
|
NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
|
||||||
{
|
{
|
||||||
inst->max_delay_ratio = new_max_delay_ratio;
|
inst->max_delay_ratio = CLAMP(0.0, new_max_delay_ratio, MAX_MAX_DELAY_RATIO);
|
||||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
|
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
|
||||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
|
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -2126,9 +2137,9 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
|
|||||||
void
|
void
|
||||||
NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio)
|
NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio)
|
||||||
{
|
{
|
||||||
inst->max_delay_dev_ratio = new_max_delay_dev_ratio;
|
inst->max_delay_dev_ratio = CLAMP(0.0, new_max_delay_dev_ratio, MAX_MAX_DELAY_DEV_RATIO);
|
||||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay dev ratio %f",
|
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay dev ratio %f",
|
||||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_dev_ratio);
|
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_dev_ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016
|
* Copyright (C) Miroslav Lichvar 2016-2017
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -187,6 +187,11 @@ accumulate_sample(time_t rtc, struct timespec *sys)
|
|||||||
discard_samples(NEW_FIRST_WHEN_FULL);
|
discard_samples(NEW_FIRST_WHEN_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Discard all samples if the RTC was stepped back (not our trim) */
|
||||||
|
if (n_samples > 0 && rtc_sec[n_samples - 1] - rtc >= rtc_trim[n_samples - 1]) {
|
||||||
|
DEBUG_LOG(LOGF_RtcLinux, "RTC samples discarded");
|
||||||
|
n_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Always use most recent sample as reference */
|
/* Always use most recent sample as reference */
|
||||||
/* use sample only if n_sample is not negative*/
|
/* use sample only if n_sample is not negative*/
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ void
|
|||||||
SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *now)
|
SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *now)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
struct timespec ago;
|
struct timespec last_sample_time;
|
||||||
|
|
||||||
if (inst->n_samples > 0) {
|
if (inst->n_samples > 0) {
|
||||||
i = get_runsbuf_index(inst, inst->n_samples - 1);
|
i = get_runsbuf_index(inst, inst->n_samples - 1);
|
||||||
@@ -938,8 +938,10 @@ SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *no
|
|||||||
report->latest_meas_err = 0.5*inst->root_delays[j] + inst->root_dispersions[j];
|
report->latest_meas_err = 0.5*inst->root_delays[j] + inst->root_dispersions[j];
|
||||||
report->stratum = inst->strata[j];
|
report->stratum = inst->strata[j];
|
||||||
|
|
||||||
UTI_DiffTimespecs(&ago, now, &inst->sample_times[i]);
|
/* Align the sample time to reduce the leak of the receive timestamp */
|
||||||
report->latest_meas_ago = ago.tv_sec;
|
last_sample_time = inst->sample_times[i];
|
||||||
|
last_sample_time.tv_nsec = 0;
|
||||||
|
report->latest_meas_ago = UTI_DiffTimespecsToDouble(now, &last_sample_time);
|
||||||
} else {
|
} else {
|
||||||
report->latest_meas_ago = (uint32_t)-1;
|
report->latest_meas_ago = (uint32_t)-1;
|
||||||
report->orig_latest_meas = 0;
|
report->orig_latest_meas = 0;
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ set_sync_status(int synchronised, double est_error, double max_error)
|
|||||||
txc.esterror = est_error * 1.0e6;
|
txc.esterror = est_error * 1.0e6;
|
||||||
txc.maxerror = max_error * 1.0e6;
|
txc.maxerror = max_error * 1.0e6;
|
||||||
|
|
||||||
SYS_Timex_Adjust(&txc, 1);
|
if (SYS_Timex_Adjust(&txc, 1) < 0)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ time_offset=-10
|
|||||||
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
|
||||||
max_sync_time=8500
|
max_sync_time=9000
|
||||||
|
|
||||||
run_test || test_fail
|
run_test || test_fail
|
||||||
check_chronyd_exit || test_fail
|
check_chronyd_exit || test_fail
|
||||||
|
|||||||
296
test/unit/ntp_core.c
Normal file
296
test/unit/ntp_core.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Miroslav Lichvar 2017
|
||||||
|
*
|
||||||
|
* 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 <cmdparse.h>
|
||||||
|
#include <conf.h>
|
||||||
|
#include <keys.h>
|
||||||
|
#include <ntp_io.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <local.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
static struct timespec current_time;
|
||||||
|
static NTP_Receive_Buffer req_buffer, res_buffer;
|
||||||
|
static int req_length, res_length;
|
||||||
|
|
||||||
|
#define NIO_OpenServerSocket(addr) ((addr)->ip_addr.family != IPADDR_UNSPEC ? 100 : 0)
|
||||||
|
#define NIO_CloseServerSocket(fd) assert(fd == 100)
|
||||||
|
#define NIO_OpenClientSocket(addr) ((addr)->ip_addr.family != IPADDR_UNSPEC ? 101 : 0)
|
||||||
|
#define NIO_CloseClientSocket(fd) assert(fd == 101)
|
||||||
|
#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_AddTimeoutInClass(delay, separation, randomness, class, handler, arg) \
|
||||||
|
add_timeout_in_class(delay, separation, randomness, class, handler, arg)
|
||||||
|
#define SCH_RemoveTimeout(id) assert(!id || id == 102)
|
||||||
|
#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 SRC_UpdateReachability(inst, reach)
|
||||||
|
#define SRC_ResetReachability(inst)
|
||||||
|
|
||||||
|
static SCH_TimeoutID
|
||||||
|
add_timeout_in_class(double min_delay, double separation, double randomness,
|
||||||
|
SCH_TimeoutClass class, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
|
||||||
|
{
|
||||||
|
return 102;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <ntp_core.c>
|
||||||
|
|
||||||
|
static NCR_Instance inst;
|
||||||
|
|
||||||
|
static void
|
||||||
|
advance_time(double x)
|
||||||
|
{
|
||||||
|
UTI_AddDoubleToTimespec(¤t_time, x, ¤t_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_request(void)
|
||||||
|
{
|
||||||
|
NTP_Local_Address local_addr;
|
||||||
|
NTP_Local_Timestamp local_ts;
|
||||||
|
uint32_t prev_tx_count;
|
||||||
|
|
||||||
|
prev_tx_count = inst->report.total_tx_count;
|
||||||
|
|
||||||
|
transmit_timeout(inst);
|
||||||
|
TEST_CHECK(!inst->valid_rx);
|
||||||
|
TEST_CHECK(!inst->updated_timestamps);
|
||||||
|
TEST_CHECK(prev_tx_count + 1 == inst->report.total_tx_count);
|
||||||
|
|
||||||
|
advance_time(1e-4);
|
||||||
|
|
||||||
|
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||||
|
local_addr.sock_fd = 101;
|
||||||
|
local_ts.ts = current_time;
|
||||||
|
local_ts.err = 0.0;
|
||||||
|
local_ts.source = NTP_TS_DAEMON;
|
||||||
|
|
||||||
|
NCR_ProcessTxKnown(inst, &local_addr, &local_ts, &req_buffer.ntp_pkt, req_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_response(int interleaved, int authenticated, int allow_update, int valid_ts, int valid_auth)
|
||||||
|
{
|
||||||
|
NTP_Packet *req, *res;
|
||||||
|
|
||||||
|
req = &req_buffer.ntp_pkt;
|
||||||
|
res = &res_buffer.ntp_pkt;
|
||||||
|
|
||||||
|
TEST_CHECK(req_length >= NTP_NORMAL_PACKET_LENGTH);
|
||||||
|
|
||||||
|
res->lvm = NTP_LVM(LEAP_Normal, NTP_LVM_TO_VERSION(req->lvm),
|
||||||
|
NTP_LVM_TO_MODE(req->lvm) == MODE_CLIENT ? MODE_SERVER : MODE_ACTIVE);
|
||||||
|
res->stratum = 1;
|
||||||
|
res->poll = req->poll;
|
||||||
|
res->precision = -20;
|
||||||
|
res->root_delay = UTI_DoubleToNtp32(0.1);
|
||||||
|
res->root_dispersion = UTI_DoubleToNtp32(0.1);
|
||||||
|
res->reference_id = 0;
|
||||||
|
UTI_ZeroNtp64(&res->reference_ts);
|
||||||
|
res->originate_ts = interleaved ? req->receive_ts : req->transmit_ts;
|
||||||
|
|
||||||
|
advance_time(TST_GetRandomDouble(1e-4, 1e-2));
|
||||||
|
UTI_TimespecToNtp64(¤t_time, &res->receive_ts, NULL);
|
||||||
|
advance_time(TST_GetRandomDouble(-1e-4, 1e-3));
|
||||||
|
UTI_TimespecToNtp64(¤t_time, &res->transmit_ts, NULL);
|
||||||
|
advance_time(TST_GetRandomDouble(1e-4, 1e-2));
|
||||||
|
|
||||||
|
if (!valid_ts) {
|
||||||
|
switch (random() % (allow_update ? 4 : 5)) {
|
||||||
|
case 0:
|
||||||
|
res->originate_ts.hi = random();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
res->originate_ts.lo = random();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
UTI_ZeroNtp64(&res->originate_ts);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
UTI_ZeroNtp64(&res->receive_ts);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
UTI_ZeroNtp64(&res->transmit_ts);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authenticated) {
|
||||||
|
res->auth_keyid = req->auth_keyid;
|
||||||
|
KEY_GenerateAuth(ntohl(res->auth_keyid), (unsigned char *)res, NTP_NORMAL_PACKET_LENGTH,
|
||||||
|
res->auth_data, 16);
|
||||||
|
res_length = NTP_NORMAL_PACKET_LENGTH + 4 + 16;
|
||||||
|
} else {
|
||||||
|
res_length = NTP_NORMAL_PACKET_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid_auth) {
|
||||||
|
switch (random() % 3) {
|
||||||
|
case 0:
|
||||||
|
res->auth_keyid++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
res->auth_data[random() % 16]++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
res_length = NTP_NORMAL_PACKET_LENGTH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_response(int valid, int updated)
|
||||||
|
{
|
||||||
|
NTP_Local_Address local_addr;
|
||||||
|
NTP_Local_Timestamp local_ts;
|
||||||
|
NTP_Packet *res;
|
||||||
|
uint32_t prev_rx_count, prev_valid_count;
|
||||||
|
struct timespec prev_rx_ts;
|
||||||
|
int prev_open_socket;
|
||||||
|
|
||||||
|
res = &res_buffer.ntp_pkt;
|
||||||
|
|
||||||
|
local_addr.ip_addr.family = IPADDR_UNSPEC;
|
||||||
|
local_addr.sock_fd = NTP_LVM_TO_MODE(res->lvm) == MODE_ACTIVE ? 100 : 101;
|
||||||
|
local_ts.ts = current_time;
|
||||||
|
local_ts.err = 0.0;
|
||||||
|
local_ts.source = NTP_TS_DAEMON;
|
||||||
|
|
||||||
|
prev_rx_count = inst->report.total_rx_count;
|
||||||
|
prev_valid_count = inst->report.total_valid_count;
|
||||||
|
prev_rx_ts = inst->local_rx.ts;
|
||||||
|
prev_open_socket = inst->local_addr.sock_fd != INVALID_SOCK_FD;
|
||||||
|
|
||||||
|
NCR_ProcessRxKnown(inst, &local_addr, &local_ts, res, res_length);
|
||||||
|
|
||||||
|
if (prev_open_socket)
|
||||||
|
TEST_CHECK(prev_rx_count + 1 == inst->report.total_rx_count);
|
||||||
|
else
|
||||||
|
TEST_CHECK(prev_rx_count == inst->report.total_rx_count);
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
TEST_CHECK(prev_valid_count + 1 == inst->report.total_valid_count);
|
||||||
|
else
|
||||||
|
TEST_CHECK(prev_valid_count == inst->report.total_valid_count);
|
||||||
|
|
||||||
|
if (updated)
|
||||||
|
TEST_CHECK(UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
||||||
|
else
|
||||||
|
TEST_CHECK(!UTI_CompareTimespecs(&inst->local_rx.ts, &prev_rx_ts));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_unit(void)
|
||||||
|
{
|
||||||
|
char source_line[] = "127.0.0.1";
|
||||||
|
char conf[][100] = {
|
||||||
|
"port 0",
|
||||||
|
"keyfile ntp_core.keys"
|
||||||
|
};
|
||||||
|
int i, j, interleaved, authenticated, valid, updated, has_updated;
|
||||||
|
CPS_NTP_Source source;
|
||||||
|
NTP_Remote_Address remote_addr;
|
||||||
|
|
||||||
|
CNF_Initialise(0);
|
||||||
|
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
|
||||||
|
CNF_ParseLine(NULL, i + 1, conf[i]);
|
||||||
|
|
||||||
|
LCL_Initialise();
|
||||||
|
TST_RegisterDummyDrivers();
|
||||||
|
SCH_Initialise();
|
||||||
|
SRC_Initialise();
|
||||||
|
NIO_Initialise(IPADDR_UNSPEC);
|
||||||
|
NCR_Initialise();
|
||||||
|
REF_Initialise();
|
||||||
|
KEY_Initialise();
|
||||||
|
|
||||||
|
for (i = 0; i < 1000; i++) {
|
||||||
|
CPS_ParseNTPSourceAdd(source_line, &source);
|
||||||
|
if (random() % 2)
|
||||||
|
source.params.interleaved = 1;
|
||||||
|
if (random() % 2)
|
||||||
|
source.params.authkey = 1;
|
||||||
|
|
||||||
|
UTI_ZeroTimespec(¤t_time);
|
||||||
|
advance_time(TST_GetRandomDouble(1.0, 1e9));
|
||||||
|
|
||||||
|
TST_GetRandomAddress(&remote_addr.ip_addr, IPADDR_UNSPEC, -1);
|
||||||
|
remote_addr.port = 123;
|
||||||
|
|
||||||
|
inst = NCR_GetInstance(&remote_addr, random() % 2 ? NTP_SERVER : NTP_PEER, &source.params);
|
||||||
|
NCR_StartInstance(inst);
|
||||||
|
has_updated = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < 50; j++) {
|
||||||
|
DEBUG_LOG(0, "iteration %d, %d", i, j);
|
||||||
|
|
||||||
|
interleaved = random() % 2;
|
||||||
|
authenticated = random() % 2;
|
||||||
|
valid = (!interleaved || (source.params.interleaved && has_updated)) &&
|
||||||
|
(!source.params.authkey || authenticated);
|
||||||
|
updated = (valid || inst->mode == MODE_ACTIVE) &&
|
||||||
|
(!source.params.authkey || authenticated);
|
||||||
|
has_updated = has_updated || updated;
|
||||||
|
|
||||||
|
send_request();
|
||||||
|
|
||||||
|
send_response(interleaved, authenticated, 1, 0, 1);
|
||||||
|
process_response(0, inst->mode == MODE_CLIENT ? 0 : updated);
|
||||||
|
|
||||||
|
if (source.params.authkey) {
|
||||||
|
send_response(interleaved, authenticated, 1, 1, 0);
|
||||||
|
process_response(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
|
process_response(valid, updated);
|
||||||
|
process_response(0, 0);
|
||||||
|
|
||||||
|
advance_time(-1.0);
|
||||||
|
|
||||||
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
|
process_response(0, 0);
|
||||||
|
|
||||||
|
advance_time(1.0);
|
||||||
|
|
||||||
|
send_response(interleaved, authenticated, 1, 1, 1);
|
||||||
|
process_response(0, inst->mode == MODE_CLIENT ? 0 : updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
NCR_DestroyInstance(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
KEY_Finalise();
|
||||||
|
REF_Finalise();
|
||||||
|
NCR_Finalise();
|
||||||
|
NIO_Finalise();
|
||||||
|
SRC_Finalise();
|
||||||
|
SCH_Finalise();
|
||||||
|
LCL_Finalise();
|
||||||
|
CNF_Finalise();
|
||||||
|
}
|
||||||
2
test/unit/ntp_core.keys
Normal file
2
test/unit/ntp_core.keys
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
1 MD5 HEX:38979C567358C0896F4D9D459A3C8B8478654579
|
||||||
|
2 MD5 HEX:38979C567358C0896F4D9D459A3C8B8478654579
|
||||||
@@ -74,6 +74,14 @@ void test_unit(void) {
|
|||||||
TEST_CHECK(!UTI_IsZeroTimespec(&ts));
|
TEST_CHECK(!UTI_IsZeroTimespec(&ts));
|
||||||
TEST_CHECK(!UTI_IsZeroNtp64(&ntp_ts));
|
TEST_CHECK(!UTI_IsZeroNtp64(&ntp_ts));
|
||||||
|
|
||||||
|
ntp_ts.hi = 0;
|
||||||
|
ntp_ts.lo = 0;
|
||||||
|
|
||||||
|
UTI_Ntp64ToTimespec(&ntp_ts, &ts);
|
||||||
|
TEST_CHECK(UTI_IsZeroTimespec(&ts));
|
||||||
|
UTI_TimespecToNtp64(&ts, &ntp_ts, NULL);
|
||||||
|
TEST_CHECK(UTI_IsZeroNtp64(&ntp_ts));
|
||||||
|
|
||||||
ntp_fuzz.hi = htonl(1);
|
ntp_fuzz.hi = htonl(1);
|
||||||
ntp_fuzz.lo = htonl(3);
|
ntp_fuzz.lo = htonl(3);
|
||||||
ntp_ts.hi = htonl(1);
|
ntp_ts.hi = htonl(1);
|
||||||
|
|||||||
7
util.c
7
util.c
@@ -754,8 +754,11 @@ UTI_Ntp64ToTimespec(NTP_int64 *src, struct timespec *dest)
|
|||||||
{
|
{
|
||||||
uint32_t ntp_sec, ntp_frac;
|
uint32_t ntp_sec, ntp_frac;
|
||||||
|
|
||||||
/* As yet, there is no need to check for zero - all processing that
|
/* Zero is a special value */
|
||||||
has to detect that case is in the NTP layer */
|
if (UTI_IsZeroNtp64(src)) {
|
||||||
|
UTI_ZeroTimespec(dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ntp_sec = ntohl(src->hi);
|
ntp_sec = ntohl(src->hi);
|
||||||
ntp_frac = ntohl(src->lo);
|
ntp_frac = ntohl(src->lo);
|
||||||
|
|||||||
Reference in New Issue
Block a user