Compare commits

...

18 Commits

Author SHA1 Message Date
Miroslav Lichvar
16519ee2cc doc: update NEWS 2016-12-15 13:47:41 +01:00
Miroslav Lichvar
50022e9286 clientlog: enable NTP response rate limiting by default
Change the default interval of both NTP and command rate limiting to -10
(1024 packets per second) and the burst to 16. The default NTP leak is 2
(rate limiting is enabled by default) and the default command leak is 0
(rate limiting is disabled by default).
2016-12-15 13:47:41 +01:00
Miroslav Lichvar
5059019535 clientlog: randomize alignment of log timestamps 2016-12-15 13:47:41 +01:00
Miroslav Lichvar
c6a38f5069 clientlog: allow very short rate limiting intervals
Support negative token shift to allow coarse rate limiting with
intervals down to -19.
2016-12-15 13:47:41 +01:00
Miroslav Lichvar
11ed197663 configure: don't use recvmmsg() on FreeBSD
Don't try recvmmsg() on FreeBSD, at least for now. It is broken on
FreeBSD 11.0 and it's just a wrapper around recvmsg().
2016-12-15 13:47:41 +01:00
Miroslav Lichvar
5634e6b963 doc: improve hwtimestamp description 2016-12-14 16:19:35 +01:00
Miroslav Lichvar
db312a5ff6 ntp: allow wildcard in hwtimestamp directive
If "*" was specified, use getifaddrs() to get a list of all interfaces,
and try to enable HW timestamping on all of them.
2016-12-14 16:19:35 +01:00
Miroslav Lichvar
88c31b3785 client: improve ntpdata output 2016-12-14 16:19:35 +01:00
Miroslav Lichvar
967f3e4f77 client: don't require address in ntpdata command
If no address is specified, use the SOURCE_DATA command to get addresses
of NTP sources, and request NTP_DATA for all of them.
2016-12-14 16:19:35 +01:00
Miroslav Lichvar
2e311d1766 sourcestats: add upper bound for skew 2016-12-14 16:19:35 +01:00
Miroslav Lichvar
11f7cc0507 examples: avoid Unix domain socket in chrony-wait service
Use the -h option to force chronyc to use internet socket instead of
Unix domain as the access to the socket may be blocked by SELinux and
trying to open it generates SELinux warnings.
2016-12-13 12:57:25 +01:00
Miroslav Lichvar
a4f28892a5 cmdmon: update protocol changelog 2016-12-13 12:57:25 +01:00
Miroslav Lichvar
5bc53741be sourcestats: add lower bound for std dev used for weighting 2016-12-13 12:57:25 +01:00
Miroslav Lichvar
95a4f33265 sourcestats: save asymmetry run in dump files
This allows the asymmetry correction to be applied right after restart.
2016-12-13 12:57:25 +01:00
Miroslav Lichvar
fac1093ebf cmdmon: add reserved fields to ntpdata reply
This might be useful if ntpdata is changed to not require authorization
and new fields need to be added without breaking compatibility.
2016-12-13 12:57:25 +01:00
Miroslav Lichvar
1b1384ccaa nameserv: set CLOEXEC flag on pipe file descriptors 2016-12-13 12:57:25 +01:00
Miroslav Lichvar
0c9a19ded5 stubs: rework emulation of asynchronous resolver to use pipes
With a larger number of configured servers, the handler of the emulated
resolver repeatedly scheduled timeout of zero, which triggered the
infinite loop detection in the scheduler and caused abort. This bug was
introduced in commit 967e358dbc.

Rework the code to use pipes instead of timeouts to avoid this problem.
2016-12-13 12:57:25 +01:00
Miroslav Lichvar
b7bd7469b7 ntp: disable maxdelayratio in interleaved/symmetric mode
It's too unreliable and the maxdelaydevratio test should work better
anyway.
2016-12-13 12:57:24 +01:00
16 changed files with 314 additions and 167 deletions

7
NEWS
View File

@@ -16,14 +16,21 @@ Enhancements
* Add -t option to chronyd to exit after specified time * Add -t option to chronyd to exit after specified time
* Add partial protection against replay attacks on symmetric mode * Add partial protection against replay attacks on symmetric mode
* Don't reset polling interval when switching sources to online state * Don't reset polling interval when switching sources to online state
* Enable NTP response rate limiting by default
(1024 packets per second per IP address and 25% leak)
* Improve maximum server throughput on Linux and NetBSD * Improve maximum server throughput on Linux and NetBSD
* Remove dump files after start * Remove dump files after start
* Add tab-completion to chronyc with libedit/readline * Add tab-completion to chronyc with libedit/readline
* Add ntpdata command to print details about NTP measurements * Add ntpdata command to print details about NTP measurements
* Allow all source options to be set in add server/peer command
* Indicate truncated addresses/hostnames in chronyc output * Indicate truncated addresses/hostnames in chronyc output
* Print reference IDs as hexadecimal numbers to avoid confusion with * Print reference IDs as hexadecimal numbers to avoid confusion with
IPv4 addresses IPv4 addresses
Bug fixes
---------
* Fix crash with disabled asynchronous name resolving
New in version 2.4.1 New in version 2.4.1
==================== ====================

View File

@@ -362,8 +362,8 @@ 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), new flags in NTP source request and report, (using new request/reply types), new fields and flags in NTP source request
new commands: refresh, serverstats and report, new commands: ntpdata, refresh, serverstats
*/ */
#define PROTO_VERSION_NUMBER 6 #define PROTO_VERSION_NUMBER 6
@@ -672,6 +672,7 @@ typedef struct {
uint32_t total_tx_count; uint32_t total_tx_count;
uint32_t total_rx_count; uint32_t total_rx_count;
uint32_t total_valid_count; uint32_t total_valid_count;
uint32_t reserved[4];
int32_t EOR; int32_t EOR;
} RPY_NTPData; } RPY_NTPData;

View File

