mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 17:45:07 -05:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c507975c | ||
|
|
b4235abd36 | ||
|
|
1966085a97 | ||
|
|
e31e7af48f | ||
|
|
adb9123fc3 | ||
|
|
b0f7efd59e | ||
|
|
e28dfada8c | ||
|
|
ac0b28cce6 | ||
|
|
48b16ae66c | ||
|
|
061579ec28 | ||
|
|
f2f834e7e7 | ||
|
|
a7802e9a76 | ||
|
|
8f7ab95ff0 | ||
|
|
042c670747 | ||
|
|
cacbe9976f | ||
|
|
8efec1d640 | ||
|
|
c44d282f0b | ||
|
|
4432f29bd2 | ||
|
|
5fee3ed5e9 | ||
|
|
b76ea64263 | ||
|
|
ed904f08a4 | ||
|
|
96cc80ffc8 | ||
|
|
ab99373cfc | ||
|
|
dbfb49384b | ||
|
|
14bb9f29a3 |
3
NEWS
3
NEWS
@@ -16,8 +16,7 @@ Enhancements
|
||||
* Add -t option to chronyd to exit after specified time
|
||||
* Add partial protection against replay attacks on symmetric mode
|
||||
* 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)
|
||||
* Allow rate limiting with very short intervals
|
||||
* Improve maximum server throughput on Linux and NetBSD
|
||||
* Remove dump files after start
|
||||
* Add tab-completion to chronyc with libedit/readline
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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>
|
||||
Handling arbitrary HZ values
|
||||
|
||||
Denny Page <dennypage@me.com>
|
||||
Advice on support for hardware timestamping
|
||||
|
||||
Gautier PHILIPPON <gautier.philippon@ensimag.grenoble-inp.fr>
|
||||
Patch to add refresh command to chronyc
|
||||
|
||||
|
||||
16
client.c
16
client.c
@@ -3,6 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Richard P. Curnow 1997-2003
|
||||
* Copyright (C) Lonnie Abelbeck 2016
|
||||
* Copyright (C) Miroslav Lichvar 2009-2016
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -2301,7 +2302,7 @@ process_cmd_ntpdata(char *line)
|
||||
"Precision : %d (%.9f seconds)\n"
|
||||
"Root delay : %.6f seconds\n"
|
||||
"Root dispersion : %.6f seconds\n"
|
||||
"Reference ID : %R\n"
|
||||
"Reference ID : %R (%s)\n"
|
||||
"Reference time : %T\n"
|
||||
"Offset : %+.9f seconds\n"
|
||||
"Peer delay : %.9f seconds\n"
|
||||
@@ -2325,7 +2326,10 @@ process_cmd_ntpdata(char *line)
|
||||
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_dispersion),
|
||||
(unsigned long)ntohl(reply.data.ntp_data.ref_id), &ref_time,
|
||||
(unsigned long)ntohl(reply.data.ntp_data.ref_id),
|
||||
reply.data.ntp_data.stratum <= 1 ?
|
||||
UTI_RefidToString(ntohl(reply.data.ntp_data.ref_id)) : "",
|
||||
&ref_time,
|
||||
UTI_FloatNetworkToHost(reply.data.ntp_data.offset),
|
||||
UTI_FloatNetworkToHost(reply.data.ntp_data.peer_delay),
|
||||
UTI_FloatNetworkToHost(reply.data.ntp_data.peer_dispersion),
|
||||
@@ -2720,7 +2724,8 @@ process_cmd_waitsync(char *line)
|
||||
max_skew_ppm = 0.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 */
|
||||
if (interval < 0.1)
|
||||
@@ -2828,7 +2833,8 @@ process_cmd_keygen(char *line)
|
||||
snprintf(hash_name, sizeof (hash_name), "MD5");
|
||||
#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));
|
||||
if (HSH_GetHashId(hash_name) < 0) {
|
||||
@@ -3091,7 +3097,7 @@ static void
|
||||
display_gpl(void)
|
||||
{
|
||||
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"
|
||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||
"GNU General Public License version 2 for details.\n\n",
|
||||
|
||||
34
clientlog.c
34
clientlog.c
@@ -119,7 +119,7 @@ static int cmd_token_shift;
|
||||
prevent an attacker sending requests with spoofed source address
|
||||
from blocking responses to the address completely. */
|
||||
|
||||
#define MIN_LEAK_RATE 0
|
||||
#define MIN_LEAK_RATE 1
|
||||
#define MAX_LEAK_RATE 4
|
||||
|
||||
static int ntp_leak_rate;
|
||||
@@ -305,19 +305,29 @@ CLG_Initialise(void)
|
||||
{
|
||||
int interval, burst, leak_rate;
|
||||
|
||||
CNF_GetNTPRateLimit(&interval, &burst, &leak_rate);
|
||||
set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet,
|
||||
&ntp_token_shift);
|
||||
ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
|
||||
max_ntp_tokens = max_cmd_tokens = 0;
|
||||
ntp_tokens_per_packet = cmd_tokens_per_packet = 0;
|
||||
ntp_token_shift = cmd_token_shift = 0;
|
||||
ntp_leak_rate = cmd_leak_rate = 0;
|
||||
|
||||
CNF_GetCommandRateLimit(&interval, &burst, &leak_rate);
|
||||
set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet,
|
||||
&cmd_token_shift);
|
||||
cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
|
||||
if (CNF_GetNTPRateLimit(&interval, &burst, &leak_rate)) {
|
||||
set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet,
|
||||
&ntp_token_shift);
|
||||
ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
|
||||
}
|
||||
|
||||
if (CNF_GetCommandRateLimit(&interval, &burst, &leak_rate)) {
|
||||
set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet,
|
||||
&cmd_token_shift);
|
||||
cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Calculate the maximum number of slots that can be allocated in the
|
||||
configured memory limit. Take into account expanding of the hash
|
||||
@@ -520,7 +530,7 @@ CLG_LimitNTPResponseRate(int index)
|
||||
Record *record;
|
||||
int drop;
|
||||
|
||||
if (!ntp_leak_rate)
|
||||
if (!ntp_tokens_per_packet)
|
||||
return 0;
|
||||
|
||||
record = ARR_GetElement(records, index);
|
||||
@@ -561,7 +571,7 @@ CLG_LimitCommandResponseRate(int index)
|
||||
{
|
||||
Record *record;
|
||||
|
||||
if (!cmd_leak_rate)
|
||||
if (!cmd_tokens_per_packet)
|
||||
return 0;
|
||||
|
||||
record = ARR_GetElement(records, index);
|
||||
|
||||
96
conf.c
96
conf.c
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* 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
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -66,7 +66,8 @@ static void parse_log(char *);
|
||||
static void parse_mailonchange(char *);
|
||||
static void parse_makestep(char *);
|
||||
static void parse_maxchange(char *);
|
||||
static void parse_ratelimit(char *line, int *interval, int *burst, int *leak);
|
||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||
int *burst, int *leak);
|
||||
static void parse_refclock(char *);
|
||||
static void parse_smoothtime(char *);
|
||||
static void parse_source(char *line, NTP_Source_Type type, int pool);
|
||||
@@ -190,12 +191,14 @@ static char *ntp_signd_socket = NULL;
|
||||
static char *pidfile;
|
||||
|
||||
/* Rate limiting parameters */
|
||||
static int ntp_ratelimit_interval = -10;
|
||||
static int ntp_ratelimit_burst = 16;
|
||||
static int ntp_ratelimit_enabled = 0;
|
||||
static int ntp_ratelimit_interval = 3;
|
||||
static int ntp_ratelimit_burst = 8;
|
||||
static int ntp_ratelimit_leak = 2;
|
||||
static int cmd_ratelimit_interval = -10;
|
||||
static int cmd_ratelimit_burst = 16;
|
||||
static int cmd_ratelimit_leak = 0;
|
||||
static int cmd_ratelimit_enabled = 0;
|
||||
static int cmd_ratelimit_interval = -4;
|
||||
static int cmd_ratelimit_burst = 8;
|
||||
static int cmd_ratelimit_leak = 2;
|
||||
|
||||
/* Smoothing constants */
|
||||
static double smooth_max_freq = 0.0; /* in ppm */
|
||||
@@ -220,7 +223,13 @@ static char *leapsec_tz = NULL;
|
||||
/* Name of the user to which will be dropped root privileges. */
|
||||
static char *user;
|
||||
|
||||
/* Array of strings for interfaces with HW timestamping */
|
||||
typedef struct {
|
||||
char *name;
|
||||
double tx_comp;
|
||||
double rx_comp;
|
||||
} HwTs_Interface;
|
||||
|
||||
/* Array of HwTs_Interface */
|
||||
static ARR_Instance hwts_interfaces;
|
||||
|
||||
typedef struct {
|
||||
@@ -324,7 +333,7 @@ CNF_Initialise(int r)
|
||||
{
|
||||
restarted = r;
|
||||
|
||||
hwts_interfaces = ARR_CreateInstance(sizeof (char *));
|
||||
hwts_interfaces = ARR_CreateInstance(sizeof (HwTs_Interface));
|
||||
|
||||
init_sources = ARR_CreateInstance(sizeof (IPAddr));
|
||||
ntp_sources = ARR_CreateInstance(sizeof (NTP_Source));
|
||||
@@ -351,7 +360,7 @@ CNF_Finalise(void)
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(hwts_interfaces); i++)
|
||||
Free(*(char **)ARR_GetElement(hwts_interfaces, i));
|
||||
Free(((HwTs_Interface *)ARR_GetElement(hwts_interfaces, i))->name);
|
||||
ARR_DestroyInstance(hwts_interfaces);
|
||||
|
||||
for (i = 0; i < ARR_GetSize(ntp_sources); i++)
|
||||
@@ -452,7 +461,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
} else if (!strcasecmp(command, "cmdport")) {
|
||||
parse_int(p, &cmd_port);
|
||||
} else if (!strcasecmp(command, "cmdratelimit")) {
|
||||
parse_ratelimit(p, &cmd_ratelimit_interval, &cmd_ratelimit_burst, &cmd_ratelimit_leak);
|
||||
parse_ratelimit(p, &cmd_ratelimit_enabled, &cmd_ratelimit_interval,
|
||||
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
|
||||
} else if (!strcasecmp(command, "combinelimit")) {
|
||||
parse_double(p, &combine_limit);
|
||||
} else if (!strcasecmp(command, "corrtimeratio")) {
|
||||
@@ -532,7 +542,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
} else if (!strcasecmp(command, "port")) {
|
||||
parse_int(p, &ntp_port);
|
||||
} else if (!strcasecmp(command, "ratelimit")) {
|
||||
parse_ratelimit(p, &ntp_ratelimit_interval, &ntp_ratelimit_burst, &ntp_ratelimit_leak);
|
||||
parse_ratelimit(p, &ntp_ratelimit_enabled, &ntp_ratelimit_interval,
|
||||
&ntp_ratelimit_burst, &ntp_ratelimit_leak);
|
||||
} else if (!strcasecmp(command, "refclock")) {
|
||||
parse_refclock(p);
|
||||
} else if (!strcasecmp(command, "reselectdist")) {
|
||||
@@ -637,11 +648,13 @@ parse_source(char *line, NTP_Source_Type type, int pool)
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_ratelimit(char *line, int *interval, int *burst, int *leak)
|
||||
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
|
||||
{
|
||||
int n, val;
|
||||
char *opt;
|
||||
|
||||
*enabled = 1;
|
||||
|
||||
while (*line) {
|
||||
opt = line;
|
||||
line = CPS_SplitWord(line);
|
||||
@@ -1238,8 +1251,39 @@ parse_tempcomp(char *line)
|
||||
static void
|
||||
parse_hwtimestamp(char *line)
|
||||
{
|
||||
check_number_of_args(line, 1);
|
||||
*(char **)ARR_GetNewElement(hwts_interfaces) = Strdup(line);
|
||||
HwTs_Interface *iface;
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
if (!*line) {
|
||||
command_parse_error();
|
||||
return;
|
||||
}
|
||||
|
||||
p = line;
|
||||
line = CPS_SplitWord(line);
|
||||
|
||||
iface = ARR_GetNewElement(hwts_interfaces);
|
||||
iface->name = Strdup(p);
|
||||
iface->tx_comp = 0.0;
|
||||
iface->rx_comp = 0.0;
|
||||
|
||||
for (p = line; *p; line += n, p = line) {
|
||||
line = CPS_SplitWord(line);
|
||||
|
||||
if (!strcasecmp(p, "rxcomp")) {
|
||||
if (sscanf(line, "%lf%n", &iface->rx_comp, &n) != 1)
|
||||
break;
|
||||
} else if (!strcasecmp(p, "txcomp")) {
|
||||
if (sscanf(line, "%lf%n", &iface->tx_comp, &n) != 1)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p)
|
||||
command_parse_error();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1823,20 +1867,22 @@ CNF_GetLockMemory(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
|
||||
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
|
||||
{
|
||||
*interval = ntp_ratelimit_interval;
|
||||
*burst = ntp_ratelimit_burst;
|
||||
*leak = ntp_ratelimit_leak;
|
||||
return ntp_ratelimit_enabled;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak)
|
||||
int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak)
|
||||
{
|
||||
*interval = cmd_ratelimit_interval;
|
||||
*burst = cmd_ratelimit_burst;
|
||||
*leak = cmd_ratelimit_leak;
|
||||
return cmd_ratelimit_enabled;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1921,8 +1967,18 @@ CNF_GetInitStepThreshold(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
ARR_Instance
|
||||
CNF_GetHwTsInterfaces(void)
|
||||
int
|
||||
CNF_GetHwTsInterface(unsigned int index, char **name, double *tx_comp, double *rx_comp)
|
||||
{
|
||||
return hwts_interfaces;
|
||||
HwTs_Interface *iface;
|
||||
|
||||
if (index >= ARR_GetSize(hwts_interfaces))
|
||||
return 0;
|
||||
|
||||
iface = ARR_GetElement(hwts_interfaces, index);
|
||||
*name = iface->name;
|
||||
*tx_comp = iface->tx_comp;
|
||||
*rx_comp = iface->rx_comp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
7
conf.h
7
conf.h
@@ -29,7 +29,6 @@
|
||||
#define GOT_CONF_H
|
||||
|
||||
#include "addressing.h"
|
||||
#include "array.h"
|
||||
#include "reference.h"
|
||||
|
||||
extern void CNF_Initialise(int restarted);
|
||||
@@ -102,8 +101,8 @@ extern void CNF_SetupAccessRestrictions(void);
|
||||
extern int CNF_GetSchedPriority(void);
|
||||
extern int CNF_GetLockMemory(void);
|
||||
|
||||
extern void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
|
||||
extern void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
|
||||
extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
|
||||
extern int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
|
||||
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);
|
||||
|
||||
@@ -120,6 +119,6 @@ extern char *CNF_GetHwclockFile(void);
|
||||
extern int CNF_GetInitSources(void);
|
||||
extern double CNF_GetInitStepThreshold(void);
|
||||
|
||||
extern ARR_Instance CNF_GetHwTsInterfaces(void);
|
||||
extern int CNF_GetHwTsInterface(unsigned int index, char **name, double *tx_comp, double *rx_comp);
|
||||
|
||||
#endif /* GOT_CONF_H */
|
||||
|
||||
3
configure
vendored
3
configure
vendored
@@ -4,7 +4,8 @@
|
||||
# chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
#
|
||||
# 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
|
||||
//
|
||||
// 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
|
||||
// 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*
|
||||
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
|
||||
3 seconds.
|
||||
3 seconds and the maximum value is 1000 seconds.
|
||||
*maxdelayratio* _ratio_:::
|
||||
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
|
||||
@@ -160,9 +161,8 @@ synchronisation only if they agree with the trusted and required source.
|
||||
*xleave*:::
|
||||
This option enables an interleaved mode which allows the server or the peer to
|
||||
send transmit timestamps captured after the actual transmission (e.g. when the
|
||||
server or the peer is running *chronyd* with HW timestamping enabled by the
|
||||
<<hwtimestamp,*hwtimestamp*>> directive). This can significantly improve the
|
||||
accuracy of the measurements.
|
||||
server or the peer is running *chronyd* with software (kernel) or hardware
|
||||
timestamping). This can significantly improve the accuracy of the measurements.
|
||||
+
|
||||
The interleaved mode is compatible with servers that support only the basic
|
||||
mode, but peers must both support and have enabled the interleaved mode,
|
||||
@@ -994,7 +994,7 @@ both a client of its servers, and a server to other clients.
|
||||
Examples of the use of the directive are as follows:
|
||||
+
|
||||
----
|
||||
allow foo.example.net
|
||||
allow 1.2.3.4
|
||||
allow 1.2
|
||||
allow 3.4.5
|
||||
allow 6.7.8/22
|
||||
@@ -1005,7 +1005,8 @@ allow ::/0
|
||||
allow
|
||||
----
|
||||
+
|
||||
The first directive allows the named node to be an NTP client of this computer.
|
||||
The first directive allows a node with IPv4 address _1.2.3.4_ to be an NTP
|
||||
client of this computer.
|
||||
The second directive allows any node with an IPv4 address of the form _1.2.x.y_
|
||||
(with _x_ and _y_ arbitrary) to be an NTP client of this computer. Likewise,
|
||||
the third directive allows any node with an IPv4 address of the form _3.4.5.x_
|
||||
@@ -1046,6 +1047,10 @@ Within a configuration file this capability is probably rather moot; however,
|
||||
it is of greater use for reconfiguration at run-time via *chronyc* with the
|
||||
<<chronyc.adoc#allow,*allow all*>> command.
|
||||
+
|
||||
The directive allows a hostname to be specified instead of an IP address, but
|
||||
the name must be resolvable when *chronyd* is started (i.e. *chronyd* needs
|
||||
to be started when the network is already up and DNS is working).
|
||||
+
|
||||
Note, if the <<initstepslew,*initstepslew*>> directive is used in the
|
||||
configuration file, each of the computers listed in that directive must allow
|
||||
client access by this computer for it to work.
|
||||
@@ -1221,8 +1226,8 @@ source port used in NTP client requests can be set by the
|
||||
<<acquisitionport,*acquisitionport*>> directive.
|
||||
|
||||
[[ratelimit]]*ratelimit* [_option_]...::
|
||||
This directive configures response rate limiting for NTP packets. Its purpose
|
||||
is to reduce network traffic with misconfigured or broken NTP clients that are
|
||||
This directive enables response rate limiting for NTP packets. Its purpose 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
|
||||
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
|
||||
@@ -1237,16 +1242,16 @@ in any order):
|
||||
+
|
||||
*interval*:::
|
||||
This option sets the minimum interval between responses. It is defined as a
|
||||
power of 2 in seconds. The default value is -10 (1/1024 of a second, or 1024
|
||||
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).
|
||||
power of 2 in seconds. The default value is 3 (8 seconds). 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*:::
|
||||
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
|
||||
useful for clients that make rapid measurements on start (e.g. *chronyd* with
|
||||
the *iburst* option). The default value is 16. The minimum value is 1 and the
|
||||
the *iburst* option). The default value is 8. The minimum value is 1 and the
|
||||
maximum value is 255.
|
||||
*leak*:::
|
||||
This option sets the rate at which responses are randomly allowed even if the
|
||||
@@ -1254,23 +1259,19 @@ limits specified by the *interval* and *burst* options are exceeded. This is
|
||||
necessary to prevent an attacker who is sending requests with a spoofed
|
||||
source address from completely blocking responses to that address. The leak
|
||||
rate is defined as a power of 1/2 and it is 2 by default, i.e. on average at
|
||||
least every fourth request has a response. The minimum value is 0, which
|
||||
disables the rate limiting, and the maximum value is 4 (one response per 16
|
||||
requests).
|
||||
least every fourth request has a response. The minimum value is 1 and the
|
||||
maximum value is 4.
|
||||
::
|
||||
+
|
||||
An example use of the directive is:
|
||||
+
|
||||
----
|
||||
ratelimit interval 1 burst 8
|
||||
ratelimit interval 1 burst 16
|
||||
----
|
||||
+
|
||||
This would reduce the response rate for IP addresses sending packets on average
|
||||
more than once per 2 seconds, or sending packets in bursts of more than 8
|
||||
more than once per 2 seconds, or sending packets in bursts of more than 16
|
||||
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*]::
|
||||
The *smoothtime* directive can be used to enable smoothing of the time that
|
||||
@@ -1397,18 +1398,16 @@ 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.)
|
||||
|
||||
[[cmdratelimit]]*cmdratelimit* [_option_]...::
|
||||
This directive is identical to the <<ratelimit,*ratelimit*>> directive, except
|
||||
it configures rate limiting for command packets and responses to localhost are
|
||||
never limited. It is disabled by default (the default *leak* is 0).
|
||||
This directive enables response rate limiting for command packets. It is
|
||||
similar to the <<ratelimit,*ratelimit*>> directive, except responses to
|
||||
localhost are never limited and the default interval is -4 (16 packets per
|
||||
second).
|
||||
+
|
||||
An example of the use of the directive is:
|
||||
+
|
||||
----
|
||||
cmdratelimit interval -2 burst 128 leak 2
|
||||
cmdratelimit interval 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)
|
||||
|
||||
@@ -1782,7 +1781,7 @@ sendmail binary.
|
||||
|
||||
=== Miscellaneous
|
||||
|
||||
[[hwtimestamp]]*hwtimestamp* _interface_::
|
||||
[[hwtimestamp]]*hwtimestamp* _interface_ [_option_]...::
|
||||
This directive enables hardware timestamping of NTP packets sent to and
|
||||
received from the specified network interface. The network interface controller
|
||||
(NIC) uses its own clock to accurately timestamp the actual transmissions and
|
||||
@@ -1813,10 +1812,25 @@ 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:
|
||||
The *hwtimestamp* directive has the following options:
|
||||
+
|
||||
*txcomp* _compensation_:::
|
||||
This option specifies the difference in seconds between the actual transmission
|
||||
time at the physical layer and the reported transmit timestamp. This value will
|
||||
be added to transmit timestamps obtained from the NIC. The default value is 0.
|
||||
*rxcomp* _compensation_:::
|
||||
This option specifies the difference in seconds between the reported receive
|
||||
timestamp and the actual reception time at the physical layer. This value will
|
||||
be subtracted from receive timestamps obtained from the NIC. The default value
|
||||
is 0.
|
||||
::
|
||||
+
|
||||
Examples of the directive are:
|
||||
+
|
||||
----
|
||||
hwtimestamp eth0
|
||||
hwtimestamp eth1 txcomp 300e-9 rxcomp 645e-9
|
||||
hwtimestamp *
|
||||
----
|
||||
|
||||
[[include]]*include* _pattern_::
|
||||
@@ -2225,24 +2239,34 @@ information to be saved.
|
||||
*chronyd* can be configured to operate as a public NTP server, e.g. to join the
|
||||
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
|
||||
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
|
||||
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
|
||||
*dumpdir* directive shortens the time for which *chronyd* will not serve time
|
||||
to its clients when it needs to be restarted for any reason.
|
||||
allow client access from all addresses. It is recommended to find at least four
|
||||
good servers (e.g. from the pool, or on the NTP homepage). If the server has a
|
||||
hardware reference clock (e.g. a GPS receiver), it can be specified by the
|
||||
<<refclock,*refclock*>> directive.
|
||||
|
||||
The configuration file might be:
|
||||
The amount of memory used for logging client accesses can be increased in order
|
||||
to enable clients to use the interleaved mode even when the server has a large
|
||||
number of clients, and better support rate limiting if it is enabled by the
|
||||
<<ratelimit,*ratelimit*>> directive. The system timezone database, if it is
|
||||
kept up to date and includes the *right/UTC* timezone, can be used as a
|
||||
reliable source to determine when a leap second will be applied to UTC. The
|
||||
*-r* option with the <<dumpdir,*dumpdir*>> directive shortens the time in which
|
||||
*chronyd* will not be able to serve time to its clients when it needs to be
|
||||
restarted (e.g. after upgrading to a newer version, or a change in the
|
||||
configuration).
|
||||
|
||||
The configuration file could look like:
|
||||
|
||||
----
|
||||
server foo.example.net iburst
|
||||
server bar.example.net iburst
|
||||
server baz.example.net iburst
|
||||
pool pool.ntp.org iburst
|
||||
server qux.example.net iburst
|
||||
makestep 1.0 3
|
||||
rtcsync
|
||||
allow
|
||||
ratelimit interval 1
|
||||
clientloglimit 100000000
|
||||
leapsectz right/UTC
|
||||
driftfile @CHRONYVARDIR@/drift
|
||||
dumpdir @CHRONYRUNDIR@
|
||||
dumponexit
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// This file is part of chrony
|
||||
//
|
||||
// Copyright (C) Richard P. Curnow 1997-2003
|
||||
// Copyright (C) Stephen Wadeley 2016
|
||||
// Copyright (C) Miroslav Lichvar 2009-2016
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
@@ -458,7 +459,7 @@ Poll interval : 10 (1024 seconds)
|
||||
Precision : -24 (0.000000060 seconds)
|
||||
Root delay : 0.000015 seconds
|
||||
Root dispersion : 0.000015 seconds
|
||||
Reference ID : 50505331
|
||||
Reference ID : 47505300 (GPS)
|
||||
Reference time : Fri Nov 25 15:22:12 2016
|
||||
Offset : -0.000060878 seconds
|
||||
Peer delay : 0.000175634 seconds
|
||||
|
||||
@@ -55,6 +55,9 @@ struct HCL_Instance_Record {
|
||||
/* Number of samples */
|
||||
int n_samples;
|
||||
|
||||
/* Maximum error of the last sample */
|
||||
double last_err;
|
||||
|
||||
/* Flag indicating the offset and frequency values are valid */
|
||||
int valid_coefs;
|
||||
|
||||
@@ -151,6 +154,7 @@ HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts,
|
||||
clock->n_samples++;
|
||||
clock->hw_ref = *hw_ts;
|
||||
clock->local_ref = *local_ts;
|
||||
clock->last_err = err;
|
||||
|
||||
/* Get new coefficients */
|
||||
clock->valid_coefs =
|
||||
@@ -196,9 +200,9 @@ HCL_CookTime(HCL_Instance clock, struct timespec *raw, struct timespec *cooked,
|
||||
offset = clock->offset + elapsed / clock->frequency;
|
||||
UTI_AddDoubleToTimespec(&clock->local_ref, offset, cooked);
|
||||
|
||||
/* Estimation of the error is not implemented yet */
|
||||
/* Fow now, just return the error of the last sample */
|
||||
if (err)
|
||||
*err = 0.0;
|
||||
*err = clock->last_err;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
2
local.c
2
local.c
@@ -144,6 +144,8 @@ calculate_sys_precision(void)
|
||||
best *= 2;
|
||||
}
|
||||
|
||||
assert(precision_log >= -30);
|
||||
|
||||
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 > 0) {
|
||||
/* Print the error message from the child */
|
||||
fprintf(stderr, "%.1024s\n", message);
|
||||
message[sizeof (message) - 1] = '\0';
|
||||
fprintf(stderr, "%s\n", message);
|
||||
}
|
||||
exit(1);
|
||||
} else
|
||||
|
||||
133
ntp_core.c
133
ntp_core.c
@@ -3,7 +3,7 @@
|
||||
|
||||
**********************************************************************
|
||||
* 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
|
||||
* 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 */
|
||||
#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 */
|
||||
#define MIN_POLL 0
|
||||
#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)
|
||||
result->presend_minpoll = MAX_POLL + 1;
|
||||
|
||||
result->max_delay = params->max_delay;
|
||||
result->max_delay_ratio = params->max_delay_ratio;
|
||||
result->max_delay_dev_ratio = params->max_delay_dev_ratio;
|
||||
result->max_delay = CLAMP(0.0, params->max_delay, MAX_MAX_DELAY);
|
||||
result->max_delay_ratio = CLAMP(0.0, params->max_delay_ratio, MAX_MAX_DELAY_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->auto_offline = params->auto_offline;
|
||||
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 */
|
||||
UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz);
|
||||
|
||||
/* Prepare random bits which will be added to the transmit timestamp. */
|
||||
UTI_GetNtp64Fuzz(&ts_fuzz, precision);
|
||||
do {
|
||||
/* 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
|
||||
store this for our own use later, next time we receive a message
|
||||
from the source we're sending to now. */
|
||||
LCL_ReadCookedTime(&local_transmit, &local_transmit_err);
|
||||
/* 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
|
||||
from the source we're sending to now. */
|
||||
LCL_ReadCookedTime(&local_transmit, &local_transmit_err);
|
||||
|
||||
if (smooth_time)
|
||||
UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
|
||||
if (smooth_time)
|
||||
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) {
|
||||
/* Pre-compensate the transmit time by approx. how long it will
|
||||
take to generate the authentication data. */
|
||||
local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
|
||||
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
|
||||
UTI_NormaliseTimespec(&local_transmit);
|
||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||
&message.transmit_ts, &ts_fuzz);
|
||||
if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
|
||||
/* Pre-compensate the transmit time by approximately how long it will
|
||||
take to generate the authentication data */
|
||||
local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
|
||||
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
|
||||
UTI_NormaliseTimespec(&local_transmit);
|
||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||
&message.transmit_ts, &ts_fuzz);
|
||||
|
||||
if (auth_mode == AUTH_SYMMETRIC) {
|
||||
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
|
||||
offsetof(NTP_Packet, auth_keyid),
|
||||
(unsigned char *)&message.auth_data,
|
||||
sizeof (message.auth_data));
|
||||
if (!auth_len) {
|
||||
DEBUG_LOG(LOGF_NtpCore, "Could not generate auth data with key %"PRIu32, key_id);
|
||||
return 0;
|
||||
if (auth_mode == AUTH_SYMMETRIC) {
|
||||
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
|
||||
offsetof(NTP_Packet, auth_keyid),
|
||||
(unsigned char *)&message.auth_data,
|
||||
sizeof (message.auth_data));
|
||||
if (!auth_len) {
|
||||
DEBUG_LOG(LOGF_NtpCore, "Could not generate auth data with key %"PRIu32, key_id);
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||
&message.transmit_ts, &ts_fuzz);
|
||||
}
|
||||
} else {
|
||||
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
|
||||
&message.transmit_ts, &ts_fuzz);
|
||||
}
|
||||
|
||||
/* Avoid sending messages with non-zero transmit timestamp equal to the
|
||||
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);
|
||||
|
||||
@@ -1412,12 +1423,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
||||
sample_rx_tss = rx_ts->source;
|
||||
}
|
||||
|
||||
/* Work out 'delay' relative to the source's time */
|
||||
delay = (1.0 - (source_freq_lo + source_freq_hi) / 2.0) *
|
||||
local_interval - remote_interval;
|
||||
|
||||
/* Clamp delay to avoid misleading results later */
|
||||
delay = fabs(delay);
|
||||
/* Calculate delay */
|
||||
delay = fabs(local_interval - remote_interval);
|
||||
if (delay < precision)
|
||||
delay = precision;
|
||||
|
||||
@@ -1439,7 +1446,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
||||
skew = (source_freq_hi - source_freq_lo) / 2.0;
|
||||
|
||||
/* and then calculate peer dispersion */
|
||||
dispersion = precision + inst->local_tx.err + rx_ts_err + skew * fabs(local_interval);
|
||||
dispersion = MAX(precision, MAX(inst->local_tx.err, rx_ts_err)) +
|
||||
skew * fabs(local_interval);
|
||||
|
||||
/* Additional tests required to pass before accumulating the sample */
|
||||
|
||||
@@ -1609,13 +1617,14 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
|
||||
UTI_DiffTimespecsToDouble(&inst->local_rx.ts, &inst->local_tx.ts));
|
||||
|
||||
if (kod_rate) {
|
||||
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr));
|
||||
|
||||
/* Back off for a while and stop ongoing burst */
|
||||
delay_time += 4 * (1UL << inst->minpoll);
|
||||
|
||||
if (inst->opmode == MD_BURST_WAS_OFFLINE || inst->opmode == MD_BURST_WAS_ONLINE) {
|
||||
inst->burst_good_samples_to_go = 0;
|
||||
LOG(LOGS_WARN, LOGF_NtpCore, "Received KoD RATE from %s, burst sampling stopped",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2108,9 +2117,9 @@ NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
|
||||
void
|
||||
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",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -2118,9 +2127,9 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
|
||||
void
|
||||
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",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_ratio);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -2128,9 +2137,9 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
|
||||
void
|
||||
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",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_dev_ratio);
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_dev_ratio);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
8
ntp_io.c
8
ntp_io.c
@@ -364,8 +364,12 @@ NIO_Initialise(int family)
|
||||
#ifdef HAVE_LINUX_TIMESTAMPING
|
||||
NIO_Linux_Initialise();
|
||||
#else
|
||||
if (ARR_GetSize(CNF_GetHwTsInterfaces()))
|
||||
LOG_FATAL(LOGF_NtpIO, "HW timestamping not supported");
|
||||
if (1) {
|
||||
double tx_comp, rx_comp;
|
||||
char *name;
|
||||
if (CNF_GetHwTsInterface(0, &name, &tx_comp, &rx_comp))
|
||||
LOG_FATAL(LOGF_NtpIO, "HW timestamping not supported");
|
||||
}
|
||||
#endif
|
||||
|
||||
recv_messages = ARR_CreateInstance(sizeof (struct Message));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
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
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@@ -66,12 +66,18 @@ struct Interface {
|
||||
/* Start of UDP data at layer 2 for IPv4 and IPv6 */
|
||||
int l2_udp4_ntp_start;
|
||||
int l2_udp6_ntp_start;
|
||||
/* Compensation of errors in TX and RX timestamping */
|
||||
double tx_comp;
|
||||
double rx_comp;
|
||||
HCL_Instance clock;
|
||||
};
|
||||
|
||||
/* Number of PHC readings per HW clock sample */
|
||||
#define PHC_READINGS 10
|
||||
|
||||
/* Maximum acceptable offset between HW and daemon/kernel timestamp */
|
||||
#define MAX_TS_DELAY 1.0
|
||||
|
||||
/* Array of Interfaces */
|
||||
static ARR_Instance interfaces;
|
||||
|
||||
@@ -85,7 +91,7 @@ static int permanent_ts_options;
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
add_interface(const char *name)
|
||||
add_interface(const char *name, double tx_comp, double rx_comp)
|
||||
{
|
||||
struct ethtool_ts_info ts_info;
|
||||
struct hwtstamp_config ts_config;
|
||||
@@ -166,6 +172,9 @@ add_interface(const char *name)
|
||||
iface->l2_udp4_ntp_start = 42;
|
||||
iface->l2_udp6_ntp_start = 62;
|
||||
|
||||
iface->tx_comp = tx_comp;
|
||||
iface->rx_comp = rx_comp;
|
||||
|
||||
iface->clock = HCL_CreateInstance();
|
||||
|
||||
DEBUG_LOG(LOGF_NtpIOLinux, "Enabled HW timestamping on %s", name);
|
||||
@@ -176,7 +185,7 @@ add_interface(const char *name)
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
add_all_interfaces(void)
|
||||
add_all_interfaces(double tx_comp, double rx_comp)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int r;
|
||||
@@ -187,7 +196,7 @@ add_all_interfaces(void)
|
||||
}
|
||||
|
||||
for (r = 0, ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
||||
if (add_interface(ifa->ifa_name))
|
||||
if (add_interface(ifa->ifa_name, tx_comp, rx_comp))
|
||||
r = 1;
|
||||
}
|
||||
|
||||
@@ -233,34 +242,30 @@ update_interface_speed(struct Interface *iface)
|
||||
void
|
||||
NIO_Linux_Initialise(void)
|
||||
{
|
||||
ARR_Instance config_hwts_ifaces;
|
||||
char *if_name;
|
||||
double tx_comp, rx_comp;
|
||||
char *name;
|
||||
unsigned int i;
|
||||
int wildcard, hwts;
|
||||
int hwts;
|
||||
|
||||
interfaces = ARR_CreateInstance(sizeof (struct Interface));
|
||||
|
||||
config_hwts_ifaces = CNF_GetHwTsInterfaces();
|
||||
|
||||
/* Enable HW timestamping on specified interfaces. If "*" was specified, try
|
||||
all interfaces. If no interface was specified, enable SW timestamping. */
|
||||
|
||||
for (i = wildcard = 0; i < ARR_GetSize(config_hwts_ifaces); i++) {
|
||||
if (!strcmp("*", *(char **)ARR_GetElement(config_hwts_ifaces, i)))
|
||||
wildcard = 1;
|
||||
for (i = hwts = 0; CNF_GetHwTsInterface(i, &name, &tx_comp, &rx_comp); i++) {
|
||||
if (!strcmp("*", name))
|
||||
continue;
|
||||
if (!add_interface(name, tx_comp, rx_comp))
|
||||
LOG_FATAL(LOGF_NtpIO, "Could not enable HW timestamping on %s", name);
|
||||
hwts = 1;
|
||||
}
|
||||
|
||||
if (!wildcard && ARR_GetSize(config_hwts_ifaces)) {
|
||||
for (i = 0; i < ARR_GetSize(config_hwts_ifaces); i++) {
|
||||
if_name = *(char **)ARR_GetElement(config_hwts_ifaces, i);
|
||||
if (!add_interface(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;
|
||||
for (i = 0; CNF_GetHwTsInterface(i, &name, &tx_comp, &rx_comp); i++) {
|
||||
if (strcmp("*", name))
|
||||
continue;
|
||||
if (add_all_interfaces(tx_comp, rx_comp))
|
||||
hwts = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hwts) {
|
||||
@@ -417,8 +422,8 @@ static void
|
||||
process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts,
|
||||
NTP_Local_Timestamp *local_ts, int rx_ntp_length, int family)
|
||||
{
|
||||
struct timespec sample_phc_ts, sample_local_ts;
|
||||
double sample_delay, rx_correction;
|
||||
struct timespec sample_phc_ts, sample_local_ts, ts;
|
||||
double sample_delay, rx_correction, ts_delay, err;
|
||||
int l2_length;
|
||||
|
||||
if (HCL_NeedsNewSample(iface->clock, &local_ts->ts)) {
|
||||
@@ -444,9 +449,23 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts,
|
||||
UTI_AddDoubleToTimespec(hw_ts, rx_correction, hw_ts);
|
||||
}
|
||||
|
||||
if (!HCL_CookTime(iface->clock, hw_ts, &local_ts->ts, &local_ts->err))
|
||||
if (!rx_ntp_length && iface->tx_comp)
|
||||
UTI_AddDoubleToTimespec(hw_ts, iface->tx_comp, hw_ts);
|
||||
else if (rx_ntp_length && iface->rx_comp)
|
||||
UTI_AddDoubleToTimespec(hw_ts, -iface->rx_comp, hw_ts);
|
||||
|
||||
if (!HCL_CookTime(iface->clock, hw_ts, &ts, &err))
|
||||
return;
|
||||
|
||||
ts_delay = UTI_DiffTimespecsToDouble(&local_ts->ts, &ts);
|
||||
|
||||
if (fabs(ts_delay) > MAX_TS_DELAY) {
|
||||
DEBUG_LOG(LOGF_NtpIOLinux, "Unacceptable timestamp delay %.9f", ts_delay);
|
||||
return;
|
||||
}
|
||||
|
||||
local_ts->ts = ts;
|
||||
local_ts->err = err;
|
||||
local_ts->source = NTP_TS_HARDWARE;
|
||||
}
|
||||
|
||||
@@ -536,7 +555,7 @@ NIO_Linux_ProcessMessage(NTP_Remote_Address *remote_addr, NTP_Local_Address *loc
|
||||
if (!UTI_IsZeroTimespec(&ts3.ts[0])) {
|
||||
LCL_CookTime(&ts3.ts[0], &local_ts->ts, &local_ts->err);
|
||||
local_ts->source = NTP_TS_KERNEL;
|
||||
} else {
|
||||
} else if (!UTI_IsZeroTimespec(&ts3.ts[2])) {
|
||||
iface = get_interface(if_index);
|
||||
if (iface) {
|
||||
process_hw_timestamp(iface, &ts3.ts[2], local_ts, !is_tx ? length : 0,
|
||||
|
||||
@@ -187,6 +187,11 @@ accumulate_sample(time_t rtc, struct timespec *sys)
|
||||
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 */
|
||||
/* use sample only if n_sample is not negative*/
|
||||
|
||||
@@ -425,10 +425,11 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
||||
}
|
||||
|
||||
/* Try to replace NTP sources that are unreachable, falsetickers, or
|
||||
have root distance larger than the allowed maximum */
|
||||
have root distance or jitter larger than the allowed maximums */
|
||||
if (inst->type == SRC_NTP &&
|
||||
((!inst->reachability && inst->reachability_size == SOURCE_REACH_BITS) ||
|
||||
inst->status == SRC_FALSETICKER || inst->status == SRC_BAD_DISTANCE)) {
|
||||
inst->status == SRC_BAD_DISTANCE || inst->status == SRC_JITTERY ||
|
||||
inst->status == SRC_FALSETICKER)) {
|
||||
NSR_HandleBadSource(inst->ip_addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,7 +928,7 @@ void
|
||||
SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timespec *now)
|
||||
{
|
||||
int i, j;
|
||||
struct timespec ago;
|
||||
struct timespec last_sample_time;
|
||||
|
||||
if (inst->n_samples > 0) {
|
||||
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->stratum = inst->strata[j];
|
||||
|
||||
UTI_DiffTimespecs(&ago, now, &inst->sample_times[i]);
|
||||
report->latest_meas_ago = ago.tv_sec;
|
||||
/* Align the sample time to reduce the leak of the receive timestamp */
|
||||
last_sample_time = inst->sample_times[i];
|
||||
last_sample_time.tv_nsec = 0;
|
||||
report->latest_meas_ago = UTI_DiffTimespecsToDouble(now, &last_sample_time);
|
||||
} else {
|
||||
report->latest_meas_ago = (uint32_t)-1;
|
||||
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.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_conf="corrtimeratio 100"
|
||||
min_sync_time=8000
|
||||
max_sync_time=8500
|
||||
max_sync_time=9000
|
||||
|
||||
run_test || 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_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.lo = htonl(3);
|
||||
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;
|
||||
|
||||
/* As yet, there is no need to check for zero - all processing that
|
||||
has to detect that case is in the NTP layer */
|
||||
/* Zero is a special value */
|
||||
if (UTI_IsZeroNtp64(src)) {
|
||||
UTI_ZeroTimespec(dest);
|
||||
return;
|
||||
}
|
||||
|
||||
ntp_sec = ntohl(src->hi);
|
||||
ntp_frac = ntohl(src->lo);
|
||||
|
||||
Reference in New Issue
Block a user