@@ -1191,7 +1191,7 @@ give_help(void)
"\0\0" "\0\0"
"NTP sources:\0\0" "NTP sources:\0\0"
"activity\0Check how many NTP sources are online/offline\0" "activity\0Check how many NTP sources are online/offline\0"
"ntpdata <address>\0Display information about last valid measurement\0" "ntpdata [<address>]\0Display information about last valid measurement\0"
"add server <address> [options]\0Add new NTP server\0" "add server <address> [options]\0Add new NTP server\0"
"add peer <address> [options]\0Add new NTP peer\0" "add peer <address> [options]\0Add new NTP peer\0"
"delete <address>\0Remove server or peer\0" "delete <address>\0Remove server or peer\0"
@@ -2244,11 +2244,39 @@ process_cmd_ntpdata(char *line)
CMD_Reply reply; CMD_Reply reply;
IPAddr remote_addr, local_addr; IPAddr remote_addr, local_addr;
struct timespec ref_time; struct timespec ref_time;
uint32_t i, n_sources;
uint16_t mode;
int specified_addr;
if (*line) {
specified_addr = 1;
n_sources = 1;
} else {
specified_addr = 0;
request.command = htons(REQ_N_SOURCES);
if (!request_reply(&request, &reply, RPY_N_SOURCES, 0))
return 0;
n_sources = ntohl(reply.data.n_sources.n_sources);
}
for (i = 0; i < n_sources; i++) {
if (specified_addr) {
if (DNS_Name2IPAddress(line, &remote_addr, 1) != DNS_Success) { if (DNS_Name2IPAddress(line, &remote_addr, 1) != DNS_Success) {
LOG(LOGS_ERR, LOGF_Client, "Could not get address for hostname"); LOG(LOGS_ERR, LOGF_Client, "Could not get address for hostname");
return 0; return 0;
} }
} else {
request.command = htons(REQ_SOURCE_DATA);
request.data.source_data.index = htonl(i);
if (!request_reply(&request, &reply, RPY_SOURCE_DATA, 0))
return 0;
mode = ntohs(reply.data.source_data.mode);
if (mode != RPY_SD_MD_CLIENT && mode != RPY_SD_MD_PEER)
continue;
UTI_IPNetworkToHost(&reply.data.source_data.ip_addr, &remote_addr);
}
request.command = htons(REQ_NTP_DATA); request.command = htons(REQ_NTP_DATA);
UTI_IPHostToNetwork(&remote_addr, &request.data.ntp_data.ip_addr); UTI_IPHostToNetwork(&remote_addr, &request.data.ntp_data.ip_addr);
@@ -2259,6 +2287,9 @@ process_cmd_ntpdata(char *line)
UTI_IPNetworkToHost(&reply.data.ntp_data.local_addr, &local_addr); UTI_IPNetworkToHost(&reply.data.ntp_data.local_addr, &local_addr);
UTI_TimespecNetworkToHost(&reply.data.ntp_data.ref_time, &ref_time); UTI_TimespecNetworkToHost(&reply.data.ntp_data.ref_time, &ref_time);
if (!specified_addr && !csv_mode)
printf("\n");
print_report("Remote address : %s (%R)\n" print_report("Remote address : %s (%R)\n"
"Remote port : %u\n" "Remote port : %u\n"
"Local address : %s (%R)\n" "Local address : %s (%R)\n"
@@ -2266,8 +2297,8 @@ process_cmd_ntpdata(char *line)
"Version : %u\n" "Version : %u\n"
"Mode : %M\n" "Mode : %M\n"
"Stratum : %u\n" "Stratum : %u\n"
"Poll : %d\n" "Poll interval : %d (%.0f seconds)\n"
"Precision : %.9f seconds\n" "Precision : %d (%.9f seconds)\n"
"Root delay : %.6f seconds\n" "Root delay : %.6f seconds\n"
"Root dispersion : %.6f seconds\n" "Root dispersion : %.6f seconds\n"
"Reference ID : %R\n" "Reference ID : %R\n"
@@ -2290,7 +2321,8 @@ process_cmd_ntpdata(char *line)
UTI_IPToString(&local_addr), (unsigned long)UTI_IPToRefid(&local_addr), UTI_IPToString(&local_addr), (unsigned long)UTI_IPToRefid(&local_addr),
reply.data.ntp_data.leap, reply.data.ntp_data.version, reply.data.ntp_data.leap, reply.data.ntp_data.version,
reply.data.ntp_data.mode, reply.data.ntp_data.stratum, reply.data.ntp_data.mode, reply.data.ntp_data.stratum,
reply.data.ntp_data.poll, UTI_Log2ToDouble(reply.data.ntp_data.precision), reply.data.ntp_data.poll, UTI_Log2ToDouble(reply.data.ntp_data.poll),
reply.data.ntp_data.precision, UTI_Log2ToDouble(reply.data.ntp_data.precision),
UTI_FloatNetworkToHost(reply.data.ntp_data.root_delay), UTI_FloatNetworkToHost(reply.data.ntp_data.root_delay),
UTI_FloatNetworkToHost(reply.data.ntp_data.root_dispersion), UTI_FloatNetworkToHost(reply.data.ntp_data.root_dispersion),
(unsigned long)ntohl(reply.data.ntp_data.ref_id), &ref_time, (unsigned long)ntohl(reply.data.ntp_data.ref_id), &ref_time,
@@ -2309,6 +2341,7 @@ process_cmd_ntpdata(char *line)
(unsigned long)ntohl(reply.data.ntp_data.total_rx_count), (unsigned long)ntohl(reply.data.ntp_data.total_rx_count),
(unsigned long)ntohl(reply.data.ntp_data.total_valid_count), (unsigned long)ntohl(reply.data.ntp_data.total_valid_count),
REPORT_END); REPORT_END);
}
return 1; return 1;
} }

View File

@@ -86,6 +86,10 @@ static unsigned int max_slots;
#define TS_FRAC 4 #define TS_FRAC 4
#define INVALID_TS 0 #define INVALID_TS 0
/* Static offset included in conversion to the fixed-point timestamps to
randomise their alignment */
static uint32_t ts_offset;
/* Request rates are saved in the record as 8-bit scaled log2 values */ /* Request rates are saved in the record as 8-bit scaled log2 values */
#define RATE_SCALE 4 #define RATE_SCALE 4
#define MIN_RATE (-14 * RATE_SCALE) #define MIN_RATE (-14 * RATE_SCALE)
@@ -95,7 +99,7 @@ static unsigned int max_slots;
number of tokens spent on response are determined from configured number of tokens spent on response are determined from configured
minimum inverval between responses (in log2) and burst length. */ minimum inverval between responses (in log2) and burst length. */
#define MIN_LIMIT_INTERVAL (-TS_FRAC) #define MIN_LIMIT_INTERVAL (-15 - TS_FRAC)
#define MAX_LIMIT_INTERVAL 12 #define MAX_LIMIT_INTERVAL 12
#define MIN_LIMIT_BURST 1 #define MIN_LIMIT_BURST 1
#define MAX_LIMIT_BURST 255 #define MAX_LIMIT_BURST 255
@@ -105,7 +109,8 @@ static uint16_t max_cmd_tokens;
static uint16_t ntp_tokens_per_packet; static uint16_t ntp_tokens_per_packet;
static uint16_t cmd_tokens_per_packet; static uint16_t cmd_tokens_per_packet;
/* Reduction of token rates to avoid overflow of 16-bit counters */ /* Reduction of token rates to avoid overflow of 16-bit counters. Negative
shift is used for coarse limiting with intervals shorter than -TS_FRAC. */
static int ntp_token_shift; static int ntp_token_shift;
static int cmd_token_shift; static int cmd_token_shift;
@@ -114,7 +119,7 @@ static int cmd_token_shift;
prevent an attacker sending requests with spoofed source address prevent an attacker sending requests with spoofed source address
from blocking responses to the address completely. */ from blocking responses to the address completely. */
#define MIN_LEAK_RATE 1 #define MIN_LEAK_RATE 0
#define MAX_LEAK_RATE 4 #define MAX_LEAK_RATE 4
static int ntp_leak_rate; static int ntp_leak_rate;
@@ -133,6 +138,8 @@ static uint32_t total_ntp_drops;
static uint32_t total_cmd_drops; static uint32_t total_cmd_drops;
static uint32_t total_record_drops; static uint32_t total_record_drops;
#define NSEC_PER_SEC 1000000000U
/* ================================================== */ /* ================================================== */
static int expand_hashtable(void); static int expand_hashtable(void);
@@ -271,11 +278,18 @@ set_bucket_params(int interval, int burst, uint16_t *max_tokens,
interval = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL); interval = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
burst = CLAMP(MIN_LIMIT_BURST, burst, MAX_LIMIT_BURST); burst = CLAMP(MIN_LIMIT_BURST, burst, MAX_LIMIT_BURST);
/* Find smallest shift with which the maximum number fits in 16 bits */ if (interval >= -TS_FRAC) {
/* Find the smallest shift with which the maximum number fits in 16 bits */
for (*token_shift = 0; *token_shift < interval + TS_FRAC; (*token_shift)++) { for (*token_shift = 0; *token_shift < interval + TS_FRAC; (*token_shift)++) {
if (burst << (TS_FRAC + interval - *token_shift) < 1U << 16) if (burst << (TS_FRAC + interval - *token_shift) < 1U << 16)
break; break;
} }
} else {
/* Coarse rate limiting */
*token_shift = interval + TS_FRAC;
*tokens_per_packet = 1;
burst = MAX(1U << -*token_shift, burst);
}
*tokens_per_packet = 1U << (TS_FRAC + interval - *token_shift); *tokens_per_packet = 1U << (TS_FRAC + interval - *token_shift);
*max_tokens = *tokens_per_packet * burst; *max_tokens = *tokens_per_packet * burst;
@@ -291,29 +305,19 @@ CLG_Initialise(void)
{ {
int interval, burst, leak_rate; int interval, burst, leak_rate;
max_ntp_tokens = max_cmd_tokens = 0; CNF_GetNTPRateLimit(&interval, &burst, &leak_rate);
ntp_tokens_per_packet = cmd_tokens_per_packet = 0;
ntp_token_shift = cmd_token_shift = 0;
ntp_leak_rate = cmd_leak_rate = 0;
if (CNF_GetNTPRateLimit(&interval, &burst, &leak_rate)) {
set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet, set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet,
&ntp_token_shift); &ntp_token_shift);
ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE); ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
}
if (CNF_GetCommandRateLimit(&interval, &burst, &leak_rate)) { CNF_GetCommandRateLimit(&interval, &burst, &leak_rate);
set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet, set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet,
&cmd_token_shift); &cmd_token_shift);
cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE); cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
}
active = !CNF_GetNoClientLog(); active = !CNF_GetNoClientLog();
if (!active) { if (!active)
if (ntp_leak_rate || cmd_leak_rate)
LOG_FATAL(LOGF_ClientLog, "ratelimit cannot be used with noclientlog");
return; return;
}
/* Calculate the maximum number of slots that can be allocated in the /* Calculate the maximum number of slots that can be allocated in the
configured memory limit. Take into account expanding of the hash configured memory limit. Take into account expanding of the hash
@@ -325,6 +329,9 @@ CLG_Initialise(void)
records = NULL; records = NULL;
expand_hashtable(); expand_hashtable();
UTI_GetRandomBytes(&ts_offset, sizeof (ts_offset));
ts_offset %= NSEC_PER_SEC / (1U << TS_FRAC);
} }
/* ================================================== */ /* ================================================== */
@@ -345,6 +352,12 @@ get_ts_from_timespec(struct timespec *ts)
{ {
uint32_t sec = ts->tv_sec, nsec = ts->tv_nsec; uint32_t sec = ts->tv_sec, nsec = ts->tv_nsec;
nsec += ts_offset;
if (nsec >= NSEC_PER_SEC) {
nsec -= NSEC_PER_SEC;
sec++;
}
/* This is fast and accurate enough */ /* This is fast and accurate enough */
return sec << TS_FRAC | (140740U * (nsec >> 15)) >> (32 - TS_FRAC); return sec << TS_FRAC | (140740U * (nsec >> 15)) >> (32 - TS_FRAC);
} }
@@ -369,7 +382,12 @@ update_record(struct timespec *now, uint32_t *last_hit, uint32_t *hits,
if (prev_hit == INVALID_TS || (int32_t)interval < 0) if (prev_hit == INVALID_TS || (int32_t)interval < 0)
return; return;
if (token_shift >= 0)
new_tokens = (now_ts >> token_shift) - (prev_hit >> token_shift); new_tokens = (now_ts >> token_shift) - (prev_hit >> token_shift);
else if (now_ts - prev_hit > max_tokens)
new_tokens = max_tokens;
else
new_tokens = (now_ts - prev_hit) << -token_shift;
*tokens = MIN(*tokens + new_tokens, max_tokens); *tokens = MIN(*tokens + new_tokens, max_tokens);
/* Convert the interval to scaled and rounded log2 */ /* Convert the interval to scaled and rounded log2 */
@@ -502,7 +520,7 @@ CLG_LimitNTPResponseRate(int index)
Record *record; Record *record;
int drop; int drop;
if (!ntp_tokens_per_packet) if (!ntp_leak_rate)
return 0; return 0;
record = ARR_GetElement(records, index); record = ARR_GetElement(records, index);
@@ -543,7 +561,7 @@ CLG_LimitCommandResponseRate(int index)
{ {
Record *record; Record *record;
if (!cmd_tokens_per_packet) if (!cmd_leak_rate)
return 0; return 0;
record = ARR_GetElement(records, index); record = ARR_GetElement(records, index);

View File

@@ -1232,6 +1232,7 @@ handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count); tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count); tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count); tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
} }
/* ================================================== */ /* ================================================== */

31
conf.c
View File

@@ -66,8 +66,7 @@ static void parse_log(char *);
static void parse_mailonchange(char *); static void parse_mailonchange(char *);
static void parse_makestep(char *); static void parse_makestep(char *);
static void parse_maxchange(char *); static void parse_maxchange(char *);
static void parse_ratelimit(char *line, int *enabled, int *interval, static void parse_ratelimit(char *line, int *interval, int *burst, int *leak);
int *burst, int *leak);
static void parse_refclock(char *); static void parse_refclock(char *);
static void parse_smoothtime(char *); static void parse_smoothtime(char *);
static void parse_source(char *line, NTP_Source_Type type, int pool); static void parse_source(char *line, NTP_Source_Type type, int pool);
@@ -191,14 +190,12 @@ static char *ntp_signd_socket = NULL;
static char *pidfile; static char *pidfile;
/* Rate limiting parameters */ /* Rate limiting parameters */
static int ntp_ratelimit_enabled = 0; static int ntp_ratelimit_interval = -10;
static int ntp_ratelimit_interval = 3; static int ntp_ratelimit_burst = 16;
static int ntp_ratelimit_burst = 8; static int ntp_ratelimit_leak = 2;
static int ntp_ratelimit_leak = 3; static int cmd_ratelimit_interval = -10;
static int cmd_ratelimit_enabled = 0;
static int cmd_ratelimit_interval = 1;
static int cmd_ratelimit_burst = 16; static int cmd_ratelimit_burst = 16;
static int cmd_ratelimit_leak = 2; static int cmd_ratelimit_leak = 0;
/* Smoothing constants */ /* Smoothing constants */
static double smooth_max_freq = 0.0; /* in ppm */ static double smooth_max_freq = 0.0; /* in ppm */
@@ -455,8 +452,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
} else if (!strcasecmp(command, "cmdport")) { } else if (!strcasecmp(command, "cmdport")) {
parse_int(p, &cmd_port); parse_int(p, &cmd_port);
} else if (!strcasecmp(command, "cmdratelimit")) { } else if (!strcasecmp(command, "cmdratelimit")) {
parse_ratelimit(p, &cmd_ratelimit_enabled, &cmd_ratelimit_interval, parse_ratelimit(p, &cmd_ratelimit_interval, &cmd_ratelimit_burst, &cmd_ratelimit_leak);
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
} else if (!strcasecmp(command, "combinelimit")) { } else if (!strcasecmp(command, "combinelimit")) {
parse_double(p, &combine_limit); parse_double(p, &combine_limit);
} else if (!strcasecmp(command, "corrtimeratio")) { } else if (!strcasecmp(command, "corrtimeratio")) {
@@ -536,8 +532,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
} else if (!strcasecmp(command, "port")) { } else if (!strcasecmp(command, "port")) {
parse_int(p, &ntp_port); parse_int(p, &ntp_port);
} else if (!strcasecmp(command, "ratelimit")) { } else if (!strcasecmp(command, "ratelimit")) {
parse_ratelimit(p, &ntp_ratelimit_enabled, &ntp_ratelimit_interval, parse_ratelimit(p, &ntp_ratelimit_interval, &ntp_ratelimit_burst, &ntp_ratelimit_leak);
&ntp_ratelimit_burst, &ntp_ratelimit_leak);
} else if (!strcasecmp(command, "refclock")) { } else if (!strcasecmp(command, "refclock")) {
parse_refclock(p); parse_refclock(p);
} else if (!strcasecmp(command, "reselectdist")) { } else if (!strcasecmp(command, "reselectdist")) {
@@ -642,13 +637,11 @@ parse_source(char *line, NTP_Source_Type type, int pool)
/* ================================================== */ /* ================================================== */
static void static void
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak) parse_ratelimit(char *line, int *interval, int *burst, int *leak)
{ {
int n, val; int n, val;
char *opt; char *opt;
*enabled = 1;
while (*line) { while (*line) {
opt = line; opt = line;
line = CPS_SplitWord(line); line = CPS_SplitWord(line);
@@ -1830,22 +1823,20 @@ CNF_GetLockMemory(void)
/* ================================================== */ /* ================================================== */
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak) void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
{ {
*interval = ntp_ratelimit_interval; *interval = ntp_ratelimit_interval;
*burst = ntp_ratelimit_burst; *burst = ntp_ratelimit_burst;
*leak = ntp_ratelimit_leak; *leak = ntp_ratelimit_leak;
return ntp_ratelimit_enabled;
} }
/* ================================================== */ /* ================================================== */
int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak) void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak)
{ {
*interval = cmd_ratelimit_interval; *interval = cmd_ratelimit_interval;
*burst = cmd_ratelimit_burst; *burst = cmd_ratelimit_burst;
*leak = cmd_ratelimit_leak; *leak = cmd_ratelimit_leak;
return cmd_ratelimit_enabled;
} }
/* ================================================== */ /* ================================================== */

4
conf.h
View File

@@ -102,8 +102,8 @@ extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void); extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void); extern int CNF_GetLockMemory(void);
extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak); extern void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
extern int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak); extern void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only); extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2); extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);

10
configure vendored
View File

@@ -219,6 +219,7 @@ try_lockmem=0
feat_asyncdns=1 feat_asyncdns=1
feat_forcednsretry=1 feat_forcednsretry=1
try_clock_gettime=1 try_clock_gettime=1
try_recvmmsg=1
feat_timestamping=1 feat_timestamping=1
try_timestamping=0 try_timestamping=0
feat_ntp_signd=0 feat_ntp_signd=0
@@ -400,6 +401,9 @@ case $OPERATINGSYSTEM in
echo "Configuring for " $SYSTEM echo "Configuring for " $SYSTEM
;; ;;
FreeBSD) FreeBSD)
# recvmmsg() seems to be broken on FreeBSD 11.0 and it's just
# a wrapper around recvmsg()
try_recvmmsg=0
EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o" EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
add_def FREEBSD add_def FREEBSD
if [ $feat_droproot = "1" ]; then if [ $feat_droproot = "1" ]; then
@@ -629,15 +633,17 @@ fi
RECVMMSG_CODE=' RECVMMSG_CODE='
struct mmsghdr hdr; struct mmsghdr hdr;
return !recvmmsg(0, &hdr, 1, MSG_DONTWAIT, 0);' return !recvmmsg(0, &hdr, 1, MSG_DONTWAIT, 0);'
if test_code 'recvmmsg()' 'sys/socket.h' '' "$EXTRA_LIBS" "$RECVMMSG_CODE"; then if [ $try_recvmmsg = "1" ]; then
if test_code 'recvmmsg()' 'sys/socket.h' '' "$EXTRA_LIBS" "$RECVMMSG_CODE"; then
add_def HAVE_RECVMMSG add_def HAVE_RECVMMSG
else else
if test_code 'recvmmsg() with _GNU_SOURCE' 'sys/socket.h' '-D_GNU_SOURCE' \ if test_code 'recvmmsg() with _GNU_SOURCE' 'sys/socket.h' '-D_GNU_SOURCE' \
"$EXTRA_LIBS" "$RECVMMSG_CODE" "$EXTRA_LIBS" "$RECVMMSG_CODE"
then then
add_def _GNU_SOURCE add_def _GNU_SOURCE
add_def HAVE_RECVMMSG add_def HAVE_RECVMMSG
fi fi
fi
fi fi
if [ $feat_timestamping = "1" ] && [ $try_timestamping = "1" ] && if [ $feat_timestamping = "1" ] && [ $try_timestamping = "1" ] &&

View File

@@ -110,7 +110,8 @@ round-trip delay of 0.3 seconds or more should be ignored. The default value is
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. This option works
only in the *server* directive when not in the interleaved mode.
*maxdelaydevratio* _ratio_::: *maxdelaydevratio* _ratio_:::
If a measurement has a ratio of the increase in the round-trip delay from the If a measurement has a ratio of the increase in the round-trip delay from the
minimum delay amongst the previous measurements to the standard deviation of minimum delay amongst the previous measurements to the standard deviation of
@@ -1220,8 +1221,8 @@ source port used in NTP client requests can be set by the
<<acquisitionport,*acquisitionport*>> directive. <<acquisitionport,*acquisitionport*>> directive.
[[ratelimit]]*ratelimit* [_option_]...:: [[ratelimit]]*ratelimit* [_option_]...::
This directive enables response rate limiting for NTP packets. Its purpose is This directive configures response rate limiting for NTP packets. Its purpose
to reduce network traffic with misconfigured or broken NTP clients that are is to reduce network traffic with misconfigured or broken NTP clients that are
polling the server too frequently. The limits are applied to individual IP polling the server too frequently. The limits are applied to individual IP
addresses. If multiple clients share one IP address (e.g. multiple hosts behind addresses. If multiple clients share one IP address (e.g. multiple hosts behind
NAT), the sum of their traffic will be limited. If a client that increases its NAT), the sum of their traffic will be limited. If a client that increases its
@@ -1236,33 +1237,40 @@ in any order):
+ +
*interval*::: *interval*:::
This option sets the minimum interval between responses. It is defined as a This option sets the minimum interval between responses. It is defined as a
power of 2 in seconds. The default value is 3 (8 seconds). The minimum value power of 2 in seconds. The default value is -10 (1/1024 of a second, or 1024
is -4 and the maximum value is 12. packets per second). The minimum value is -19 (524288 packets per second) and
the maximum value is 12 (one packet per 4096 seconds). Note that with values
below -4 the rate limiting is coarse (responses are allowed in bursts, even if
the interval between them is shorter than the specified interval).
*burst*::: *burst*:::
This option sets the maximum number of responses that can be sent in a burst, This option sets the maximum number of responses that can be sent in a burst,
temporarily exceeding the limit specified by the *interval* option. This is temporarily exceeding the limit specified by the *interval* option. This is
useful for clients that make rapid measurements on start (e.g. *chronyd* with useful for clients that make rapid measurements on start (e.g. *chronyd* with
the *iburst* option). The default value is 8. The minimum value is 1 and the the *iburst* option). The default value is 16. The minimum value is 1 and the
maximum value is 255. maximum value is 255.
*leak*::: *leak*:::
This option sets the rate at which responses are randomly allowed even if the This option sets the rate at which responses are randomly allowed even if the
limits specified by the *interval* and *burst* options are exceeded. This is limits specified by the *interval* and *burst* options are exceeded. This is
necessary to prevent an attacker who is sending requests with a spoofed necessary to prevent an attacker who is sending requests with a spoofed
source address from completely blocking responses to that address. The leak source address from completely blocking responses to that address. The leak
rate is defined as a power of 1/2 and it is 3 by default, i.e. on average at rate is defined as a power of 1/2 and it is 2 by default, i.e. on average at
least every eighth request has a response. The minimum value is 1 and the least every fourth request has a response. The minimum value is 0, which
maximum value is 4. disables the rate limiting, and the maximum value is 4 (one response per 16
requests).
:: ::
+ +
An example use of the directive is: An example use of the directive is:
+ +
---- ----
ratelimit interval 4 burst 4 ratelimit interval 1 burst 8
---- ----
+ +
This would reduce the response rate for IP addresses that send packets on This would reduce the response rate for IP addresses sending packets on average
average more frequently than once per 16 seconds or send packets in bursts more than once per 2 seconds, or sending packets in bursts of more than 8
of more than 4 packets. packets, by up to 75% (with default *leak* of 2).
+
Rate limiting can be disabled by setting the *leak* option to 0, or by the
<<noclientlog,*noclientlog*>> directive.
[[smoothtime]]*smoothtime* _max-freq_ _max-wander_ [*leaponly*]:: [[smoothtime]]*smoothtime* _max-freq_ _max-wander_ [*leaponly*]::
The *smoothtime* directive can be used to enable smoothing of the time that The *smoothtime* directive can be used to enable smoothing of the time that
@@ -1389,16 +1397,18 @@ This would make *chronyd* use UDP 257 as its command port. (*chronyc* would
need to be run with the *-p 257* switch to inter-operate correctly.) need to be run with the *-p 257* switch to inter-operate correctly.)
[[cmdratelimit]]*cmdratelimit* [_option_]...:: [[cmdratelimit]]*cmdratelimit* [_option_]...::
This directive enables response rate limiting for command packets. It is This directive is identical to the <<ratelimit,*ratelimit*>> directive, except
similar to the <<ratelimit,*ratelimit*>> directive, except responses to it configures rate limiting for command packets and responses to localhost are
localhost are never limited and the default interval is 1 (2 seconds), the default never limited. It is disabled by default (the default *leak* is 0).
burst is 16, and the default leak rate is 2.
+ +
An example of the use of the directive is: An example of the use of the directive is:
+ +
---- ----
cmdratelimit interval 2 cmdratelimit interval -2 burst 128 leak 2
---- ----
+
This would reduce response rate for addresses that send more than 4 requests
per second, or bursts of more than 128 packets, by up to 75%.
=== Real-time clock (RTC) === Real-time clock (RTC)
@@ -1779,10 +1789,11 @@ received from the specified network interface. The network interface controller
receptions, avoiding processing and queueing delays in the kernel, network receptions, avoiding processing and queueing delays in the kernel, network
driver, and hardware. This can significantly improve the accuracy of the driver, and hardware. This can significantly improve the accuracy of the
timestamps and the measured offset, which is used for synchronisation of the timestamps and the measured offset, which is used for synchronisation of the
system clock. In order to get best results, it is necessary to enable HW system clock. In order to get the best results, both sides receiving and
timestamping on both sides receiving and sending the packets (i.e. server and sending NTP packets (i.e. server and client, or two peers) need to use HW
client, or both peers), and also enable the interleaved mode with the *xleave* timestamping. If the server or peer supports the interleaved mode, it needs to
option in the <<server,*server*>> or the <<peer,*peer*>> directive. be enabled by the *xleave* option in the <<server,*server*>> or the
<<peer,*peer*>> directive.
+ +
This directive is supported on Linux 3.19 and newer. The NIC must support HW This directive is supported on Linux 3.19 and newer. The NIC must support HW
timestamping, which can be verified with the *ethtool -T* command. The list of timestamping, which can be verified with the *ethtool -T* command. The list of
@@ -1799,6 +1810,9 @@ interfaces. The timestamping used in measurements is indicated in the
_measurements.log_ file if enabled by the <<log,*log measurements*>> directive, _measurements.log_ file if enabled by the <<log,*log measurements*>> directive,
and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in *chronyc*. and the <<chronyc.adoc#ntpdata,*ntpdata*>> report in *chronyc*.
+ +
If the specified interface is _*_, *chronyd* will try to enable HW timestamping
on all available interfaces.
+
An example of the directive is: An example of the directive is:
+ +
---- ----
@@ -2213,7 +2227,7 @@ http://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
is similar to the NTP client with permanent connection, except it needs to is similar to the NTP client with permanent connection, except it needs to
allow client access from all addresses. It is recommended to handpick at least allow client access from all addresses. It is recommended to handpick at least
few good servers, and possibly combine them with a random selection of other few good servers, and possibly combine them with a random selection of other
servers in the pool. Rate limiting can be enabled to not waste too much servers in the pool. The rate limiting interval can be increased to save more
bandwidth on misconfigured and broken NTP clients. The *-r* option with the bandwidth on misconfigured and broken NTP clients. The *-r* option with the
*dumpdir* directive shortens the time for which *chronyd* will not serve time *dumpdir* directive shortens the time for which *chronyd* will not serve time
to its clients when it needs to be restarted for any reason. to its clients when it needs to be restarted for any reason.
@@ -2228,7 +2242,7 @@ pool pool.ntp.org iburst
makestep 1.0 3 makestep 1.0 3
rtcsync rtcsync
allow allow
ratelimit interval 2 burst 10 ratelimit interval 1
driftfile @CHRONYVARDIR@/drift driftfile @CHRONYVARDIR@/drift
dumpdir @CHRONYRUNDIR@ dumpdir @CHRONYRUNDIR@
dumponexit dumponexit

View File

@@ -441,10 +441,10 @@ the offline state.
the name of the server or peer was not resolved to an address yet; this source is the name of the server or peer was not resolved to an address yet; this source is
not visible in the *sources* and *sourcestats* reports. not visible in the *sources* and *sourcestats* reports.
[[ntpdata]]*ntpdata* _address_:: [[ntpdata]]*ntpdata* [_address_]::
The *ntpdata* command displays the last valid measurement and other The *ntpdata* command displays the last valid measurement and other
NTP-specific information about the NTP source. An example of the output is NTP-specific information about the specified NTP source, or all NTP sources if
shown below. no address was specified. An example of the output is shown below.
+ +
---- ----
Remote address : 203.0.113.15 (CB00710F) Remote address : 203.0.113.15 (CB00710F)
@@ -454,8 +454,8 @@ Leap status : Normal
Version : 4 Version : 4
Mode : Server Mode : Server
Stratum : 1 Stratum : 1
Poll : 10 Poll interval : 10 (1024 seconds)
Precision : 0.000000060 seconds Precision : -24 (0.000000060 seconds)
Root delay : 0.000015 seconds Root delay : 0.000015 seconds
Root dispersion : 0.000015 seconds Root dispersion : 0.000015 seconds
Reference ID : 50505331 Reference ID : 50505331
@@ -489,7 +489,7 @@ reference ID.
*Version*::: *Version*:::
*Mode*::: *Mode*:::
*Stratum*::: *Stratum*:::
*Poll*::: *Poll interval*:::
*Precision*::: *Precision*:::
*Root delay*::: *Root delay*:::
*Root dispersion*::: *Root dispersion*:::

View File

@@ -9,7 +9,7 @@ Wants=time-sync.target
Type=oneshot Type=oneshot
# Wait up to ~10 minutes for chronyd to synchronize and the remaining # Wait up to ~10 minutes for chronyd to synchronize and the remaining
# clock correction to be less than 0.1 seconds # clock correction to be less than 0.1 seconds
ExecStart=/usr/bin/chronyc waitsync 600 0.1 0.0 1 ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 600 0.1 0.0 1
RemainAfterExit=yes RemainAfterExit=yes
StandardOutput=null StandardOutput=null

View File

@@ -113,6 +113,9 @@ DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *
LOG_FATAL(LOGF_Nameserv, "pipe() failed"); LOG_FATAL(LOGF_Nameserv, "pipe() failed");
} }
UTI_FdSetCloexec(inst->pipe[0]);
UTI_FdSetCloexec(inst->pipe[1]);
resolving_threads++; resolving_threads++;
assert(resolving_threads <= 1); assert(resolving_threads <= 1);

View File

@@ -1453,11 +1453,12 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
!(inst->mode == MODE_ACTIVE && interleaved_packet && !(inst->mode == MODE_ACTIVE && interleaved_packet &&
delay > UTI_Log2ToDouble(message->poll - 1)); delay > UTI_Log2ToDouble(message->poll - 1));
/* Test B requires that the ratio of the round trip delay to the /* Test B requires in the basic client mode that the ratio of the round
minimum one currently in the stats data register is less than an trip delay to the minimum one currently in the stats data register is
administrator-defined value */ less than an administrator-defined value */
testB = inst->max_delay_ratio <= 1.0 || testB = inst->max_delay_ratio <= 1.0 ||
(delay - dispersion) / SST_MinRoundTripDelay(stats) <= inst->max_delay_ratio; !(inst->mode == MODE_CLIENT && !interleaved_packet &&
(delay - dispersion) / SST_MinRoundTripDelay(stats) > inst->max_delay_ratio);
/* Test C requires that the ratio of the increase in delay from the minimum /* Test C requires that the ratio of the increase in delay from the minimum
one in the stats data register to the standard deviation of the offsets one in the stats data register to the standard deviation of the offsets

View File

@@ -28,6 +28,7 @@
#include "sysincl.h" #include "sysincl.h"
#include <ifaddrs.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
@@ -90,9 +91,16 @@ add_interface(const char *name)
struct hwtstamp_config ts_config; struct hwtstamp_config ts_config;
struct ifreq req; struct ifreq req;
int sock_fd, if_index, phc_index, phc_fd; int sock_fd, if_index, phc_index, phc_fd;
unsigned int i;
struct Interface *iface; struct Interface *iface;
char phc_path[64]; char phc_path[64];
/* Check if the interface was not already added */
for (i = 0; i < ARR_GetSize(interfaces); i++) {
if (!strcmp(name, ((struct Interface *)ARR_GetElement(interfaces, i))->name))
return 1;
}
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) if (sock_fd < 0)
return 0; return 0;
@@ -160,11 +168,37 @@ add_interface(const char *name)
iface->clock = HCL_CreateInstance(); iface->clock = HCL_CreateInstance();
DEBUG_LOG(LOGF_NtpIOLinux, "Enabled HW timestamping on %s", name);
return 1; return 1;
} }
/* ================================================== */ /* ================================================== */
static int
add_all_interfaces(void)
{
struct ifaddrs *ifaddr, *ifa;
int r;
if (getifaddrs(&ifaddr)) {
DEBUG_LOG(LOGF_NtpIOLinux, "getifaddrs() failed : %s", strerror(errno));
return 0;
}
for (r = 0, ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (add_interface(ifa->ifa_name))
r = 1;
}
freeifaddrs(ifaddr);
/* Return success if at least one interface was added */
return r;
}
/* ================================================== */
static void static void
update_interface_speed(struct Interface *iface) update_interface_speed(struct Interface *iface)
{ {
@@ -202,19 +236,34 @@ NIO_Linux_Initialise(void)
ARR_Instance config_hwts_ifaces; ARR_Instance config_hwts_ifaces;
char *if_name; char *if_name;
unsigned int i; unsigned int i;
int wildcard, hwts;
interfaces = ARR_CreateInstance(sizeof (struct Interface)); interfaces = ARR_CreateInstance(sizeof (struct Interface));
config_hwts_ifaces = CNF_GetHwTsInterfaces(); config_hwts_ifaces = CNF_GetHwTsInterfaces();
/* Enable HW timestamping on all specified interfaces. If no interface was /* Enable HW timestamping on specified interfaces. If "*" was specified, try
specified, use SW timestamping. */ all interfaces. If no interface was specified, enable SW timestamping. */
if (ARR_GetSize(config_hwts_ifaces)) {
for (i = wildcard = 0; i < ARR_GetSize(config_hwts_ifaces); i++) {
if (!strcmp("*", *(char **)ARR_GetElement(config_hwts_ifaces, i)))
wildcard = 1;
}
if (!wildcard && ARR_GetSize(config_hwts_ifaces)) {
for (i = 0; i < ARR_GetSize(config_hwts_ifaces); i++) { for (i = 0; i < ARR_GetSize(config_hwts_ifaces); i++) {
if_name = *(char **)ARR_GetElement(config_hwts_ifaces, i); if_name = *(char **)ARR_GetElement(config_hwts_ifaces, i);
if (!add_interface(if_name)) if (!add_interface(if_name))
LOG_FATAL(LOGF_NtpIO, "Could not enable HW timestamping on %s", if_name); LOG_FATAL(LOGF_NtpIO, "Could not enable HW timestamping on %s", if_name);
} }
hwts = 1;
} else if (wildcard && add_all_interfaces()) {
hwts = 1;
} else {
hwts = 0;
}
if (hwts) {
ts_flags = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; ts_flags = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE;
ts_tx_flags = SOF_TIMESTAMPING_TX_HARDWARE; ts_tx_flags = SOF_TIMESTAMPING_TX_HARDWARE;
} else { } else {

View File

@@ -47,8 +47,12 @@
2000ppm, which would be pretty bad */ 2000ppm, which would be pretty bad */
#define WORST_CASE_FREQ_BOUND (2000.0/1.0e6) #define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
/* The minimum allowed skew */ /* The minimum and maximum assumed skew */
#define MIN_SKEW 1.0e-12 #define MIN_SKEW 1.0e-12
#define MAX_SKEW 1.0e+02
/* The minimum assumed std dev for weighting */
#define MIN_WEIGHT_SD 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
@@ -507,8 +511,7 @@ SST_DoNewRegression(SST_Stats inst)
/* And now, work out the weight vector */ /* And now, work out the weight vector */
sd = mean_distance - min_distance; sd = mean_distance - min_distance;
if (sd > min_distance || sd <= 0.0) sd = CLAMP(MIN_WEIGHT_SD, sd, min_distance);
sd = min_distance;
for (i=0; i<inst->n_samples; i++) { for (i=0; i<inst->n_samples; i++) {
sd_weight = 1.0 + SD_TO_DIST_RATIO * (peer_distances[i] - min_distance) / sd; sd_weight = 1.0 + SD_TO_DIST_RATIO * (peer_distances[i] - min_distance) / sd;
@@ -539,9 +542,7 @@ SST_DoNewRegression(SST_Stats inst)
inst->std_dev = sqrt(est_var); inst->std_dev = sqrt(est_var);
inst->nruns = nruns; inst->nruns = nruns;
if (inst->skew < MIN_SKEW) inst->skew = CLAMP(MIN_SKEW, inst->skew, MAX_SKEW);
inst->skew = MIN_SKEW;
stress = fabs(old_freq - inst->estimated_frequency) / old_skew; stress = fabs(old_freq - inst->estimated_frequency) / old_skew;
DEBUG_LOG(LOGF_SourceStats, "off=%e freq=%e skew=%e n=%d bs=%d runs=%d asym=%f arun=%d", DEBUG_LOG(LOGF_SourceStats, "off=%e freq=%e skew=%e n=%d bs=%d runs=%d asym=%f arun=%d",
@@ -844,6 +845,8 @@ SST_SaveToFile(SST_Stats inst, FILE *out)
inst->strata[j]); inst->strata[j]);
} }
fprintf(out, "%d\n", inst->asymmetry_run);
} }
/* ================================================== */ /* ================================================== */
@@ -898,6 +901,10 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
UTI_NormaliseTimespec(&inst->sample_times[i]); UTI_NormaliseTimespec(&inst->sample_times[i]);
} }
} }
/* This field was not saved in older versions */
if (!fgets(line, sizeof(line), in) || sscanf(line, "%d\n", &inst->asymmetry_run) != 1)
inst->asymmetry_run = 0;
} else { } else {
inst->n_samples = 0; /* Load abandoned if any sign of corruption */ inst->n_samples = 0; /* Load abandoned if any sign of corruption */
return 0; return 0;

20
stubs.c
View File

@@ -42,6 +42,7 @@
#include "privops.h" #include "privops.h"
#include "refclock.h" #include "refclock.h"
#include "sched.h" #include "sched.h"
#include "util.h"
#ifndef FEAT_ASYNCDNS #ifndef FEAT_ASYNCDNS
@@ -51,10 +52,11 @@ struct DNS_Async_Instance {
const char *name; const char *name;
DNS_NameResolveHandler handler; DNS_NameResolveHandler handler;
void *arg; void *arg;
int pipe[2];
}; };
static void static void
resolve_name(void *anything) resolve_name(int fd, int event, void *anything)
{ {
struct DNS_Async_Instance *inst; struct DNS_Async_Instance *inst;
IPAddr addrs[DNS_MAX_ADDRESSES]; IPAddr addrs[DNS_MAX_ADDRESSES];
@@ -62,6 +64,11 @@ resolve_name(void *anything)
int i; int i;
inst = (struct DNS_Async_Instance *)anything; inst = (struct DNS_Async_Instance *)anything;
SCH_RemoveFileHandler(inst->pipe[0]);
close(inst->pipe[0]);
close(inst->pipe[1]);
status = PRV_Name2IPAddress(inst->name, addrs, DNS_MAX_ADDRESSES); status = PRV_Name2IPAddress(inst->name, addrs, DNS_MAX_ADDRESSES);
for (i = 0; status == DNS_Success && i < DNS_MAX_ADDRESSES && for (i = 0; status == DNS_Success && i < DNS_MAX_ADDRESSES &&
@@ -83,7 +90,16 @@ DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *
inst->handler = handler; inst->handler = handler;
inst->arg = anything; inst->arg = anything;
SCH_AddTimeoutByDelay(0.0, resolve_name, inst); if (pipe(inst->pipe))
LOG_FATAL(LOGF_Nameserv, "pipe() failed");
UTI_FdSetCloexec(inst->pipe[0]);
UTI_FdSetCloexec(inst->pipe[1]);
SCH_AddFileHandler(inst->pipe[0], SCH_FILE_INPUT, resolve_name, inst);
if (write(inst->pipe[1], "", 1) < 0)
;
} }
#endif /* !FEAT_ASYNCDNS */ #endif /* !FEAT_ASYNCDNS */