mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 17:35:06 -05:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43189651b0 | ||
|
|
f518b8d00f | ||
|
|
42b3c40c32 | ||
|
|
66512ebcb3 | ||
|
|
3940d2aae3 | ||
|
|
34be117c9c | ||
|
|
7915f52495 | ||
|
|
05bd4898a9 | ||
|
|
4da088ec2f | ||
|
|
c46e0549ab | ||
|
|
8f5b308414 | ||
|
|
084fe6b0cc | ||
|
|
ebfc676d74 | ||
|
|
adaca0ff19 | ||
|
|
84d6c7a527 | ||
|
|
c43efccf02 | ||
|
|
1affd03cca | ||
|
|
276591172e | ||
|
|
989ef702aa | ||
|
|
1920b1efde | ||
|
|
bb5db828c6 | ||
|
|
dcc94a4c10 | ||
|
|
2ed72c49c9 | ||
|
|
342b588e3b | ||
|
|
a914140bd4 | ||
|
|
28e4eec1c4 | ||
|
|
5235c51801 | ||
|
|
26ea4e35e7 | ||
|
|
9397ae2b0a | ||
|
|
b8ead3485b | ||
|
|
24d28cd679 | ||
|
|
aac898343e | ||
|
|
c8c7f518b1 | ||
|
|
ce956c99a8 | ||
|
|
863866354d | ||
|
|
6e5513c80b | ||
|
|
6d0143e963 | ||
|
|
f49be7f063 | ||
|
|
7fe98a83b8 | ||
|
|
ad37c409c9 | ||
|
|
719c6f6a8a | ||
|
|
b0750136b5 | ||
|
|
ad79aec946 | ||
|
|
008dc16727 | ||
|
|
6cf9fe2f16 | ||
|
|
637b77d1bd | ||
|
|
53823b9f1c | ||
|
|
83f90279b0 | ||
|
|
02ae9a8607 | ||
|
|
017d6f8f56 | ||
|
|
eb26d13140 | ||
|
|
8d19f49341 | ||
|
|
637fa29e1e | ||
|
|
2d349595ee | ||
|
|
5cb584d6c1 | ||
|
|
d7c2b1d2f3 | ||
|
|
e11b518a1f |
@@ -37,7 +37,7 @@ GETDATE_CFLAGS = @GETDATE_CFLAGS@
|
||||
|
||||
EXTRA_OBJS = @EXTRA_OBJS@
|
||||
|
||||
OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o quantiles.o \
|
||||
OBJS = array.o cmdparse.o conf.o leapdb.o local.o logging.o main.o memory.o quantiles.o \
|
||||
reference.o regress.o rtc.o samplefilt.o sched.o socket.o sources.o sourcestats.o \
|
||||
stubs.o smooth.o sys.o sys_null.o tempcomp.o util.o $(EXTRA_OBJS)
|
||||
|
||||
|
||||
20
NEWS
20
NEWS
@@ -1,3 +1,23 @@
|
||||
New in version 4.6
|
||||
==================
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
* Add activate option to local directive to set activation threshold
|
||||
* Add ipv4 and ipv6 options to server/pool/peer directive
|
||||
* Add kod option to ratelimit directive for server KoD RATE support
|
||||
* Add leapseclist directive to read NIST/IERS leap-seconds.list file
|
||||
* Add ptpdomain directive to set PTP domain for NTP over PTP
|
||||
* Improve copy server option to accept unsynchronised status instantly
|
||||
* Log one selection failure on start
|
||||
* Add offset command to modify source offset correction
|
||||
* Add timestamp sources to ntpdata report
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
* Fix crash on sources reload during initstepslew or RTC initialisation
|
||||
* Fix source refreshment to not repeat failed name resolving attempts
|
||||
|
||||
New in version 4.5
|
||||
==================
|
||||
|
||||
|
||||
5
README
5
README
@@ -12,7 +12,7 @@ a time service to other computers in the network.
|
||||
It is designed to perform well in a wide range of conditions, including
|
||||
intermittent network connections, heavily congested networks, changing
|
||||
temperatures (ordinary computer clocks are sensitive to temperature),
|
||||
and systems that do not run continuosly, or run on a virtual machine.
|
||||
and systems that do not run continuously, 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
|
||||
@@ -89,7 +89,9 @@ Christian Ehrhardt <christian.ehrhardt@canonical.com>
|
||||
Paul Elliott <pelliott@io.com>
|
||||
Robert Fairley <rfairley@redhat.com>
|
||||
Stefan R. Filipek <srfilipek@gmail.com>
|
||||
Andy Fiddaman <illumos@fiddaman.net>
|
||||
Mike Fleetwood <mike@rockover.demon.co.uk>
|
||||
Rob Gill <rrobgill@protonmail.com>
|
||||
Alexander Gretencord <arutha@gmx.de>
|
||||
Andrew Griffiths <agriffit@redhat.com>
|
||||
Walter Haidinger <walter.haidinger@gmx.at>
|
||||
@@ -111,6 +113,7 @@ Paul Menzel <paulepanter@users.sourceforge.net>
|
||||
Vladimir Michl <vladimir.michl@seznam.cz>
|
||||
Victor Moroz <vim@prv.adlum.ru>
|
||||
Kalle Olavi Niemitalo <tosi@stekt.oulu.fi>
|
||||
Patrick Oppenlander <patrick.oppenlander@gmail.com>
|
||||
Frank Otto <sandwichmacher@web.de>
|
||||
Denny Page <dennypage@me.com>
|
||||
Rupesh Patel <rupatel@redhat.com>
|
||||
|
||||
25
candm.h
25
candm.h
@@ -110,7 +110,9 @@
|
||||
#define REQ_RELOAD_SOURCES 70
|
||||
#define REQ_DOFFSET2 71
|
||||
#define REQ_MODIFY_SELECTOPTS 72
|
||||
#define N_REQUEST_TYPES 73
|
||||
#define REQ_MODIFY_OFFSET 73
|
||||
#define REQ_LOCAL3 74
|
||||
#define N_REQUEST_TYPES 75
|
||||
|
||||
/* Structure used to exchange timespecs independent of time_t size */
|
||||
typedef struct {
|
||||
@@ -236,6 +238,8 @@ typedef struct {
|
||||
int32_t stratum;
|
||||
Float distance;
|
||||
int32_t orphan;
|
||||
Float activate;
|
||||
uint32_t reserved[2];
|
||||
int32_t EOR;
|
||||
} REQ_Local;
|
||||
|
||||
@@ -279,6 +283,8 @@ typedef struct {
|
||||
#define REQ_ADDSRC_COPY 0x400
|
||||
#define REQ_ADDSRC_EF_EXP_MONO_ROOT 0x800
|
||||
#define REQ_ADDSRC_EF_EXP_NET_CORRECTION 0x1000
|
||||
#define REQ_ADDSRC_IPV4 0x2000
|
||||
#define REQ_ADDSRC_IPV6 0x4000
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
@@ -388,6 +394,13 @@ typedef struct {
|
||||
int32_t EOR;
|
||||
} REQ_Modify_SelectOpts;
|
||||
|
||||
typedef struct {
|
||||
IPAddr address;
|
||||
uint32_t ref_id;
|
||||
Float new_offset;
|
||||
int32_t EOR;
|
||||
} REQ_Modify_Offset;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define PKT_TYPE_CMD_REQUEST 1
|
||||
@@ -495,6 +508,7 @@ typedef struct {
|
||||
REQ_AuthData auth_data;
|
||||
REQ_SelectData select_data;
|
||||
REQ_Modify_SelectOpts modify_select_opts;
|
||||
REQ_Modify_Offset modify_offset;
|
||||
} data; /* Command specific parameters */
|
||||
|
||||
/* Padding used to prevent traffic amplification. It only defines the
|
||||
@@ -538,7 +552,8 @@ typedef struct {
|
||||
#define RPY_SELECT_DATA 23
|
||||
#define RPY_SERVER_STATS3 24
|
||||
#define RPY_SERVER_STATS4 25
|
||||
#define N_REPLY_TYPES 26
|
||||
#define RPY_NTP_DATA2 26
|
||||
#define N_REPLY_TYPES 27
|
||||
|
||||
/* Status codes */
|
||||
#define STT_SUCCESS 0
|
||||
@@ -761,7 +776,11 @@ typedef struct {
|
||||
uint32_t total_rx_count;
|
||||
uint32_t total_valid_count;
|
||||
uint32_t total_good_count;
|
||||
uint32_t reserved[3];
|
||||
uint32_t total_kernel_tx_ts;
|
||||
uint32_t total_kernel_rx_ts;
|
||||
uint32_t total_hw_tx_ts;
|
||||
uint32_t total_hw_rx_ts;
|
||||
uint32_t reserved[4];
|
||||
int32_t EOR;
|
||||
} RPY_NTPData;
|
||||
|
||||
|
||||
85
client.c
85
client.c
@@ -344,6 +344,24 @@ parse_source_address(char *word, IPAddr *address)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
parse_source_address_or_refid(char *s, IPAddr *address, uint32_t *ref_id)
|
||||
{
|
||||
address->family = IPADDR_UNSPEC;
|
||||
*ref_id = 0;
|
||||
|
||||
/* Don't allow hostnames to avoid conflicts with reference IDs */
|
||||
if (UTI_StringToIdIP(s, address) || UTI_StringToIP(s, address))
|
||||
return 1;
|
||||
|
||||
if (CPS_ParseRefid(s, ref_id) > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
read_mask_address(char *line, IPAddr *mask, IPAddr *address)
|
||||
{
|
||||
@@ -737,22 +755,24 @@ static int
|
||||
process_cmd_local(CMD_Request *msg, char *line)
|
||||
{
|
||||
int on_off, stratum = 0, orphan = 0;
|
||||
double distance = 0.0;
|
||||
double distance = 0.0, activate = 0.0;
|
||||
|
||||
if (!strcmp(line, "off")) {
|
||||
on_off = 0;
|
||||
} else if (CPS_ParseLocal(line, &stratum, &orphan, &distance)) {
|
||||
} else if (CPS_ParseLocal(line, &stratum, &orphan, &distance, &activate)) {
|
||||
on_off = 1;
|
||||
} else {
|
||||
LOG(LOGS_ERR, "Invalid syntax for local command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg->command = htons(REQ_LOCAL2);
|
||||
msg->command = htons(REQ_LOCAL3);
|
||||
msg->data.local.on_off = htonl(on_off);
|
||||
msg->data.local.stratum = htonl(stratum);
|
||||
msg->data.local.distance = UTI_FloatHostToNetwork(distance);
|
||||
msg->data.local.orphan = htonl(orphan);
|
||||
msg->data.local.activate = UTI_FloatHostToNetwork(activate);
|
||||
memset(msg->data.local.reserved, 0, sizeof (msg->data.local.reserved));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -962,6 +982,8 @@ process_cmd_add_source(CMD_Request *msg, char *line)
|
||||
REQ_ADDSRC_EF_EXP_MONO_ROOT : 0) |
|
||||
(data.params.ext_fields & NTP_EF_FLAG_EXP_NET_CORRECTION ?
|
||||
REQ_ADDSRC_EF_EXP_NET_CORRECTION : 0) |
|
||||
(data.family == IPADDR_INET4 ? REQ_ADDSRC_IPV4 : 0) |
|
||||
(data.family == IPADDR_INET6 ? REQ_ADDSRC_IPV6 : 0) |
|
||||
convert_addsrc_sel_options(data.params.sel_options));
|
||||
msg->data.ntp_source.filter_length = htonl(data.params.filter_length);
|
||||
msg->data.ntp_source.cert_set = htonl(data.params.cert_set);
|
||||
@@ -1029,6 +1051,7 @@ give_help(void)
|
||||
"selectopts <address|refid> <+|-options>\0Modify selection options\0"
|
||||
"reselect\0Force reselecting synchronisation source\0"
|
||||
"reselectdist <dist>\0Modify reselection distance\0"
|
||||
"offset <address|refid> <offset>\0Modify offset correction\0"
|
||||
"\0\0"
|
||||
"NTP sources:\0\0"
|
||||
"activity\0Check how many NTP sources are online/offline\0"
|
||||
@@ -1139,7 +1162,8 @@ command_name_generator(const char *text, int state)
|
||||
"clients", "cmdaccheck", "cmdallow", "cmddeny", "cyclelogs", "delete",
|
||||
"deny", "dns", "dump", "exit", "help", "keygen", "local", "makestep",
|
||||
"manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
|
||||
"maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline",
|
||||
"maxupdateskew", "minpoll", "minstratum", "ntpdata",
|
||||
"offline", "offset", "online", "onoffline",
|
||||
"polltarget", "quit", "refresh", "rekey", "reload", "reselect", "reselectdist", "reset",
|
||||
"retries", "rtcdata", "selectdata", "selectopts", "serverstats", "settime",
|
||||
"shutdown", "smoothing", "smoothtime", "sourcename", "sources", "sourcestats",
|
||||
@@ -2329,7 +2353,7 @@ process_cmd_ntpdata(char *line)
|
||||
|
||||
request.command = htons(REQ_NTP_DATA);
|
||||
UTI_IPHostToNetwork(&remote_addr, &request.data.ntp_data.ip_addr);
|
||||
if (!request_reply(&request, &reply, RPY_NTP_DATA, 0))
|
||||
if (!request_reply(&request, &reply, RPY_NTP_DATA2, 0))
|
||||
return 0;
|
||||
|
||||
UTI_IPNetworkToHost(&reply.data.ntp_data.remote_addr, &remote_addr);
|
||||
@@ -2365,7 +2389,11 @@ process_cmd_ntpdata(char *line)
|
||||
"Total TX : %U\n"
|
||||
"Total RX : %U\n"
|
||||
"Total valid RX : %U\n"
|
||||
"Total good RX : %U\n",
|
||||
"Total good RX : %U\n"
|
||||
"Total kernel TX : %U\n"
|
||||
"Total kernel RX : %U\n"
|
||||
"Total HW TX : %U\n"
|
||||
"Total HW RX : %U\n",
|
||||
UTI_IPToString(&remote_addr), UTI_IPToRefid(&remote_addr),
|
||||
ntohs(reply.data.ntp_data.remote_port),
|
||||
UTI_IPToString(&local_addr), UTI_IPToRefid(&local_addr),
|
||||
@@ -2393,6 +2421,10 @@ process_cmd_ntpdata(char *line)
|
||||
ntohl(reply.data.ntp_data.total_rx_count),
|
||||
ntohl(reply.data.ntp_data.total_valid_count),
|
||||
ntohl(reply.data.ntp_data.total_good_count),
|
||||
ntohl(reply.data.ntp_data.total_kernel_tx_ts),
|
||||
ntohl(reply.data.ntp_data.total_kernel_rx_ts),
|
||||
ntohl(reply.data.ntp_data.total_hw_tx_ts),
|
||||
ntohl(reply.data.ntp_data.total_hw_rx_ts),
|
||||
REPORT_END);
|
||||
}
|
||||
|
||||
@@ -2848,6 +2880,34 @@ process_cmd_activity(const char *line)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
process_cmd_offset(CMD_Request *msg, char *line)
|
||||
{
|
||||
uint32_t ref_id;
|
||||
IPAddr ip_addr;
|
||||
double offset;
|
||||
char *src;
|
||||
|
||||
src = line;
|
||||
line = CPS_SplitWord(line);
|
||||
|
||||
if (!parse_source_address_or_refid(src, &ip_addr, &ref_id) ||
|
||||
sscanf(line, "%lf", &offset) != 1) {
|
||||
LOG(LOGS_ERR, "Invalid syntax for offset command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_IPHostToNetwork(&ip_addr, &msg->data.modify_offset.address);
|
||||
msg->data.modify_offset.ref_id = htonl(ref_id);
|
||||
msg->data.modify_offset.new_offset = UTI_FloatHostToNetwork(offset);
|
||||
|
||||
msg->command = htons(REQ_MODIFY_OFFSET);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
process_cmd_reselectdist(CMD_Request *msg, char *line)
|
||||
{
|
||||
@@ -2929,15 +2989,10 @@ process_cmd_selectopts(CMD_Request *msg, char *line)
|
||||
|
||||
src = line;
|
||||
line = CPS_SplitWord(line);
|
||||
ref_id = 0;
|
||||
|
||||
/* Don't allow hostnames to avoid conflicts with reference IDs */
|
||||
if (!UTI_StringToIdIP(src, &ip_addr) && !UTI_StringToIP(src, &ip_addr)) {
|
||||
ip_addr.family = IPADDR_UNSPEC;
|
||||
if (CPS_ParseRefid(src, &ref_id) == 0) {
|
||||
LOG(LOGS_ERR, "Invalid syntax for selectopts command");
|
||||
return 0;
|
||||
}
|
||||
if (!parse_source_address_or_refid(src, &ip_addr, &ref_id)) {
|
||||
LOG(LOGS_ERR, "Invalid syntax for selectopts command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mask = options = 0;
|
||||
@@ -3239,6 +3294,8 @@ process_line(char *line)
|
||||
ret = process_cmd_ntpdata(line);
|
||||
} else if (!strcmp(command, "offline")) {
|
||||
do_normal_submit = process_cmd_offline(&tx_message, line);
|
||||
} else if (!strcmp(command, "offset")) {
|
||||
do_normal_submit = process_cmd_offset(&tx_message, line);
|
||||
} else if (!strcmp(command, "online")) {
|
||||
do_normal_submit = process_cmd_online(&tx_message, line);
|
||||
} else if (!strcmp(command, "onoffline")) {
|
||||
|
||||
40
clientlog.c
40
clientlog.c
@@ -117,6 +117,14 @@ static int token_shift[MAX_SERVICES];
|
||||
|
||||
static int leak_rate[MAX_SERVICES];
|
||||
|
||||
/* Rates at which responses requesting clients to reduce their rate
|
||||
(e.g. NTP KoD RATE) are randomly allowed (in log2, but 0 means disabled) */
|
||||
|
||||
#define MIN_KOD_RATE 0
|
||||
#define MAX_KOD_RATE 4
|
||||
|
||||
static int kod_rate[MAX_SERVICES];
|
||||
|
||||
/* Limit intervals in log2 */
|
||||
static int limit_interval[MAX_SERVICES];
|
||||
|
||||
@@ -354,18 +362,19 @@ set_bucket_params(int interval, int burst, uint16_t *max_tokens,
|
||||
void
|
||||
CLG_Initialise(void)
|
||||
{
|
||||
int i, interval, burst, lrate, slots2;
|
||||
int i, interval, burst, lrate, krate, slots2;
|
||||
|
||||
for (i = 0; i < MAX_SERVICES; i++) {
|
||||
max_tokens[i] = 0;
|
||||
tokens_per_hit[i] = 0;
|
||||
token_shift[i] = 0;
|
||||
leak_rate[i] = 0;
|
||||
kod_rate[i] = 0;
|
||||
limit_interval[i] = MIN_LIMIT_INTERVAL;
|
||||
|
||||
switch (i) {
|
||||
case CLG_NTP:
|
||||
if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate))
|
||||
if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate, &krate))
|
||||
continue;
|
||||
break;
|
||||
case CLG_NTSKE:
|
||||
@@ -382,6 +391,7 @@ CLG_Initialise(void)
|
||||
|
||||
set_bucket_params(interval, burst, &max_tokens[i], &tokens_per_hit[i], &token_shift[i]);
|
||||
leak_rate[i] = CLAMP(MIN_LEAK_RATE, lrate, MAX_LEAK_RATE);
|
||||
kod_rate[i] = CLAMP(MIN_KOD_RATE, krate, MAX_KOD_RATE);
|
||||
limit_interval[i] = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
|
||||
}
|
||||
|
||||
@@ -579,28 +589,28 @@ CLG_LogServiceAccess(CLG_Service service, IPAddr *client, struct timespec *now)
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
limit_response_random(int leak_rate)
|
||||
limit_response_random(int rate)
|
||||
{
|
||||
static uint32_t rnd;
|
||||
static int bits_left = 0;
|
||||
int r;
|
||||
|
||||
if (bits_left < leak_rate) {
|
||||
if (bits_left < rate) {
|
||||
UTI_GetRandomBytes(&rnd, sizeof (rnd));
|
||||
bits_left = 8 * sizeof (rnd);
|
||||
}
|
||||
|
||||
/* Return zero on average once per 2^leak_rate */
|
||||
r = rnd % (1U << leak_rate) ? 1 : 0;
|
||||
rnd >>= leak_rate;
|
||||
bits_left -= leak_rate;
|
||||
/* Return zero on average once per 2^rate */
|
||||
r = rnd % (1U << rate) ? 1 : 0;
|
||||
rnd >>= rate;
|
||||
bits_left -= rate;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CLG_Limit
|
||||
CLG_LimitServiceRate(CLG_Service service, int index)
|
||||
{
|
||||
Record *record;
|
||||
@@ -609,14 +619,14 @@ CLG_LimitServiceRate(CLG_Service service, int index)
|
||||
check_service_number(service);
|
||||
|
||||
if (tokens_per_hit[service] == 0)
|
||||
return 0;
|
||||
return CLG_PASS;
|
||||
|
||||
record = ARR_GetElement(records, index);
|
||||
record->drop_flags &= ~(1U << service);
|
||||
|
||||
if (record->tokens[service] >= tokens_per_hit[service]) {
|
||||
record->tokens[service] -= tokens_per_hit[service];
|
||||
return 0;
|
||||
return CLG_PASS;
|
||||
}
|
||||
|
||||
drop = limit_response_random(leak_rate[service]);
|
||||
@@ -632,14 +642,18 @@ CLG_LimitServiceRate(CLG_Service service, int index)
|
||||
|
||||
if (!drop) {
|
||||
record->tokens[service] = 0;
|
||||
return 0;
|
||||
return CLG_PASS;
|
||||
}
|
||||
|
||||
if (kod_rate[service] > 0 && !limit_response_random(kod_rate[service])) {
|
||||
return CLG_KOD;
|
||||
}
|
||||
|
||||
record->drop_flags |= 1U << service;
|
||||
record->drops[service]++;
|
||||
total_drops[service]++;
|
||||
|
||||
return 1;
|
||||
return CLG_DROP;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -37,11 +37,17 @@ typedef enum {
|
||||
CLG_CMDMON,
|
||||
} CLG_Service;
|
||||
|
||||
typedef enum {
|
||||
CLG_PASS = 0,
|
||||
CLG_DROP,
|
||||
CLG_KOD,
|
||||
} CLG_Limit;
|
||||
|
||||
extern void CLG_Initialise(void);
|
||||
extern void CLG_Finalise(void);
|
||||
extern int CLG_GetClientIndex(IPAddr *client);
|
||||
extern int CLG_LogServiceAccess(CLG_Service service, IPAddr *client, struct timespec *now);
|
||||
extern int CLG_LimitServiceRate(CLG_Service service, int index);
|
||||
extern CLG_Limit CLG_LimitServiceRate(CLG_Service service, int index);
|
||||
extern void CLG_UpdateNtpStats(int auth, NTP_Timestamp_Source rx_ts_src,
|
||||
NTP_Timestamp_Source tx_ts_src);
|
||||
extern int CLG_GetNtpMinPoll(void);
|
||||
|
||||
77
cmdmon.c
77
cmdmon.c
@@ -145,6 +145,8 @@ static const char permissions[] = {
|
||||
PERMIT_AUTH, /* RELOAD_SOURCES */
|
||||
PERMIT_AUTH, /* DOFFSET2 */
|
||||
PERMIT_AUTH, /* MODIFY_SELECTOPTS */
|
||||
PERMIT_AUTH, /* MODIFY_OFFSET */
|
||||
PERMIT_AUTH, /* LOCAL3 */
|
||||
};
|
||||
|
||||
/* ================================================== */
|
||||
@@ -530,7 +532,8 @@ handle_local(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
if (ntohl(rx_message->data.local.on_off)) {
|
||||
REF_EnableLocal(ntohl(rx_message->data.local.stratum),
|
||||
UTI_FloatNetworkToHost(rx_message->data.local.distance),
|
||||
ntohl(rx_message->data.local.orphan));
|
||||
ntohl(rx_message->data.local.orphan),
|
||||
UTI_FloatNetworkToHost(rx_message->data.local.activate));
|
||||
} else {
|
||||
REF_DisableLocal();
|
||||
}
|
||||
@@ -720,9 +723,10 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
NTP_Source_Type type;
|
||||
SourceParameters params;
|
||||
int family, pool, port;
|
||||
NSR_Status status;
|
||||
uint32_t flags;
|
||||
char *name;
|
||||
int pool, port;
|
||||
|
||||
switch (ntohl(rx_message->data.ntp_source.type)) {
|
||||
case REQ_ADDSRC_SERVER:
|
||||
@@ -750,6 +754,10 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
return;
|
||||
}
|
||||
|
||||
flags = ntohl(rx_message->data.ntp_source.flags);
|
||||
|
||||
family = flags & REQ_ADDSRC_IPV4 ? IPADDR_INET4 :
|
||||
flags & REQ_ADDSRC_IPV6 ? IPADDR_INET6 : IPADDR_UNSPEC;
|
||||
port = ntohl(rx_message->data.ntp_source.port);
|
||||
params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
|
||||
params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
|
||||
@@ -775,21 +783,19 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
params.asymmetry = UTI_FloatNetworkToHost(rx_message->data.ntp_source.asymmetry);
|
||||
params.offset = UTI_FloatNetworkToHost(rx_message->data.ntp_source.offset);
|
||||
|
||||
params.connectivity = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ?
|
||||
SRC_ONLINE : SRC_OFFLINE;
|
||||
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
|
||||
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
|
||||
params.interleaved = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_INTERLEAVED ? 1 : 0;
|
||||
params.burst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_BURST ? 1 : 0;
|
||||
params.nts = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NTS ? 1 : 0;
|
||||
params.copy = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_COPY ? 1 : 0;
|
||||
params.ext_fields = (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_EF_EXP_MONO_ROOT ?
|
||||
NTP_EF_FLAG_EXP_MONO_ROOT : 0) |
|
||||
(ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_EF_EXP_NET_CORRECTION ?
|
||||
NTP_EF_FLAG_EXP_NET_CORRECTION : 0);
|
||||
params.connectivity = flags & REQ_ADDSRC_ONLINE ? SRC_ONLINE : SRC_OFFLINE;
|
||||
params.auto_offline = !!(flags & REQ_ADDSRC_AUTOOFFLINE);
|
||||
params.iburst = !!(flags & REQ_ADDSRC_IBURST);
|
||||
params.interleaved = !!(flags & REQ_ADDSRC_INTERLEAVED);
|
||||
params.burst = !!(flags & REQ_ADDSRC_BURST);
|
||||
params.nts = !!(flags & REQ_ADDSRC_NTS);
|
||||
params.copy = !!(flags & REQ_ADDSRC_COPY);
|
||||
params.ext_fields = (flags & REQ_ADDSRC_EF_EXP_MONO_ROOT ? NTP_EF_FLAG_EXP_MONO_ROOT : 0) |
|
||||
(flags & REQ_ADDSRC_EF_EXP_NET_CORRECTION ?
|
||||
NTP_EF_FLAG_EXP_NET_CORRECTION : 0);
|
||||
params.sel_options = convert_addsrc_select_options(ntohl(rx_message->data.ntp_source.flags));
|
||||
|
||||
status = NSR_AddSourceByName(name, port, pool, type, ¶ms, NULL);
|
||||
status = NSR_AddSourceByName(name, family, port, pool, type, ¶ms, NULL);
|
||||
switch (status) {
|
||||
case NSR_Success:
|
||||
break;
|
||||
@@ -807,6 +813,8 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
tx_message->status = htons(STT_INVALIDNAME);
|
||||
break;
|
||||
case NSR_InvalidAF:
|
||||
tx_message->status = htons(STT_INVALIDAF);
|
||||
break;
|
||||
case NSR_NoSuchSource:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -1225,7 +1233,7 @@ handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
return;
|
||||
}
|
||||
|
||||
tx_message->reply = htons(RPY_NTP_DATA);
|
||||
tx_message->reply = htons(RPY_NTP_DATA2);
|
||||
UTI_IPHostToNetwork(&report.remote_addr, &tx_message->data.ntp_data.remote_addr);
|
||||
UTI_IPHostToNetwork(&report.local_addr, &tx_message->data.ntp_data.local_addr);
|
||||
tx_message->data.ntp_data.remote_port = htons(report.remote_port);
|
||||
@@ -1253,6 +1261,10 @@ handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
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_good_count = htonl(report.total_good_count);
|
||||
tx_message->data.ntp_data.total_kernel_tx_ts = htonl(report.total_kernel_tx_ts);
|
||||
tx_message->data.ntp_data.total_kernel_rx_ts = htonl(report.total_kernel_rx_ts);
|
||||
tx_message->data.ntp_data.total_hw_tx_ts = htonl(report.total_hw_tx_ts);
|
||||
tx_message->data.ntp_data.total_hw_rx_ts = htonl(report.total_hw_rx_ts);
|
||||
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
|
||||
}
|
||||
|
||||
@@ -1409,6 +1421,24 @@ handle_modify_selectopts(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
handle_modify_offset(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||
{
|
||||
uint32_t ref_id;
|
||||
IPAddr ip_addr;
|
||||
double offset;
|
||||
|
||||
UTI_IPNetworkToHost(&rx_message->data.modify_offset.address, &ip_addr);
|
||||
ref_id = ntohl(rx_message->data.modify_offset.ref_id);
|
||||
offset = UTI_FloatNetworkToHost(rx_message->data.modify_offset.new_offset);
|
||||
|
||||
if ((ip_addr.family != IPADDR_UNSPEC && !NSR_ModifyOffset(&ip_addr, offset)) ||
|
||||
(ip_addr.family == IPADDR_UNSPEC && !RCL_ModifyOffset(ref_id, offset)))
|
||||
tx_message->status = htons(STT_NOSUCHSOURCE);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Read a packet and process it */
|
||||
|
||||
@@ -1483,9 +1513,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
||||
|
||||
/* Don't reply to all requests from hosts other than localhost if the rate
|
||||
is excessive */
|
||||
if (!localhost && log_index >= 0 && CLG_LimitServiceRate(CLG_CMDMON, log_index)) {
|
||||
DEBUG_LOG("Command packet discarded to limit response rate");
|
||||
return;
|
||||
if (!localhost && log_index >= 0 &&
|
||||
CLG_LimitServiceRate(CLG_CMDMON, log_index) != CLG_PASS) {
|
||||
DEBUG_LOG("Command packet discarded to limit response rate");
|
||||
return;
|
||||
}
|
||||
|
||||
expected_length = PKL_CommandLength(&rx_message);
|
||||
@@ -1620,8 +1651,8 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
||||
case REQ_SETTIME:
|
||||
handle_settime(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_LOCAL2:
|
||||
|
||||
case REQ_LOCAL3:
|
||||
handle_local(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
@@ -1809,6 +1840,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
||||
handle_modify_selectopts(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_MODIFY_OFFSET:
|
||||
handle_modify_offset(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_LOG("Unhandled command %d", rx_command);
|
||||
tx_message.status = htons(STT_FAILED);
|
||||
|
||||
11
cmdparse.c
11
cmdparse.c
@@ -46,6 +46,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
||||
uint32_t ef_type;
|
||||
int n, sel_option;
|
||||
|
||||
src->family = IPADDR_UNSPEC;
|
||||
src->port = SRC_DEFAULT_PORT;
|
||||
src->params.minpoll = SRC_DEFAULT_MINPOLL;
|
||||
src->params.maxpoll = SRC_DEFAULT_MAXPOLL;
|
||||
@@ -127,6 +128,10 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
||||
} else if (!strcasecmp(cmd, "filter")) {
|
||||
if (sscanf(line, "%d%n", &src->params.filter_length, &n) != 1)
|
||||
return 0;
|
||||
} else if (!strcasecmp(cmd, "ipv4")) {
|
||||
src->family = IPADDR_INET4;
|
||||
} else if (!strcasecmp(cmd, "ipv6")) {
|
||||
src->family = IPADDR_INET6;
|
||||
} else if (!strcasecmp(cmd, "maxdelay")) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1)
|
||||
return 0;
|
||||
@@ -291,13 +296,14 @@ CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits)
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
||||
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance, double *activate)
|
||||
{
|
||||
int n;
|
||||
char *cmd;
|
||||
|
||||
*stratum = 10;
|
||||
*distance = 1.0;
|
||||
*activate = 0.0;
|
||||
*orphan = 0;
|
||||
|
||||
while (*line) {
|
||||
@@ -314,6 +320,9 @@ CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
||||
} else if (!strcasecmp(cmd, "distance")) {
|
||||
if (sscanf(line, "%lf%n", distance, &n) != 1)
|
||||
return 0;
|
||||
} else if (!strcasecmp(cmd, "activate")) {
|
||||
if (sscanf(line, "%lf%n", activate, &n) != 1)
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int family;
|
||||
int port;
|
||||
SourceParameters params;
|
||||
} CPS_NTP_Source;
|
||||
@@ -46,7 +47,7 @@ extern int CPS_GetSelectOption(char *option);
|
||||
extern int CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits);
|
||||
|
||||
/* Parse a command to enable local reference */
|
||||
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance);
|
||||
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance, double *activate);
|
||||
|
||||
/* Remove extra white-space and comments */
|
||||
extern void CPS_NormalizeLine(char *line);
|
||||
|
||||
70
conf.c
70
conf.c
@@ -79,7 +79,7 @@ static void parse_maxchange(char *);
|
||||
static void parse_ntsserver(char *, ARR_Instance files);
|
||||
static void parse_ntstrustedcerts(char *);
|
||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||
int *burst, int *leak);
|
||||
int *burst, int *leak, int *kod);
|
||||
static void parse_refclock(char *);
|
||||
static void parse_smoothtime(char *);
|
||||
static void parse_source(char *line, char *type, int fatal);
|
||||
@@ -129,6 +129,7 @@ static int enable_local=0;
|
||||
static int local_stratum;
|
||||
static int local_orphan;
|
||||
static double local_distance;
|
||||
static double local_activate;
|
||||
|
||||
/* Threshold (in seconds) - if absolute value of initial error is less
|
||||
than this, slew instead of stepping */
|
||||
@@ -220,6 +221,7 @@ 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 ntp_ratelimit_kod = 0;
|
||||
static int nts_ratelimit_enabled = 0;
|
||||
static int nts_ratelimit_interval = 6;
|
||||
static int nts_ratelimit_burst = 8;
|
||||
@@ -249,6 +251,9 @@ static REF_LeapMode leapsec_mode = REF_LeapModeSystem;
|
||||
/* Name of a system timezone containing leap seconds occuring at midnight */
|
||||
static char *leapsec_tz = NULL;
|
||||
|
||||
/* File name of leap seconds list, usually /usr/share/zoneinfo/leap-seconds.list */
|
||||
static char *leapsec_list = NULL;
|
||||
|
||||
/* Name of the user to which will be dropped root privileges. */
|
||||
static char *user;
|
||||
|
||||
@@ -282,6 +287,8 @@ static double hwts_timeout = 0.001;
|
||||
|
||||
/* PTP event port (disabled by default) */
|
||||
static int ptp_port = 0;
|
||||
/* PTP domain number of NTP-over-PTP messages */
|
||||
static int ptp_domain = 123;
|
||||
|
||||
typedef struct {
|
||||
NTP_Source_Type type;
|
||||
@@ -295,6 +302,8 @@ static ARR_Instance ntp_sources;
|
||||
static ARR_Instance ntp_source_dirs;
|
||||
/* Array of uint32_t corresponding to ntp_sources (for sourcedirs reload) */
|
||||
static ARR_Instance ntp_source_ids;
|
||||
/* Flag indicating ntp_sources and ntp_source_ids are used for sourcedirs */
|
||||
static int conf_ntp_sources_added = 0;
|
||||
|
||||
/* Array of RefclockParameters */
|
||||
static ARR_Instance refclock_sources;
|
||||
@@ -471,6 +480,7 @@ CNF_Finalise(void)
|
||||
Free(hwclock_file);
|
||||
Free(keys_file);
|
||||
Free(leapsec_tz);
|
||||
Free(leapsec_list);
|
||||
Free(logdir);
|
||||
Free(bind_ntp_iface);
|
||||
Free(bind_acq_iface);
|
||||
@@ -585,7 +595,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
parse_int(p, &cmd_port);
|
||||
} else if (!strcasecmp(command, "cmdratelimit")) {
|
||||
parse_ratelimit(p, &cmd_ratelimit_enabled, &cmd_ratelimit_interval,
|
||||
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
|
||||
&cmd_ratelimit_burst, &cmd_ratelimit_leak, NULL);
|
||||
} else if (!strcasecmp(command, "combinelimit")) {
|
||||
parse_double(p, &combine_limit);
|
||||
} else if (!strcasecmp(command, "confdir")) {
|
||||
@@ -620,6 +630,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
parse_leapsecmode(p);
|
||||
} else if (!strcasecmp(command, "leapsectz")) {
|
||||
parse_string(p, &leapsec_tz);
|
||||
} else if (!strcasecmp(command, "leapseclist")) {
|
||||
parse_string(p, &leapsec_list);
|
||||
} else if (!strcasecmp(command, "local")) {
|
||||
parse_local(p);
|
||||
} else if (!strcasecmp(command, "lock_all")) {
|
||||
@@ -670,7 +682,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
parse_string(p, &ntp_signd_socket);
|
||||
} else if (!strcasecmp(command, "ntsratelimit")) {
|
||||
parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
|
||||
&nts_ratelimit_burst, &nts_ratelimit_leak);
|
||||
&nts_ratelimit_burst, &nts_ratelimit_leak, NULL);
|
||||
} else if (!strcasecmp(command, "ntscachedir") ||
|
||||
!strcasecmp(command, "ntsdumpdir")) {
|
||||
parse_string(p, &nts_dump_dir);
|
||||
@@ -698,11 +710,13 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||
parse_source(p, command, 1);
|
||||
} else if (!strcasecmp(command, "port")) {
|
||||
parse_int(p, &ntp_port);
|
||||
} else if (!strcasecmp(command, "ptpdomain")) {
|
||||
parse_int(p, &ptp_domain);
|
||||
} else if (!strcasecmp(command, "ptpport")) {
|
||||
parse_int(p, &ptp_port);
|
||||
} else if (!strcasecmp(command, "ratelimit")) {
|
||||
parse_ratelimit(p, &ntp_ratelimit_enabled, &ntp_ratelimit_interval,
|
||||
&ntp_ratelimit_burst, &ntp_ratelimit_leak);
|
||||
&ntp_ratelimit_burst, &ntp_ratelimit_leak, &ntp_ratelimit_kod);
|
||||
} else if (!strcasecmp(command, "refclock")) {
|
||||
parse_refclock(p);
|
||||
} else if (!strcasecmp(command, "refresh")) {
|
||||
@@ -840,7 +854,7 @@ parse_sourcedir(char *line)
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
|
||||
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak, int *kod)
|
||||
{
|
||||
int n, val;
|
||||
char *opt;
|
||||
@@ -861,6 +875,8 @@ parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
|
||||
*burst = val;
|
||||
else if (!strcasecmp(opt, "leak"))
|
||||
*leak = val;
|
||||
else if (!strcasecmp(opt, "kod") && kod)
|
||||
*kod = val;
|
||||
else
|
||||
command_parse_error();
|
||||
}
|
||||
@@ -1058,7 +1074,7 @@ parse_log(char *line)
|
||||
static void
|
||||
parse_local(char *line)
|
||||
{
|
||||
if (!CPS_ParseLocal(line, &local_stratum, &local_orphan, &local_distance))
|
||||
if (!CPS_ParseLocal(line, &local_stratum, &local_orphan, &local_distance, &local_activate))
|
||||
command_parse_error();
|
||||
enable_local = 1;
|
||||
}
|
||||
@@ -1664,6 +1680,8 @@ compare_sources(const void *a, const void *b)
|
||||
return d;
|
||||
if ((d = (int)sa->pool - (int)sb->pool) != 0)
|
||||
return d;
|
||||
if ((d = (int)sa->params.family - (int)sb->params.family) != 0)
|
||||
return d;
|
||||
if ((d = (int)sa->params.port - (int)sb->params.port) != 0)
|
||||
return d;
|
||||
return memcmp(&sa->params.params, &sb->params.params, sizeof (sa->params.params));
|
||||
@@ -1681,8 +1699,12 @@ reload_source_dirs(void)
|
||||
NSR_Status s;
|
||||
int d, pass;
|
||||
|
||||
/* Ignore reload command before adding configured sources */
|
||||
if (!conf_ntp_sources_added)
|
||||
return;
|
||||
|
||||
prev_size = ARR_GetSize(ntp_source_ids);
|
||||
if (prev_size > 0 && ARR_GetSize(ntp_sources) != prev_size)
|
||||
if (ARR_GetSize(ntp_sources) != prev_size)
|
||||
assert(0);
|
||||
|
||||
/* Save the current sources and their configuration IDs */
|
||||
@@ -1728,8 +1750,9 @@ reload_source_dirs(void)
|
||||
/* Add new sources */
|
||||
if (pass == 1 && d > 0) {
|
||||
source = &new_sources[j];
|
||||
s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool,
|
||||
source->type, &source->params.params, &new_ids[j]);
|
||||
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
|
||||
source->pool, source->type, &source->params.params,
|
||||
&new_ids[j]);
|
||||
|
||||
if (s == NSR_UnresolvedName) {
|
||||
unresolved++;
|
||||
@@ -1842,15 +1865,18 @@ CNF_AddSources(void)
|
||||
for (i = 0; i < ARR_GetSize(ntp_sources); i++) {
|
||||
source = (NTP_Source *)ARR_GetElement(ntp_sources, i);
|
||||
|
||||
s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool,
|
||||
source->type, &source->params.params, NULL);
|
||||
s = NSR_AddSourceByName(source->params.name, source->params.family, source->params.port,
|
||||
source->pool, source->type, &source->params.params, NULL);
|
||||
if (s != NSR_Success && s != NSR_UnresolvedName)
|
||||
LOG(LOGS_ERR, "Could not add source %s", source->params.name);
|
||||
|
||||
Free(source->params.name);
|
||||
}
|
||||
|
||||
/* The arrays will be used for sourcedir (re)loading */
|
||||
ARR_SetSize(ntp_sources, 0);
|
||||
ARR_SetSize(ntp_source_ids, 0);
|
||||
conf_ntp_sources_added = 1;
|
||||
|
||||
reload_source_dirs();
|
||||
}
|
||||
@@ -2148,12 +2174,13 @@ CNF_GetCommandPort(void) {
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CNF_AllowLocalReference(int *stratum, int *orphan, double *distance)
|
||||
CNF_AllowLocalReference(int *stratum, int *orphan, double *distance, double *activate)
|
||||
{
|
||||
if (enable_local) {
|
||||
*stratum = local_stratum;
|
||||
*orphan = local_orphan;
|
||||
*distance = local_distance;
|
||||
*activate = local_activate;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -2386,6 +2413,14 @@ CNF_GetLeapSecTimezone(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CNF_GetLeapSecList(void)
|
||||
{
|
||||
return leapsec_list;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CNF_GetSchedPriority(void)
|
||||
{
|
||||
@@ -2402,11 +2437,12 @@ CNF_GetLockMemory(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
|
||||
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod)
|
||||
{
|
||||
*interval = ntp_ratelimit_interval;
|
||||
*burst = ntp_ratelimit_burst;
|
||||
*leak = ntp_ratelimit_leak;
|
||||
*kod = ntp_ratelimit_kod;
|
||||
return ntp_ratelimit_enabled;
|
||||
}
|
||||
|
||||
@@ -2540,6 +2576,14 @@ CNF_GetPtpPort(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CNF_GetPtpDomain(void)
|
||||
{
|
||||
return ptp_domain;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
CNF_GetRefresh(void)
|
||||
{
|
||||
|
||||
6
conf.h
6
conf.h
@@ -91,6 +91,7 @@ extern char *CNF_GetNtpSigndSocket(void);
|
||||
extern char *CNF_GetPidFile(void);
|
||||
extern REF_LeapMode CNF_GetLeapSecMode(void);
|
||||
extern char *CNF_GetLeapSecTimezone(void);
|
||||
extern char *CNF_GetLeapSecList(void);
|
||||
|
||||
/* Value returned in ppm, as read from file */
|
||||
extern double CNF_GetMaxUpdateSkew(void);
|
||||
@@ -107,14 +108,14 @@ extern double CNF_GetReselectDistance(void);
|
||||
extern double CNF_GetStratumWeight(void);
|
||||
extern double CNF_GetCombineLimit(void);
|
||||
|
||||
extern int CNF_AllowLocalReference(int *stratum, int *orphan, double *distance);
|
||||
extern int CNF_AllowLocalReference(int *stratum, int *orphan, double *distance, double *activate);
|
||||
|
||||
extern void CNF_SetupAccessRestrictions(void);
|
||||
|
||||
extern int CNF_GetSchedPriority(void);
|
||||
extern int CNF_GetLockMemory(void);
|
||||
|
||||
extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
|
||||
extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod);
|
||||
extern int CNF_GetNtsRateLimit(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);
|
||||
@@ -158,6 +159,7 @@ extern int CNF_GetHwTsInterface(unsigned int index, CNF_HwTsInterface **iface);
|
||||
extern double CNF_GetHwTsTimeout(void);
|
||||
|
||||
extern int CNF_GetPtpPort(void);
|
||||
extern int CNF_GetPtpDomain(void);
|
||||
|
||||
extern int CNF_GetRefresh(void);
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ when disconnecting the network link. (It will still be necessary to use the
|
||||
<<chronyc.adoc#online,*online*>> command when the link has been established, to
|
||||
enable measurements to start.)
|
||||
*prefer*:::
|
||||
Prefer this source over sources without the *prefer* option.
|
||||
Prefer this source over other selectable sources without the *prefer* option.
|
||||
*noselect*:::
|
||||
Never select this source. This is particularly useful for monitoring.
|
||||
*trust*:::
|
||||
@@ -343,6 +343,12 @@ the PTP port. The corrections are applied only to NTP measurements with HW
|
||||
timestamps (enabled by the <<hwtimestamp,*hwtimestamp*>> directive). This
|
||||
field should be enabled only for servers known to be running *chronyd* version
|
||||
4.5 or later.
|
||||
*ipv4*:::
|
||||
*ipv6*:::
|
||||
These options force *chronyd* to use only IPv4 or IPv6 addresses respectively
|
||||
for this source. They do not override the *-4* or *-6* option on the *chronyd*
|
||||
command line.
|
||||
|
||||
{blank}:::
|
||||
|
||||
[[pool]]*pool* _name_ [_option_]...::
|
||||
@@ -655,7 +661,7 @@ default is 64. With drivers that perform their own polling (PPS, PHC, SHM), the
|
||||
maximum value is adjusted to the number of driver polls per source poll, i.e.
|
||||
2^(_poll_ - _dpoll_).
|
||||
*prefer*:::
|
||||
Prefer this source over sources without the prefer option.
|
||||
Prefer this source over other selectable sources without the *prefer* option.
|
||||
*noselect*:::
|
||||
Never select this source. This is useful for monitoring or with sources which
|
||||
are not very accurate, but are locked with a PPS refclock.
|
||||
@@ -674,9 +680,10 @@ trusted and required source.
|
||||
*tai*:::
|
||||
This option indicates that the reference clock keeps time in TAI instead of UTC
|
||||
and that *chronyd* should correct its offset by the current TAI-UTC offset. The
|
||||
<<leapsectz,*leapsectz*>> directive must be used with this option and the
|
||||
database must be kept up to date in order for this correction to work as
|
||||
expected. This option does not make sense with PPS refclocks.
|
||||
<<leapsectz,*leapsectz*>> or <<leapseclist,*leapseclist*>> directive must be
|
||||
used with this option and the database must be kept up to date in order for
|
||||
this correction to work as expected. This option does not make sense with PPS
|
||||
refclocks.
|
||||
*local*:::
|
||||
This option specifies that the reference clock is an unsynchronised clock which
|
||||
is more stable than the system clock (e.g. TCXO, OCXO, or atomic clock) and
|
||||
@@ -1263,6 +1270,19 @@ $ TZ=right/UTC date -d 'Dec 31 2008 23:59:60'
|
||||
Wed Dec 31 23:59:60 UTC 2008
|
||||
----
|
||||
|
||||
[[leapseclist]]*leapseclist* _file_::
|
||||
This directive specifies the path to a file containing a list of leap seconds
|
||||
and TAI-UTC offsets in NIST/IERS format. It is recommended to use
|
||||
the file _leap-seconds.list_ usually included with the system timezone
|
||||
database. The behaviour of this directive is otherwise equivalent to
|
||||
<<leapsectz,*leapsectz*>>.
|
||||
+
|
||||
An example of this directive is:
|
||||
+
|
||||
----
|
||||
leapseclist /usr/share/zoneinfo/leap-seconds.list
|
||||
----
|
||||
|
||||
[[makestep]]*makestep* _threshold_ _limit_::
|
||||
Normally *chronyd* will cause the system to gradually correct any time offset,
|
||||
by slowing down or speeding up the clock as required. In certain situations,
|
||||
@@ -1655,6 +1675,14 @@ The current root distance can be calculated from root delay and root dispersion
|
||||
----
|
||||
distance = delay / 2 + dispersion
|
||||
----
|
||||
*activate* _distance_:::
|
||||
This option sets an activating root distance for the local reference. The
|
||||
local reference will not be used until the root distance drops below the
|
||||
configured value for the first time. This can be used to prevent the local
|
||||
reference from being activated on a server which has never been synchronised
|
||||
with an upstream server. The default value of 0.0 causes no activating
|
||||
distance to be used, such that the local reference is always eligible for
|
||||
activation.
|
||||
*orphan*:::
|
||||
This option enables a special '`orphan`' mode, where sources with stratum equal
|
||||
to the local _stratum_ are assumed to not serve real time. They are ignored
|
||||
@@ -1677,7 +1705,7 @@ The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
local stratum 10 orphan distance 0.1
|
||||
local stratum 10 orphan distance 0.1 activate 0.5
|
||||
----
|
||||
|
||||
[[ntpsigndsocket]]*ntpsigndsocket* _directory_::
|
||||
@@ -1841,6 +1869,14 @@ 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 1 and the
|
||||
maximum value is 4.
|
||||
*kod* _rate_:::
|
||||
This option sets the rate at which Kiss-o'-Death (KoD) RATE responses are
|
||||
randomly sent when the limits specified by the *interval* and *burst* options
|
||||
are exceeded. It is an additional stream of responses to the *leak* option. A
|
||||
KoD RATE response is a request for the client to reduce its polling rate. Few
|
||||
implementations actually support it. The rate is defined as a power of 1/2. The
|
||||
default value is 0, which means disabled. The minimum value is 0 and the
|
||||
maximum value is 4.
|
||||
{blank}::
|
||||
+
|
||||
An example use of the directive is:
|
||||
@@ -1856,7 +1892,7 @@ packets, by up to 75% (with default *leak* of 2).
|
||||
[[ntsratelimit]]*ntsratelimit* [_option_]...::
|
||||
This directive enables rate limiting of NTS-KE requests. It is similar to the
|
||||
<<ratelimit,*ratelimit*>> directive, except the default interval is 6
|
||||
(1 connection per 64 seconds).
|
||||
(1 connection per 64 seconds) and the *kod* option is not supported.
|
||||
+
|
||||
An example of the use of the directive is:
|
||||
+
|
||||
@@ -2004,8 +2040,8 @@ need to be run with the *-p 257* option to inter-operate correctly.)
|
||||
[[cmdratelimit]]*cmdratelimit* [_option_]...::
|
||||
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).
|
||||
localhost are never limited, the default interval is -4 (16 packets per
|
||||
second), and the *kod* option is not supported.
|
||||
+
|
||||
An example of the use of the directive is:
|
||||
+
|
||||
@@ -2143,8 +2179,8 @@ from the example line above):
|
||||
. Results of the *maxdelay*, *maxdelayratio*, and *maxdelaydevratio* (or
|
||||
*maxdelayquant*) tests, and a test for synchronisation loop (1=pass,
|
||||
0=fail). The first test from these four also checks the server precision,
|
||||
response time, and whether an interleaved response is acceptable for
|
||||
synchronisation. [1111]
|
||||
response time, validity of the measured offset, and whether an interleaved
|
||||
response is acceptable for synchronisation. [1111]
|
||||
. Local poll [10]
|
||||
. Remote poll [10]
|
||||
. '`Score`' (an internal score within each polling level used to decide when to
|
||||
@@ -2766,6 +2802,11 @@ hwtimestamp * rxfilter ptp
|
||||
ptpport 319
|
||||
----
|
||||
|
||||
[[ptpdomain]]*ptpdomain* _domain_::
|
||||
The *ptpdomain* directive sets the PTP domain number of transmitted and
|
||||
accepted NTP-over-PTP messages. Messages from other domains are ignored.
|
||||
The default is 123, the minimum is 0, and the maximum is 255.
|
||||
|
||||
[[sched_priority]]*sched_priority* _priority_::
|
||||
On Linux, FreeBSD, NetBSD, and illumos, the *sched_priority* directive will
|
||||
select the SCHED_FIFO real-time scheduler at the specified priority (which must
|
||||
|
||||
@@ -459,8 +459,8 @@ states are reported.
|
||||
The following states indicate the source is not considered selectable for
|
||||
synchronisation:
|
||||
* _N_ - has the *noselect* option.
|
||||
* _s_ - is not synchronised.
|
||||
* _M_ - does not have enough measurements.
|
||||
* _s_ - is not synchronised.
|
||||
* _d_ - has a root distance larger than the maximum distance (configured by the
|
||||
<<chrony.conf.adoc#maxdistance,*maxdistance*>> directive).
|
||||
* _~_ - has a jitter larger than the maximum jitter (configured by the
|
||||
@@ -492,7 +492,7 @@ local clock:
|
||||
This column shows the name or IP address of the source if it is an NTP server,
|
||||
or the reference ID if it is a reference clock.
|
||||
*Auth*:::
|
||||
This column indicites whether an authentication mechanism is enabled for the
|
||||
This column indicates whether an authentication mechanism is enabled for the
|
||||
source. _Y_ means yes and _N_ means no.
|
||||
*COpts*:::
|
||||
This column displays the configured selection options of the source.
|
||||
@@ -556,6 +556,13 @@ The *reselectdist* command sets the reselection distance. It is equivalent to
|
||||
the <<chrony.conf.adoc#reselectdist,*reselectdist*>> directive in the
|
||||
configuration file.
|
||||
|
||||
[[offset]]*offset* _address|refid_ _offset_::
|
||||
The *offset* command modifies the offset correction of an NTP source specified
|
||||
by IP address (or the _ID#XXXXXXXXXX_ identifier used for unknown addresses),
|
||||
or a reference clock specified by reference ID as a string. It is equivalent to
|
||||
the *offset* option in the <<chrony.conf.adoc#server,*server*>> or
|
||||
<<chrony.conf.adoc#refclock,*refclock*>> directive respectively.
|
||||
|
||||
=== NTP sources
|
||||
|
||||
[[activity]]*activity*::
|
||||
@@ -689,6 +696,10 @@ Total TX : 24
|
||||
Total RX : 24
|
||||
Total valid RX : 24
|
||||
Total good RX : 22
|
||||
Total kernel TX : 24
|
||||
Total kernel RX : 24
|
||||
Total HW TX : 0
|
||||
Total HW RX : 0
|
||||
----
|
||||
+
|
||||
The fields are explained as follows:
|
||||
@@ -746,6 +757,18 @@ The number of packets which passed the first two groups of NTP tests.
|
||||
*Total good RX*:::
|
||||
The number of packets which passed all three groups of NTP tests, i.e. the NTP
|
||||
measurement was accepted.
|
||||
*Total kernel TX*:::
|
||||
The number of packets sent to the source for which a timestamp was captured by
|
||||
the kernel.
|
||||
*Total kernel RX*:::
|
||||
The number of packets received from the source for which a timestamp was
|
||||
captured by the kernel.
|
||||
*Total HW TX*:::
|
||||
The number of packets sent to the source for which a timestamp was captured by
|
||||
the NIC.
|
||||
*Total HW RX*:::
|
||||
The number of packets received from the source for which a timestamp was
|
||||
captured by the NIC.
|
||||
|
||||
[[add_peer]]*add peer* _name_ [_option_]...::
|
||||
The *add peer* command allows a new NTP peer to be added whilst
|
||||
|
||||
74
doc/contributing.adoc
Normal file
74
doc/contributing.adoc
Normal file
@@ -0,0 +1,74 @@
|
||||
// This file is part of chrony
|
||||
//
|
||||
// Copyright (C) Miroslav Lichvar 2024
|
||||
//
|
||||
// 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.
|
||||
|
||||
= Contributing
|
||||
|
||||
== Patches
|
||||
|
||||
The source code of `chrony` is maintained in a git repository at
|
||||
https://gitlab.com/chrony/chrony. Patches can be submitted to the `chrony-dev`
|
||||
mailing list, or as a merge request on gitlab. Before spending a lot of time
|
||||
implementing a new major feature, it is recommended to ask on the mailing list
|
||||
for comments about its design and whether such feature fits the goals of the
|
||||
project.
|
||||
|
||||
Each commit should be a self-contained logical change, which does not break
|
||||
the build or tests. New functionality and fixed bugs should be covered by a new
|
||||
test or an extended existing test in the test suite. The test can be included
|
||||
in the same commit or added as a separate commit. The same rule applies to
|
||||
documentation. All command-line options, configuration directives, and
|
||||
`chronyc` commands should be documented.
|
||||
|
||||
The most important tests can be executed by running `make check` or `make
|
||||
quickcheck`. The unit and system tests run on all supported systems. The system
|
||||
tests require root privileges. The simulation tests run only on Linux and
|
||||
require https://gitlab.com/chrony/clknetsim[clknetsim] to be compiled in the
|
||||
directory containing the tests, but they are executed with a merge request on
|
||||
gitlab.
|
||||
|
||||
The commit message should explain any non-trivial changes, e.g. what problem is
|
||||
the commit solving and how. The commit subject (first line of the message)
|
||||
should be written in an imperative form, prefixed with the component name if it
|
||||
is not a more general change, starting in lower case, and no period at the end.
|
||||
See the git log for examples.
|
||||
|
||||
Simpler code is better. Less code is better. Security is a top priority.
|
||||
|
||||
Assertions should catch only bugs in the `chrony` code. Unexpected values in
|
||||
external input (e.g. anything received from network) must be handled correctly
|
||||
without crashing and memory corruption. Fuzzing support is available at
|
||||
https://gitlab.com/chrony/chrony-fuzz. The fuzzing coverage is checked by the
|
||||
project maintainer before each release.
|
||||
|
||||
The code should mostly be self-documenting. Comments should explain the
|
||||
less obvious things.
|
||||
|
||||
== Coding style
|
||||
|
||||
The code uses two spaces for indentation. No tabs. The line length should
|
||||
normally not exceed 95 characters. Too much indentation indicates the code will
|
||||
not be very readable.
|
||||
|
||||
Function names are in an imperative form. Names of static functions use
|
||||
lowercase characters and underscores. Public functions, structures, typedefs
|
||||
are in CamelCase with a prefix specific to the module (e.g. LCL - local, NCR
|
||||
- NTP core, NKS - NTS-KE server, SST - sourcestats).
|
||||
|
||||
Function names are not followed by space, but keywords of the language (e.g.
|
||||
`if`, `for`, `while`, `sizeof`) are followed by space.
|
||||
|
||||
Have a look at the existing code to get a better idea what is expected.
|
||||
@@ -37,8 +37,8 @@ ntsdumpdir /var/lib/chrony
|
||||
# Insert/delete leap seconds by slewing instead of stepping.
|
||||
#leapsecmode slew
|
||||
|
||||
# Get TAI-UTC offset and leap seconds from the system tz database.
|
||||
#leapsectz right/UTC
|
||||
# Set the TAI-UTC offset of the system clock.
|
||||
#leapseclist /usr/share/zoneinfo/leap-seconds.list
|
||||
|
||||
# Specify directory for log files.
|
||||
logdir /var/log/chrony
|
||||
|
||||
@@ -126,11 +126,11 @@ ntsdumpdir /var/lib/chrony
|
||||
|
||||
! pidfile /var/run/chrony/chronyd.pid
|
||||
|
||||
# If the system timezone database is kept up to date and includes the
|
||||
# right/UTC timezone, chronyd can use it to determine the current
|
||||
# TAI-UTC offset and when will the next leap second occur.
|
||||
# The system timezone database usually comes with a list of leap seconds and
|
||||
# corresponding TAI-UTC offsets. chronyd can use it to set the offset of the
|
||||
# system TAI clock and have an additional source of leap seconds.
|
||||
|
||||
! leapsectz right/UTC
|
||||
! leapseclist /usr/share/zoneinfo/leap-seconds.list
|
||||
|
||||
#######################################################################
|
||||
### INITIAL CLOCK CORRECTION
|
||||
|
||||
@@ -943,6 +943,7 @@ get_date (const char *p, const time_t *now)
|
||||
tm.tm_hour += yyRelHour;
|
||||
tm.tm_min += yyRelMinutes;
|
||||
tm.tm_sec += yyRelSeconds;
|
||||
tm.tm_wday = 0;
|
||||
|
||||
/* Let mktime deduce tm_isdst if we have an absolute timestamp,
|
||||
or if the relative timestamp mentions days, months, or years. */
|
||||
|
||||
272
leapdb.c
Normal file
272
leapdb.c
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022
|
||||
* Copyright (C) Patrick Oppenlander 2023, 2024
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
This module provides leap second information. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "conf.h"
|
||||
#include "leapdb.h"
|
||||
#include "logging.h"
|
||||
#include "util.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Source of leap second data */
|
||||
enum {
|
||||
SRC_NONE,
|
||||
SRC_TIMEZONE,
|
||||
SRC_LIST,
|
||||
} leap_src;
|
||||
|
||||
/* Offset between leap-seconds.list timestamp epoch and Unix epoch.
|
||||
leap-seconds.list epoch is 1 Jan 1900, 00:00:00 */
|
||||
#define LEAP_SEC_LIST_OFFSET 2208988800
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static NTP_Leap
|
||||
get_tz_leap(time_t when, int *tai_offset)
|
||||
{
|
||||
struct tm stm, *tm;
|
||||
time_t t;
|
||||
char *tz_env, tz_orig[128];
|
||||
NTP_Leap tz_leap = LEAP_Normal;
|
||||
|
||||
tm = gmtime(&when);
|
||||
if (!tm)
|
||||
return tz_leap;
|
||||
|
||||
stm = *tm;
|
||||
|
||||
/* Temporarily switch to the timezone containing leap seconds */
|
||||
tz_env = getenv("TZ");
|
||||
if (tz_env) {
|
||||
if (strlen(tz_env) >= sizeof (tz_orig))
|
||||
return tz_leap;
|
||||
strcpy(tz_orig, tz_env);
|
||||
}
|
||||
setenv("TZ", CNF_GetLeapSecTimezone(), 1);
|
||||
tzset();
|
||||
|
||||
/* Get the TAI-UTC offset, which started at the epoch at 10 seconds */
|
||||
t = mktime(&stm);
|
||||
if (t != -1)
|
||||
*tai_offset = t - when + 10;
|
||||
|
||||
/* Set the time to 23:59:60 and see how it overflows in mktime() */
|
||||
stm.tm_sec = 60;
|
||||
stm.tm_min = 59;
|
||||
stm.tm_hour = 23;
|
||||
|
||||
t = mktime(&stm);
|
||||
|
||||
if (tz_env)
|
||||
setenv("TZ", tz_orig, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
tzset();
|
||||
|
||||
if (t == -1)
|
||||
return tz_leap;
|
||||
|
||||
if (stm.tm_sec == 60)
|
||||
tz_leap = LEAP_InsertSecond;
|
||||
else if (stm.tm_sec == 1)
|
||||
tz_leap = LEAP_DeleteSecond;
|
||||
|
||||
return tz_leap;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static NTP_Leap
|
||||
get_list_leap(time_t when, int *tai_offset)
|
||||
{
|
||||
FILE *f;
|
||||
char line[1024];
|
||||
NTP_Leap ret_leap = LEAP_Normal;
|
||||
int ret_tai_offset = 0, prev_lsl_tai_offset = 10;
|
||||
int64_t when1900, lsl_updated = 0, lsl_expiry = 0;
|
||||
const char *leap_sec_list = CNF_GetLeapSecList();
|
||||
|
||||
if (!(f = UTI_OpenFile(NULL, leap_sec_list, NULL, 'r', 0))) {
|
||||
LOG(LOGS_ERR, "Failed to open leap seconds list %s", leap_sec_list);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Leap second happens at midnight */
|
||||
when = (when / (24 * 3600) + 1) * (24 * 3600);
|
||||
|
||||
/* leap-seconds.list timestamps are relative to 1 Jan 1900, 00:00:00 */
|
||||
when1900 = (int64_t)when + LEAP_SEC_LIST_OFFSET;
|
||||
|
||||
while (fgets(line, sizeof line, f) > 0) {
|
||||
int64_t lsl_when;
|
||||
int lsl_tai_offset;
|
||||
char *p;
|
||||
|
||||
/* Ignore blank lines */
|
||||
for (p = line; *p && isspace(*p); ++p)
|
||||
;
|
||||
if (!*p)
|
||||
continue;
|
||||
|
||||
if (*line == '#') {
|
||||
/* Update time line starts with #$ */
|
||||
if (line[1] == '$' && sscanf(line + 2, "%"SCNd64, &lsl_updated) != 1)
|
||||
goto error;
|
||||
/* Expiration time line starts with #@ */
|
||||
if (line[1] == '@' && sscanf(line + 2, "%"SCNd64, &lsl_expiry) != 1)
|
||||
goto error;
|
||||
/* Comment or a special comment we don't care about */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Leap entry */
|
||||
if (sscanf(line, "%"SCNd64" %d", &lsl_when, &lsl_tai_offset) != 2)
|
||||
goto error;
|
||||
|
||||
if (when1900 == lsl_when) {
|
||||
if (lsl_tai_offset > prev_lsl_tai_offset)
|
||||
ret_leap = LEAP_InsertSecond;
|
||||
else if (lsl_tai_offset < prev_lsl_tai_offset)
|
||||
ret_leap = LEAP_DeleteSecond;
|
||||
/* When is rounded to the end of the day, so offset hasn't changed yet! */
|
||||
ret_tai_offset = prev_lsl_tai_offset;
|
||||
} else if (when1900 > lsl_when) {
|
||||
ret_tai_offset = lsl_tai_offset;
|
||||
}
|
||||
|
||||
prev_lsl_tai_offset = lsl_tai_offset;
|
||||
}
|
||||
|
||||
/* Make sure the file looks sensible */
|
||||
if (!feof(f) || !lsl_updated || !lsl_expiry)
|
||||
goto error;
|
||||
|
||||
if (when1900 >= lsl_expiry)
|
||||
LOG(LOGS_WARN, "Leap second list %s needs update", leap_sec_list);
|
||||
|
||||
goto out;
|
||||
|
||||
error:
|
||||
if (f)
|
||||
fclose(f);
|
||||
LOG(LOGS_ERR, "Failed to parse leap seconds list %s", leap_sec_list);
|
||||
return LEAP_Normal;
|
||||
|
||||
out:
|
||||
if (f)
|
||||
fclose(f);
|
||||
*tai_offset = ret_tai_offset;
|
||||
return ret_leap;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
check_leap_source(NTP_Leap (*src)(time_t when, int *tai_offset))
|
||||
{
|
||||
int tai_offset = 0;
|
||||
|
||||
/* Check that the leap second source has good data for Jun 30 2012 and Dec 31 2012 */
|
||||
if (src(1341014400, &tai_offset) == LEAP_InsertSecond && tai_offset == 34 &&
|
||||
src(1356912000, &tai_offset) == LEAP_Normal && tai_offset == 35)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LDB_Initialise(void)
|
||||
{
|
||||
const char *leap_tzname, *leap_sec_list;
|
||||
|
||||
leap_tzname = CNF_GetLeapSecTimezone();
|
||||
if (leap_tzname && !check_leap_source(get_tz_leap)) {
|
||||
LOG(LOGS_WARN, "Timezone %s failed leap second check, ignoring", leap_tzname);
|
||||
leap_tzname = NULL;
|
||||
}
|
||||
|
||||
leap_sec_list = CNF_GetLeapSecList();
|
||||
if (leap_sec_list && !check_leap_source(get_list_leap)) {
|
||||
LOG(LOGS_WARN, "Leap second list %s failed check, ignoring", leap_sec_list);
|
||||
leap_sec_list = NULL;
|
||||
}
|
||||
|
||||
if (leap_sec_list) {
|
||||
LOG(LOGS_INFO, "Using leap second list %s", leap_sec_list);
|
||||
leap_src = SRC_LIST;
|
||||
} else if (leap_tzname) {
|
||||
LOG(LOGS_INFO, "Using %s timezone to obtain leap second data", leap_tzname);
|
||||
leap_src = SRC_TIMEZONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
NTP_Leap
|
||||
LDB_GetLeap(time_t when, int *tai_offset)
|
||||
{
|
||||
static time_t last_ldb_leap_check;
|
||||
static NTP_Leap ldb_leap;
|
||||
static int ldb_tai_offset;
|
||||
|
||||
/* Do this check at most twice a day */
|
||||
when = when / (12 * 3600) * (12 * 3600);
|
||||
if (last_ldb_leap_check == when)
|
||||
goto out;
|
||||
|
||||
last_ldb_leap_check = when;
|
||||
ldb_leap = LEAP_Normal;
|
||||
ldb_tai_offset = 0;
|
||||
|
||||
switch (leap_src) {
|
||||
case SRC_NONE:
|
||||
break;
|
||||
case SRC_TIMEZONE:
|
||||
ldb_leap = get_tz_leap(when, &ldb_tai_offset);
|
||||
break;
|
||||
case SRC_LIST:
|
||||
ldb_leap = get_list_leap(when, &ldb_tai_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
*tai_offset = ldb_tai_offset;
|
||||
return ldb_leap;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LDB_Finalise(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
37
leapdb.h
Normal file
37
leapdb.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Patrick Oppenlander 2023
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
This module provides leap second information.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GOT_LEAPDB_H
|
||||
#define GOT_LEAPDB_H
|
||||
|
||||
#include "ntp.h"
|
||||
|
||||
extern void LDB_Initialise(void);
|
||||
extern NTP_Leap LDB_GetLeap(time_t when, int *tai_offset);
|
||||
extern void LDB_Finalise(void);
|
||||
|
||||
#endif /* GOT_LEAPDB_H */
|
||||
13
logging.c
13
logging.c
@@ -185,7 +185,7 @@ void LOG_Message(LOG_Severity severity,
|
||||
/* Send the message also to the foreground process if it is
|
||||
still running, or stderr if it is still open */
|
||||
if (parent_fd > 0) {
|
||||
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
|
||||
if (!LOG_NotifyParent(buf))
|
||||
; /* Not much we can do here */
|
||||
} else if (system_log && parent_fd == 0) {
|
||||
system_log = 0;
|
||||
@@ -291,6 +291,17 @@ LOG_SetParentFd(int fd)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
LOG_NotifyParent(const char *message)
|
||||
{
|
||||
if (parent_fd <= 0)
|
||||
return 1;
|
||||
|
||||
return write(parent_fd, message, strlen(message) + 1) > 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
LOG_CloseParentFd()
|
||||
{
|
||||
|
||||
@@ -126,7 +126,10 @@ extern void LOG_OpenSystemLog(void);
|
||||
/* Stop using stderr and send fatal message to the foreground process */
|
||||
extern void LOG_SetParentFd(int fd);
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
/* Send a message to the foreground process */
|
||||
extern int LOG_NotifyParent(const char *message);
|
||||
|
||||
/* Close the pipe to the foreground process */
|
||||
extern void LOG_CloseParentFd(void);
|
||||
|
||||
/* File logging functions */
|
||||
|
||||
12
main.c
12
main.c
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "main.h"
|
||||
#include "sched.h"
|
||||
#include "leapdb.h"
|
||||
#include "local.h"
|
||||
#include "sys.h"
|
||||
#include "ntp_io.h"
|
||||
@@ -134,6 +135,7 @@ MAI_CleanupAndExit(void)
|
||||
RCL_Finalise();
|
||||
SRC_Finalise();
|
||||
REF_Finalise();
|
||||
LDB_Finalise();
|
||||
RTC_Finalise();
|
||||
SYS_Finalise();
|
||||
|
||||
@@ -213,7 +215,10 @@ post_init_ntp_hook(void *anything)
|
||||
REF_SetMode(ref_mode);
|
||||
}
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
/* Send an empty message to the foreground process so it can exit.
|
||||
If that fails, indicating the process was killed, exit too. */
|
||||
if (!LOG_NotifyParent(""))
|
||||
SCH_QuitProgram();
|
||||
LOG_CloseParentFd();
|
||||
|
||||
CNF_AddSources();
|
||||
@@ -336,8 +341,8 @@ go_daemon(void)
|
||||
|
||||
close(pipefd[1]);
|
||||
r = read(pipefd[0], message, sizeof (message));
|
||||
if (r) {
|
||||
if (r > 0) {
|
||||
if (r != 1 || message[0] != '\0') {
|
||||
if (r > 1) {
|
||||
/* Print the error message from the child */
|
||||
message[sizeof (message) - 1] = '\0';
|
||||
fprintf(stderr, "%s\n", message);
|
||||
@@ -655,6 +660,7 @@ int main
|
||||
if (!geteuid())
|
||||
LOG(LOGS_WARN, "Running with root privileges");
|
||||
|
||||
LDB_Initialise();
|
||||
REF_Initialise();
|
||||
SST_Initialise();
|
||||
NSR_Initialise();
|
||||
|
||||
46
ntp_core.c
46
ntp_core.c
@@ -221,7 +221,7 @@ struct NCR_Instance_Record {
|
||||
int burst_good_samples_to_go;
|
||||
int burst_total_samples_to_go;
|
||||
|
||||
/* Report from last valid response */
|
||||
/* Report from last valid response and packet/timestamp statistics */
|
||||
RPT_NTPReport report;
|
||||
};
|
||||
|
||||
@@ -2211,7 +2211,8 @@ process_response(NCR_Instance inst, int saved, NTP_Local_Address *local_addr,
|
||||
/* Test A combines multiple tests to avoid changing the measurements log
|
||||
format and ntpdata report. It requires that the minimum estimate of the
|
||||
peer delay is not larger than the configured maximum, it is not a
|
||||
response in the 'warm up' exchange, in both client modes that the server
|
||||
response in the 'warm up' exchange, the configured offset correction is
|
||||
within the supported NTP interval, both client modes that the server
|
||||
processing time is sane, in interleaved client/server mode that the
|
||||
previous response was not in basic mode (which prevents using timestamps
|
||||
that minimise delay error), and in interleaved symmetric mode that the
|
||||
@@ -2220,6 +2221,7 @@ process_response(NCR_Instance inst, int saved, NTP_Local_Address *local_addr,
|
||||
testA = sample.peer_delay - sample.peer_dispersion <= inst->max_delay &&
|
||||
precision <= inst->max_delay &&
|
||||
inst->presend_done <= 0 &&
|
||||
UTI_IsTimeOffsetSane(&sample.time, sample.offset) &&
|
||||
!(inst->mode == MODE_CLIENT && response_time > MAX_SERVER_INTERVAL) &&
|
||||
!(inst->mode == MODE_CLIENT && interleaved_packet &&
|
||||
UTI_IsZeroTimespec(&inst->prev_local_tx.ts) &&
|
||||
@@ -2372,13 +2374,17 @@ process_response(NCR_Instance inst, int saved, NTP_Local_Address *local_addr,
|
||||
|
||||
SRC_UpdateReachability(inst->source, synced_packet);
|
||||
|
||||
if (synced_packet) {
|
||||
if (inst->copy && inst->remote_stratum > 0) {
|
||||
/* Assume the reference ID and stratum of the server */
|
||||
if (inst->copy) {
|
||||
/* Assume the reference ID and stratum of the server */
|
||||
if (synced_packet && inst->remote_stratum > 0) {
|
||||
inst->remote_stratum--;
|
||||
SRC_SetRefid(inst->source, ntohl(message->reference_id), &inst->remote_addr.ip_addr);
|
||||
} else {
|
||||
SRC_ResetInstance(inst->source);
|
||||
}
|
||||
}
|
||||
|
||||
if (synced_packet) {
|
||||
SRC_UpdateStatus(inst->source, MAX(inst->remote_stratum, inst->min_stratum), pkt_leap);
|
||||
|
||||
if (inst->delay_quant)
|
||||
@@ -2530,6 +2536,10 @@ NCR_ProcessRxKnown(NCR_Instance inst, NTP_Local_Address *local_addr,
|
||||
NTP_PacketInfo info;
|
||||
|
||||
inst->report.total_rx_count++;
|
||||
if (rx_ts->source == NTP_TS_KERNEL)
|
||||
inst->report.total_kernel_rx_ts++;
|
||||
else if (rx_ts->source == NTP_TS_HARDWARE)
|
||||
inst->report.total_hw_rx_ts++;
|
||||
|
||||
if (!parse_packet(message, length, &info))
|
||||
return 0;
|
||||
@@ -2652,6 +2662,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
||||
NTP_Local_Timestamp local_tx, *tx_ts;
|
||||
NTP_int64 ntp_rx, *local_ntp_rx;
|
||||
int log_index, interleaved, poll, version;
|
||||
CLG_Limit limit;
|
||||
uint32_t kod;
|
||||
|
||||
/* Ignore the packet if it wasn't received by server socket */
|
||||
@@ -2697,7 +2708,8 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
||||
log_index = CLG_LogServiceAccess(CLG_NTP, &remote_addr->ip_addr, &rx_ts->ts);
|
||||
|
||||
/* Don't reply to all requests if the rate is excessive */
|
||||
if (log_index >= 0 && CLG_LimitServiceRate(CLG_NTP, log_index)) {
|
||||
limit = log_index >= 0 ? CLG_LimitServiceRate(CLG_NTP, log_index) : CLG_PASS;
|
||||
if (limit == CLG_DROP) {
|
||||
DEBUG_LOG("NTP packet discarded to limit response rate");
|
||||
return;
|
||||
}
|
||||
@@ -2711,6 +2723,13 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
||||
return;
|
||||
}
|
||||
|
||||
if (limit == CLG_KOD) {
|
||||
/* Don't respond if there is a conflict with the NTS NAK */
|
||||
if (kod != 0)
|
||||
return;
|
||||
kod = KOD_RATE;
|
||||
}
|
||||
|
||||
local_ntp_rx = NULL;
|
||||
tx_ts = NULL;
|
||||
interleaved = 0;
|
||||
@@ -2736,7 +2755,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
||||
CLG_DisableNtpTimestamps(&ntp_rx);
|
||||
}
|
||||
|
||||
CLG_UpdateNtpStats(kod != 0 && info.auth.mode != NTP_AUTH_NONE &&
|
||||
CLG_UpdateNtpStats(kod == 0 && info.auth.mode != NTP_AUTH_NONE &&
|
||||
info.auth.mode != NTP_AUTH_MSSNTP,
|
||||
rx_ts->source, interleaved ? tx_ts->source : NTP_TS_DAEMON);
|
||||
|
||||
@@ -2812,8 +2831,11 @@ NCR_ProcessTxKnown(NCR_Instance inst, NTP_Local_Address *local_addr,
|
||||
message);
|
||||
|
||||
if (tx_ts->source == NTP_TS_HARDWARE) {
|
||||
inst->report.total_hw_tx_ts++;
|
||||
if (has_saved_response(inst))
|
||||
process_saved_response(inst);
|
||||
} else if (tx_ts->source == NTP_TS_KERNEL) {
|
||||
inst->report.total_kernel_tx_ts++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3017,6 +3039,16 @@ NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NCR_ModifyOffset(NCR_Instance inst, double new_offset)
|
||||
{
|
||||
inst->offset_correction = new_offset;
|
||||
LOG(LOGS_INFO, "Source %s new offset %f",
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr), new_offset);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target)
|
||||
{
|
||||
|
||||
@@ -113,6 +113,8 @@ extern void NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_d
|
||||
|
||||
extern void NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum);
|
||||
|
||||
extern void NCR_ModifyOffset(NCR_Instance inst, double new_offset);
|
||||
|
||||
extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
|
||||
|
||||
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
|
||||
|
||||
10
ntp_io.c
10
ntp_io.c
@@ -513,9 +513,11 @@ NIO_UnwrapMessage(SCK_Message *message, int sock_fd, double *net_correction)
|
||||
|
||||
msg = message->data;
|
||||
|
||||
if (msg->header.type != PTP_TYPE_DELAY_REQ || msg->header.version != PTP_VERSION ||
|
||||
if ((msg->header.type != PTP_TYPE_DELAY_REQ && msg->header.type != PTP_TYPE_SYNC) ||
|
||||
(msg->header.version != PTP_VERSION_2 &&
|
||||
(msg->header.version != PTP_VERSION_2_1 || msg->header.min_sdoid != 0)) ||
|
||||
ntohs(msg->header.length) != message->length ||
|
||||
msg->header.domain != PTP_DOMAIN_NTP ||
|
||||
msg->header.domain != CNF_GetPtpDomain() ||
|
||||
ntohs(msg->header.flags) != PTP_FLAG_UNICAST ||
|
||||
ntohs(msg->tlv_header.type) != PTP_TLV_NTP ||
|
||||
ntohs(msg->tlv_header.length) != message->length - PTP_NTP_PREFIX_LENGTH) {
|
||||
@@ -561,9 +563,9 @@ wrap_message(SCK_Message *message, int sock_fd)
|
||||
|
||||
memset(ptp_message, 0, PTP_NTP_PREFIX_LENGTH);
|
||||
ptp_message->header.type = PTP_TYPE_DELAY_REQ;
|
||||
ptp_message->header.version = PTP_VERSION;
|
||||
ptp_message->header.version = PTP_VERSION_2;
|
||||
ptp_message->header.length = htons(PTP_NTP_PREFIX_LENGTH + message->length);
|
||||
ptp_message->header.domain = PTP_DOMAIN_NTP;
|
||||
ptp_message->header.domain = CNF_GetPtpDomain();
|
||||
ptp_message->header.flags = htons(PTP_FLAG_UNICAST);
|
||||
ptp_message->header.sequence_id = htons(sequence_id++);
|
||||
ptp_message->tlv_header.type = htons(PTP_TLV_NTP);
|
||||
|
||||
13
ntp_signd.c
13
ntp_signd.c
@@ -99,6 +99,9 @@ static int sock_fd;
|
||||
/* Flag indicating if the MS-SNTP authentication is enabled */
|
||||
static int enabled;
|
||||
|
||||
/* Flag limiting logging of connection error messages */
|
||||
static int logged_connection_error;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void read_write_socket(int sock_fd, int event, void *anything);
|
||||
@@ -134,6 +137,14 @@ open_socket(void)
|
||||
sock_fd = SCK_OpenUnixStreamSocket(path, NULL, 0);
|
||||
if (sock_fd < 0) {
|
||||
sock_fd = INVALID_SOCK_FD;
|
||||
|
||||
/* Log an error only once before a successful exchange to avoid
|
||||
flooding the system log */
|
||||
if (!logged_connection_error) {
|
||||
LOG(LOGS_ERR, "Could not connect to signd socket %s : %s", path, strerror(errno));
|
||||
logged_connection_error = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -160,6 +171,8 @@ process_response(SignInstance *inst)
|
||||
return;
|
||||
}
|
||||
|
||||
logged_connection_error = 0;
|
||||
|
||||
/* Check if the file descriptor is still valid */
|
||||
if (!NIO_IsServerSocket(inst->local_addr.sock_fd)) {
|
||||
DEBUG_LOG("Invalid NTP socket");
|
||||
|
||||
@@ -61,6 +61,8 @@ typedef struct {
|
||||
(may be an IP address) */
|
||||
IPAddr resolved_addr; /* Address resolved from the name, which can be
|
||||
different from remote_addr (e.g. NTS-KE) */
|
||||
int family; /* IP family of acceptable resolved addresses
|
||||
(IPADDR_UNSPEC if any) */
|
||||
int pool_id; /* ID of the pool from which was this source
|
||||
added or INVALID_POOL */
|
||||
int tentative; /* Flag indicating there was no valid response
|
||||
@@ -98,6 +100,8 @@ struct UnresolvedSource {
|
||||
int pool_id;
|
||||
/* Name to be resolved */
|
||||
char *name;
|
||||
/* Address family to filter resolved addresses */
|
||||
int family;
|
||||
/* Flag indicating addresses should be used in a random order */
|
||||
int random_order;
|
||||
/* Flag indicating current address should be replaced only if it is
|
||||
@@ -353,7 +357,7 @@ log_source(SourceRecord *record, int addition, int once_per_pool)
|
||||
|
||||
/* Procedure to add a new source */
|
||||
static NSR_Status
|
||||
add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
|
||||
add_source(NTP_Remote_Address *remote_addr, char *name, int family, NTP_Source_Type type,
|
||||
SourceParameters *params, int pool_id, uint32_t conf_id)
|
||||
{
|
||||
SourceRecord *record;
|
||||
@@ -391,6 +395,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
|
||||
record->data = NCR_CreateInstance(remote_addr, type, params, record->name);
|
||||
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
||||
record->resolved_addr = remote_addr->ip_addr;
|
||||
record->family = family;
|
||||
record->pool_id = pool_id;
|
||||
record->tentative = 1;
|
||||
record->conf_id = conf_id;
|
||||
@@ -552,6 +557,10 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
|
||||
|
||||
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
|
||||
|
||||
/* Skip addresses not from the requested family */
|
||||
if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.family)
|
||||
continue;
|
||||
|
||||
if (us->pool_id != INVALID_POOL) {
|
||||
/* In the pool resolving mode, try to replace a source from
|
||||
the pool which does not have a real address yet */
|
||||
@@ -629,13 +638,16 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *any
|
||||
next = us->next;
|
||||
|
||||
/* Don't repeat the resolving if it (permanently) failed, it was a
|
||||
replacement of a real address, or all addresses are already resolved */
|
||||
if (status == DNS_Failure || UTI_IsIPReal(&us->address.ip_addr) || is_resolved(us))
|
||||
replacement of a real address, a refreshment, or all addresses are
|
||||
already resolved */
|
||||
if (status == DNS_Failure || UTI_IsIPReal(&us->address.ip_addr) ||
|
||||
us->refreshment || is_resolved(us))
|
||||
remove_unresolved_source(us);
|
||||
|
||||
/* If a restart was requested and this was the last source in the list,
|
||||
start with the first source again (if there still is one) */
|
||||
if (!next && resolving_restart) {
|
||||
DEBUG_LOG("Restarting");
|
||||
next = unresolved_sources;
|
||||
resolving_restart = 0;
|
||||
}
|
||||
@@ -700,11 +712,15 @@ static void
|
||||
append_unresolved_source(struct UnresolvedSource *us)
|
||||
{
|
||||
struct UnresolvedSource **i;
|
||||
int n;
|
||||
|
||||
for (i = &unresolved_sources; *i; i = &(*i)->next)
|
||||
for (i = &unresolved_sources, n = 0; *i; i = &(*i)->next, n++)
|
||||
;
|
||||
*i = us;
|
||||
us->next = NULL;
|
||||
|
||||
DEBUG_LOG("Added unresolved source #%d pool_id=%d random=%d refresh=%d",
|
||||
n + 1, us->pool_id, us->random_order, us->refreshment);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -754,8 +770,19 @@ static int get_unused_pool_id(void)
|
||||
static uint32_t
|
||||
get_next_conf_id(uint32_t *conf_id)
|
||||
{
|
||||
SourceRecord *record;
|
||||
unsigned int i;
|
||||
|
||||
again:
|
||||
last_conf_id++;
|
||||
|
||||
/* Make sure the ID is not already used (after 32-bit wraparound) */
|
||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||
record = get_record(i);
|
||||
if (record->remote_addr && record->conf_id == last_conf_id)
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (conf_id)
|
||||
*conf_id = last_conf_id;
|
||||
|
||||
@@ -768,14 +795,14 @@ NSR_Status
|
||||
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
||||
SourceParameters *params, uint32_t *conf_id)
|
||||
{
|
||||
return add_source(remote_addr, NULL, type, params, INVALID_POOL,
|
||||
return add_source(remote_addr, NULL, IPADDR_UNSPEC, type, params, INVALID_POOL,
|
||||
get_next_conf_id(conf_id));
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
NSR_Status
|
||||
NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type,
|
||||
SourceParameters *params, uint32_t *conf_id)
|
||||
{
|
||||
struct UnresolvedSource *us;
|
||||
@@ -787,7 +814,9 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
/* If the name is an IP address, add the source with the address directly */
|
||||
if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
|
||||
remote_addr.port = port;
|
||||
return add_source(&remote_addr, name, type, params, INVALID_POOL,
|
||||
if (family != IPADDR_UNSPEC && family != remote_addr.ip_addr.family)
|
||||
return NSR_InvalidAF;
|
||||
return add_source(&remote_addr, name, IPADDR_UNSPEC, type, params, INVALID_POOL,
|
||||
get_next_conf_id(conf_id));
|
||||
}
|
||||
|
||||
@@ -799,6 +828,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
us->name = Strdup(name);
|
||||
us->family = family;
|
||||
us->random_order = 0;
|
||||
us->refreshment = 0;
|
||||
|
||||
@@ -835,7 +865,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
for (i = 0; i < new_sources; i++) {
|
||||
if (i > 0)
|
||||
remote_addr.ip_addr.addr.id = ++last_address_id;
|
||||
if (add_source(&remote_addr, name, type, params, us->pool_id, cid) != NSR_Success)
|
||||
if (add_source(&remote_addr, name, family, type, params, us->pool_id, cid) != NSR_Success)
|
||||
return NSR_TooManySources;
|
||||
}
|
||||
|
||||
@@ -1026,6 +1056,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment)
|
||||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
us->name = Strdup(record->name);
|
||||
us->family = record->family;
|
||||
/* Ignore the order of addresses from the resolver to not get
|
||||
stuck with a pair of unreachable or otherwise unusable servers
|
||||
(e.g. falsetickers) in case the order doesn't change, or a group
|
||||
@@ -1036,7 +1067,10 @@ resolve_source_replacement(SourceRecord *record, int refreshment)
|
||||
us->address = *record->remote_addr;
|
||||
|
||||
append_unresolved_source(us);
|
||||
NSR_ResolveSources();
|
||||
|
||||
/* Don't restart resolving round if already running */
|
||||
if (!resolving_source)
|
||||
NSR_ResolveSources();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -1431,6 +1465,20 @@ NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NSR_ModifyOffset(IPAddr *address, double new_offset)
|
||||
{
|
||||
int slot;
|
||||
|
||||
if (!find_slot(address, &slot))
|
||||
return 0;
|
||||
|
||||
NCR_ModifyOffset(get_record(slot)->data, new_offset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NSR_ModifyPolltarget(IPAddr *address, int new_poll_target)
|
||||
{
|
||||
|
||||
@@ -55,9 +55,12 @@ extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type
|
||||
|
||||
/* Procedure to add a new server, peer source, or pool of servers specified by
|
||||
name instead of address. The name is resolved in exponentially increasing
|
||||
intervals until it succeeds or fails with a non-temporary error. If the
|
||||
name is an address, it is equivalent to NSR_AddSource(). */
|
||||
extern NSR_Status NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
intervals until it succeeds or fails with a non-temporary error. The
|
||||
specified family filters resolved addresses. If the name is an address
|
||||
and its family does not conflict with the specified family, it is equivalent
|
||||
to NSR_AddSource(). */
|
||||
extern NSR_Status NSR_AddSourceByName(char *name, int family, int port, int pool,
|
||||
NTP_Source_Type type,
|
||||
SourceParameters *params, uint32_t *conf_id);
|
||||
|
||||
extern const char *NSR_StatusToString(NSR_Status status);
|
||||
@@ -137,6 +140,8 @@ extern int NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_rati
|
||||
|
||||
extern int NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum);
|
||||
|
||||
extern int NSR_ModifyOffset(IPAddr *address, double new_offset);
|
||||
|
||||
extern int NSR_ModifyPolltarget(IPAddr *address, int new_poll_target);
|
||||
|
||||
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
|
||||
|
||||
@@ -242,7 +242,7 @@ accept_connection(int listening_fd, int event, void *arg)
|
||||
SCH_GetLastEventTime(&now, NULL, NULL);
|
||||
|
||||
log_index = CLG_LogServiceAccess(CLG_NTSKE, &addr.ip_addr, &now);
|
||||
if (log_index >= 0 && CLG_LimitServiceRate(CLG_NTSKE, log_index)) {
|
||||
if (log_index >= 0 && CLG_LimitServiceRate(CLG_NTSKE, log_index) != CLG_PASS) {
|
||||
DEBUG_LOG("Rejected connection from %s (%s)",
|
||||
UTI_IPSockAddrToString(&addr), "rate limit");
|
||||
SCK_CloseSocket(sock_fd);
|
||||
|
||||
@@ -279,7 +279,7 @@ NNS_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *req_info,
|
||||
}
|
||||
|
||||
/* NTS NAK response does not have any other fields */
|
||||
if (kod)
|
||||
if (kod == NTP_KOD_NTS_NAK)
|
||||
return 1;
|
||||
|
||||
for (i = 0, plaintext_length = 0; i < server->num_cookies; i++) {
|
||||
|
||||
@@ -111,7 +111,7 @@ static const struct request_length request_lengths[] = {
|
||||
REQ_LENGTH_ENTRY(null, null), /* REFRESH */
|
||||
REQ_LENGTH_ENTRY(null, server_stats), /* SERVER_STATS */
|
||||
{ 0, 0 }, /* CLIENT_ACCESSES_BY_INDEX2 - not supported */
|
||||
REQ_LENGTH_ENTRY(local, null), /* LOCAL2 */
|
||||
{ 0, 0 }, /* LOCAL2 - not supported */
|
||||
REQ_LENGTH_ENTRY(ntp_data, ntp_data), /* NTP_DATA */
|
||||
{ 0, 0 }, /* ADD_SERVER2 */
|
||||
{ 0, 0 }, /* ADD_PEER2 */
|
||||
@@ -130,6 +130,8 @@ static const struct request_length request_lengths[] = {
|
||||
REQ_LENGTH_ENTRY(null, null), /* RELOAD_SOURCES */
|
||||
REQ_LENGTH_ENTRY(doffset, null), /* DOFFSET2 */
|
||||
REQ_LENGTH_ENTRY(modify_select_opts, null), /* MODIFY_SELECTOPTS */
|
||||
REQ_LENGTH_ENTRY(modify_offset, null), /* MODIFY_OFFSET */
|
||||
REQ_LENGTH_ENTRY(local, null), /* LOCAL3 */
|
||||
};
|
||||
|
||||
static const uint16_t reply_lengths[] = {
|
||||
@@ -149,7 +151,7 @@ static const uint16_t reply_lengths[] = {
|
||||
RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */
|
||||
0, /* SERVER_STATS - not supported */
|
||||
0, /* CLIENT_ACCESSES_BY_INDEX2 - not supported */
|
||||
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */
|
||||
0, /* NTP_DATA - not supported */
|
||||
RPY_LENGTH_ENTRY(manual_timestamp), /* MANUAL_TIMESTAMP2 */
|
||||
RPY_LENGTH_ENTRY(manual_list), /* MANUAL_LIST2 */
|
||||
RPY_LENGTH_ENTRY(ntp_source_name), /* NTP_SOURCE_NAME */
|
||||
@@ -159,6 +161,7 @@ static const uint16_t reply_lengths[] = {
|
||||
RPY_LENGTH_ENTRY(select_data), /* SELECT_DATA */
|
||||
0, /* SERVER_STATS3 - not supported */
|
||||
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS4 */
|
||||
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA2 */
|
||||
};
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
5
ptp.h
5
ptp.h
@@ -31,9 +31,10 @@
|
||||
|
||||
#include "ntp.h"
|
||||
|
||||
#define PTP_VERSION 2
|
||||
#define PTP_VERSION_2 2
|
||||
#define PTP_VERSION_2_1 (2 | 1 << 4)
|
||||
#define PTP_TYPE_SYNC 0
|
||||
#define PTP_TYPE_DELAY_REQ 1
|
||||
#define PTP_DOMAIN_NTP 123
|
||||
#define PTP_FLAG_UNICAST (1 << (2 + 8))
|
||||
#define PTP_TLV_NTP 0x2023
|
||||
|
||||
|
||||
20
refclock.c
20
refclock.c
@@ -166,8 +166,8 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||
if (!inst->driver->init && !inst->driver->poll)
|
||||
LOG_FATAL("refclock driver %s is not compiled in", params->driver_name);
|
||||
|
||||
if (params->tai && !CNF_GetLeapSecTimezone())
|
||||
LOG_FATAL("refclock tai option requires leapsectz");
|
||||
if (params->tai && !CNF_GetLeapSecList() && !CNF_GetLeapSecTimezone())
|
||||
LOG_FATAL("refclock tai option requires leapseclist or leapsectz");
|
||||
|
||||
inst->data = NULL;
|
||||
inst->driver_parameter = Strdup(params->driver_parameter);
|
||||
@@ -321,6 +321,22 @@ RCL_ReportSource(RPT_SourceReport *report, struct timespec *now)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
RCL_ModifyOffset(uint32_t ref_id, double offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(refclocks); i++) {
|
||||
RCL_Instance inst = get_refclock(i);
|
||||
if (inst->ref_id == ref_id) {
|
||||
inst->offset = offset;
|
||||
LOG(LOGS_INFO, "Source %s new offset %f", UTI_RefidToString(ref_id), offset);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
RCL_SetDriverData(RCL_Instance instance, void *data)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,7 @@ extern void RCL_Finalise(void);
|
||||
extern int RCL_AddRefclock(RefclockParameters *params);
|
||||
extern void RCL_StartRefclocks(void);
|
||||
extern void RCL_ReportSource(RPT_SourceReport *report, struct timespec *now);
|
||||
extern int RCL_ModifyOffset(uint32_t ref_id, double offset);
|
||||
|
||||
/* functions used by drivers */
|
||||
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
|
||||
|
||||
@@ -175,7 +175,7 @@ static void read_ext_pulse(int fd, int event, void *anything)
|
||||
instance = anything;
|
||||
phc1 = RCL_GetDriverData(instance);
|
||||
|
||||
/* The Linux kernel (as of 6.2) has one shared queue of timestamps for all
|
||||
/* Linux versions before 6.7 had one shared queue of timestamps for all
|
||||
descriptors of the same PHC. Search for all refclocks that expect
|
||||
the timestamp. */
|
||||
|
||||
|
||||
121
reference.c
121
reference.c
@@ -33,6 +33,7 @@
|
||||
#include "reference.h"
|
||||
#include "util.h"
|
||||
#include "conf.h"
|
||||
#include "leapdb.h"
|
||||
#include "logging.h"
|
||||
#include "local.h"
|
||||
#include "sched.h"
|
||||
@@ -53,6 +54,8 @@ static int enable_local_stratum;
|
||||
static int local_stratum;
|
||||
static int local_orphan;
|
||||
static double local_distance;
|
||||
static int local_activate_ok;
|
||||
static double local_activate;
|
||||
static struct timespec local_ref_time;
|
||||
static NTP_Leap our_leap_status;
|
||||
static int our_leap_sec;
|
||||
@@ -122,9 +125,6 @@ static int leap_in_progress;
|
||||
/* Timer for the leap second handler */
|
||||
static SCH_TimeoutID leap_timeout_id;
|
||||
|
||||
/* Name of a system timezone containing leap seconds occuring at midnight */
|
||||
static char *leap_tzname;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static LOG_FileID logfileid;
|
||||
@@ -155,7 +155,6 @@ static int ref_adjustments;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static NTP_Leap get_tz_leap(time_t when, int *tai_offset);
|
||||
static void update_leap_status(NTP_Leap leap, time_t now, int reset);
|
||||
|
||||
/* ================================================== */
|
||||
@@ -195,7 +194,6 @@ REF_Initialise(void)
|
||||
FILE *in;
|
||||
double file_freq_ppm, file_skew_ppm;
|
||||
double our_frequency_ppm;
|
||||
int tai_offset;
|
||||
|
||||
mode = REF_ModeNormal;
|
||||
are_we_synchronised = 0;
|
||||
@@ -211,6 +209,7 @@ REF_Initialise(void)
|
||||
our_frequency_sd = 0.0;
|
||||
our_offset_sd = 0.0;
|
||||
drift_file_age = 0.0;
|
||||
local_activate_ok = 0;
|
||||
|
||||
/* Now see if we can get the drift file opened */
|
||||
drift_file = CNF_GetDriftFile();
|
||||
@@ -249,7 +248,8 @@ REF_Initialise(void)
|
||||
|
||||
correction_time_ratio = CNF_GetCorrectionTimeRatio();
|
||||
|
||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan, &local_distance);
|
||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan,
|
||||
&local_distance, &local_activate);
|
||||
UTI_ZeroTimespec(&local_ref_time);
|
||||
|
||||
leap_when = 0;
|
||||
@@ -260,18 +260,6 @@ REF_Initialise(void)
|
||||
if (leap_mode == REF_LeapModeSystem && !LCL_CanSystemLeap())
|
||||
leap_mode = REF_LeapModeStep;
|
||||
|
||||
leap_tzname = CNF_GetLeapSecTimezone();
|
||||
if (leap_tzname) {
|
||||
/* Check that the timezone has good data for Jun 30 2012 and Dec 31 2012 */
|
||||
if (get_tz_leap(1341014400, &tai_offset) == LEAP_InsertSecond && tai_offset == 34 &&
|
||||
get_tz_leap(1356912000, &tai_offset) == LEAP_Normal && tai_offset == 35) {
|
||||
LOG(LOGS_INFO, "Using %s timezone to obtain leap second data", leap_tzname);
|
||||
} else {
|
||||
LOG(LOGS_WARN, "Timezone %s failed leap second check, ignoring", leap_tzname);
|
||||
leap_tzname = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
|
||||
CNF_GetMaxChange(&max_offset_delay, &max_offset_ignore, &max_offset);
|
||||
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
|
||||
@@ -593,77 +581,6 @@ is_leap_second_day(time_t when)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static NTP_Leap
|
||||
get_tz_leap(time_t when, int *tai_offset)
|
||||
{
|
||||
static time_t last_tz_leap_check;
|
||||
static NTP_Leap tz_leap;
|
||||
static int tz_tai_offset;
|
||||
|
||||
struct tm stm, *tm;
|
||||
time_t t;
|
||||
char *tz_env, tz_orig[128];
|
||||
|
||||
*tai_offset = tz_tai_offset;
|
||||
|
||||
/* Do this check at most twice a day */
|
||||
when = when / (12 * 3600) * (12 * 3600);
|
||||
if (last_tz_leap_check == when)
|
||||
return tz_leap;
|
||||
|
||||
last_tz_leap_check = when;
|
||||
tz_leap = LEAP_Normal;
|
||||
tz_tai_offset = 0;
|
||||
|
||||
tm = gmtime(&when);
|
||||
if (!tm)
|
||||
return tz_leap;
|
||||
|
||||
stm = *tm;
|
||||
|
||||
/* Temporarily switch to the timezone containing leap seconds */
|
||||
tz_env = getenv("TZ");
|
||||
if (tz_env) {
|
||||
if (strlen(tz_env) >= sizeof (tz_orig))
|
||||
return tz_leap;
|
||||
strcpy(tz_orig, tz_env);
|
||||
}
|
||||
setenv("TZ", leap_tzname, 1);
|
||||
tzset();
|
||||
|
||||
/* Get the TAI-UTC offset, which started at the epoch at 10 seconds */
|
||||
t = mktime(&stm);
|
||||
if (t != -1)
|
||||
tz_tai_offset = t - when + 10;
|
||||
|
||||
/* Set the time to 23:59:60 and see how it overflows in mktime() */
|
||||
stm.tm_sec = 60;
|
||||
stm.tm_min = 59;
|
||||
stm.tm_hour = 23;
|
||||
|
||||
t = mktime(&stm);
|
||||
|
||||
if (tz_env)
|
||||
setenv("TZ", tz_orig, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
tzset();
|
||||
|
||||
if (t == -1)
|
||||
return tz_leap;
|
||||
|
||||
if (stm.tm_sec == 60)
|
||||
tz_leap = LEAP_InsertSecond;
|
||||
else if (stm.tm_sec == 1)
|
||||
tz_leap = LEAP_DeleteSecond;
|
||||
|
||||
*tai_offset = tz_tai_offset;
|
||||
|
||||
return tz_leap;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
leap_end_timeout(void *arg)
|
||||
{
|
||||
@@ -751,16 +668,16 @@ set_leap_timeout(time_t now)
|
||||
static void
|
||||
update_leap_status(NTP_Leap leap, time_t now, int reset)
|
||||
{
|
||||
NTP_Leap tz_leap;
|
||||
NTP_Leap ldb_leap;
|
||||
int leap_sec, tai_offset;
|
||||
|
||||
leap_sec = 0;
|
||||
tai_offset = 0;
|
||||
|
||||
if (leap_tzname && now) {
|
||||
tz_leap = get_tz_leap(now, &tai_offset);
|
||||
if (now) {
|
||||
ldb_leap = LDB_GetLeap(now, &tai_offset);
|
||||
if (leap == LEAP_Normal)
|
||||
leap = tz_leap;
|
||||
leap = ldb_leap;
|
||||
}
|
||||
|
||||
if (leap == LEAP_InsertSecond || leap == LEAP_DeleteSecond) {
|
||||
@@ -1219,7 +1136,7 @@ REF_GetReferenceParams
|
||||
double *root_dispersion
|
||||
)
|
||||
{
|
||||
double dispersion, delta;
|
||||
double dispersion, delta, distance;
|
||||
|
||||
assert(initialised);
|
||||
|
||||
@@ -1229,11 +1146,16 @@ REF_GetReferenceParams
|
||||
dispersion = 0.0;
|
||||
}
|
||||
|
||||
distance = our_root_delay / 2 + dispersion;
|
||||
|
||||
if (local_activate == 0.0 || (are_we_synchronised && distance < local_activate))
|
||||
local_activate_ok = 1;
|
||||
|
||||
/* Local reference is active when enabled and the clock is not synchronised
|
||||
or the root distance exceeds the threshold */
|
||||
|
||||
if (are_we_synchronised &&
|
||||
!(enable_local_stratum && our_root_delay / 2 + dispersion > local_distance)) {
|
||||
!(enable_local_stratum && local_activate_ok && distance > local_distance)) {
|
||||
|
||||
*is_synchronised = 1;
|
||||
|
||||
@@ -1245,7 +1167,7 @@ REF_GetReferenceParams
|
||||
*root_delay = our_root_delay;
|
||||
*root_dispersion = dispersion;
|
||||
|
||||
} else if (enable_local_stratum) {
|
||||
} else if (enable_local_stratum && local_activate_ok) {
|
||||
|
||||
*is_synchronised = 0;
|
||||
|
||||
@@ -1345,12 +1267,13 @@ REF_ModifyMakestep(int limit, double threshold)
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
REF_EnableLocal(int stratum, double distance, int orphan)
|
||||
REF_EnableLocal(int stratum, double distance, int orphan, double activate)
|
||||
{
|
||||
enable_local_stratum = 1;
|
||||
local_stratum = CLAMP(1, stratum, NTP_MAX_STRATUM - 1);
|
||||
local_distance = distance;
|
||||
local_orphan = !!orphan;
|
||||
local_activate = activate;
|
||||
LOG(LOGS_INFO, "%s local reference mode", "Enabled");
|
||||
}
|
||||
|
||||
@@ -1368,7 +1291,7 @@ REF_DisableLocal(void)
|
||||
#define LEAP_SECOND_CLOSE 5
|
||||
|
||||
static int
|
||||
is_leap_close(time_t t)
|
||||
is_leap_close(double t)
|
||||
{
|
||||
return leap_when != 0 &&
|
||||
t >= leap_when - LEAP_SECOND_CLOSE && t < leap_when + LEAP_SECOND_CLOSE;
|
||||
@@ -1398,7 +1321,7 @@ REF_GetTaiOffset(struct timespec *ts)
|
||||
{
|
||||
int tai_offset;
|
||||
|
||||
get_tz_leap(ts->tv_sec, &tai_offset);
|
||||
LDB_GetLeap(ts->tv_sec, &tai_offset);
|
||||
|
||||
return tai_offset;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
|
||||
/* Modify makestep settings */
|
||||
extern void REF_ModifyMakestep(int limit, double threshold);
|
||||
|
||||
extern void REF_EnableLocal(int stratum, double distance, int orphan);
|
||||
extern void REF_EnableLocal(int stratum, double distance, int orphan, double activate);
|
||||
extern void REF_DisableLocal(void);
|
||||
|
||||
/* Check if either of the current raw and cooked time, and optionally a
|
||||
|
||||
@@ -377,7 +377,7 @@ find_ordered_entry_with_flags(double *x, int n, int index, char *flags)
|
||||
r = v;
|
||||
do {
|
||||
while (l < v && x[l] < piv) l++;
|
||||
while (x[r] > piv) r--;
|
||||
while (r > 0 && x[r] > piv) r--;
|
||||
if (r <= l) break;
|
||||
EXCH(x[l], x[r]);
|
||||
l++;
|
||||
|
||||
@@ -181,6 +181,10 @@ typedef struct {
|
||||
uint32_t total_rx_count;
|
||||
uint32_t total_valid_count;
|
||||
uint32_t total_good_count;
|
||||
uint32_t total_kernel_tx_ts;
|
||||
uint32_t total_kernel_rx_ts;
|
||||
uint32_t total_hw_tx_ts;
|
||||
uint32_t total_hw_rx_ts;
|
||||
} RPT_NTPReport;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -802,6 +802,7 @@ read_from_device(int fd_, int event, void *any)
|
||||
rtc_tm.tm_mday = rtc_raw.tm_mday;
|
||||
rtc_tm.tm_mon = rtc_raw.tm_mon;
|
||||
rtc_tm.tm_year = rtc_raw.tm_year;
|
||||
rtc_tm.tm_wday = 0;
|
||||
|
||||
rtc_t = t_from_rtc(&rtc_tm);
|
||||
|
||||
|
||||
40
sources.c
40
sources.c
@@ -68,8 +68,8 @@ struct SelectInfo {
|
||||
typedef enum {
|
||||
SRC_OK, /* OK so far, not a final status! */
|
||||
SRC_UNSELECTABLE, /* Has noselect option set */
|
||||
SRC_UNSYNCHRONISED, /* Provides samples but not unsynchronised */
|
||||
SRC_BAD_STATS, /* Doesn't have valid stats data */
|
||||
SRC_UNSYNCHRONISED, /* Provides samples, but not synchronised */
|
||||
SRC_BAD_DISTANCE, /* Has root distance longer than allowed maximum */
|
||||
SRC_JITTERY, /* Had std dev larger than allowed maximum */
|
||||
SRC_WAITS_STATS, /* Others have bad stats, selection postponed */
|
||||
@@ -177,6 +177,8 @@ static int reported_no_majority; /* Flag to avoid repeated log message
|
||||
static int report_selection_loss; /* Flag to force logging a message if
|
||||
selection is lost in a transient state
|
||||
(SRC_WAITS_STATS, SRC_WAITS_UPDATE) */
|
||||
static int forced_first_report; /* Flag to allow one failed selection to be
|
||||
logged before a successful selection */
|
||||
|
||||
/* Score needed to replace the currently selected source */
|
||||
#define SCORE_LIMIT 10.0
|
||||
@@ -524,8 +526,8 @@ SRC_UpdateReachability(SRC_Instance inst, int reachable)
|
||||
if (inst->reachability_size < SOURCE_REACH_BITS)
|
||||
inst->reachability_size++;
|
||||
|
||||
if (!reachable && inst->index == selected_source_index) {
|
||||
/* Try to select a better source */
|
||||
/* Source selection can change with unreachable sources */
|
||||
if (inst->reachability == 0) {
|
||||
SRC_SelectSource(NULL);
|
||||
}
|
||||
|
||||
@@ -862,7 +864,8 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
struct SelectInfo *si;
|
||||
struct timespec now, ref_time;
|
||||
int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources, sel_req_source;
|
||||
int n_badstats_sources, max_sel_reach, max_sel_reach_size, max_badstat_reach;
|
||||
int max_badstat_reach, max_badstat_reach_size, n_badstats_sources;
|
||||
int max_sel_reach, max_sel_reach_size;
|
||||
int depth, best_depth, trust_depth, best_trust_depth, n_sel_trust_sources;
|
||||
int combined, stratum, min_stratum, max_score_index;
|
||||
int orphan_stratum, orphan_source;
|
||||
@@ -893,7 +896,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
n_badstats_sources = 0;
|
||||
sel_req_source = 0;
|
||||
max_sel_reach = max_badstat_reach = 0;
|
||||
max_sel_reach_size = 0;
|
||||
max_sel_reach_size = max_badstat_reach_size = 0;
|
||||
max_reach_sample_ago = 0.0;
|
||||
|
||||
for (i = 0; i < n_sources; i++) {
|
||||
@@ -913,12 +916,6 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore sources which are not synchronised */
|
||||
if (sources[i]->leap == LEAP_Unsynchronised) {
|
||||
mark_source(sources[i], SRC_UNSYNCHRONISED);
|
||||
continue;
|
||||
}
|
||||
|
||||
si = &sources[i]->sel_info;
|
||||
SST_GetSelectionData(sources[i]->stats, &now,
|
||||
&si->lo_limit, &si->hi_limit, &si->root_distance,
|
||||
@@ -930,6 +927,14 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
mark_source(sources[i], SRC_BAD_STATS);
|
||||
if (max_badstat_reach < sources[i]->reachability)
|
||||
max_badstat_reach = sources[i]->reachability;
|
||||
if (max_badstat_reach_size < sources[i]->reachability_size)
|
||||
max_badstat_reach_size = sources[i]->reachability_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore sources which are not synchronised */
|
||||
if (sources[i]->leap == LEAP_Unsynchronised) {
|
||||
mark_source(sources[i], SRC_UNSYNCHRONISED);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1068,6 +1073,14 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for a source to have full reachability register to allow one
|
||||
failed selection to be logged before first successful selection */
|
||||
if (!forced_first_report &&
|
||||
MAX(max_sel_reach_size, max_badstat_reach_size) == SOURCE_REACH_BITS) {
|
||||
report_selection_loss = 1;
|
||||
forced_first_report = 1;
|
||||
}
|
||||
|
||||
if (n_endpoints == 0) {
|
||||
/* No sources provided valid endpoints */
|
||||
unselect_selected_source(LOGS_INFO, "Can't synchronise: no selectable sources", NULL);
|
||||
@@ -1334,6 +1347,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
|
||||
|
||||
reported_no_majority = 0;
|
||||
report_selection_loss = 0;
|
||||
forced_first_report = 1;
|
||||
}
|
||||
|
||||
mark_source(sources[selected_source_index], SRC_SELECTED);
|
||||
@@ -1796,10 +1810,10 @@ get_status_char(SRC_Status status)
|
||||
switch (status) {
|
||||
case SRC_UNSELECTABLE:
|
||||
return 'N';
|
||||
case SRC_UNSYNCHRONISED:
|
||||
return 's';
|
||||
case SRC_BAD_STATS:
|
||||
return 'M';
|
||||
case SRC_UNSYNCHRONISED:
|
||||
return 's';
|
||||
case SRC_BAD_DISTANCE:
|
||||
return 'd';
|
||||
case SRC_JITTERY:
|
||||
|
||||
@@ -549,9 +549,9 @@ SST_DoNewRegression(SST_Stats inst)
|
||||
sd_weight += (peer_distances[i] - min_distance) / sd;
|
||||
weights[i] = SQUARE(sd_weight);
|
||||
}
|
||||
}
|
||||
|
||||
correct_asymmetry(inst, times_back, offsets);
|
||||
correct_asymmetry(inst, times_back, offsets);
|
||||
}
|
||||
|
||||
inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
|
||||
offsets + inst->runs_samples, weights,
|
||||
|
||||
14
stubs.c
14
stubs.c
@@ -201,7 +201,7 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
||||
}
|
||||
|
||||
NSR_Status
|
||||
NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||
NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type,
|
||||
SourceParameters *params, uint32_t *conf_id)
|
||||
{
|
||||
return NSR_TooManySources;
|
||||
@@ -320,6 +320,12 @@ NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NSR_ModifyOffset(IPAddr *address, double new_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NSR_ModifyPolltarget(IPAddr *address, int new_poll_target)
|
||||
{
|
||||
@@ -419,6 +425,12 @@ RCL_ReportSource(RPT_SourceReport *report, struct timespec *now)
|
||||
memset(report, 0, sizeof (*report));
|
||||
}
|
||||
|
||||
int
|
||||
RCL_ModifyOffset(uint32_t ref_id, double offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !FEAT_REFCLOCK */
|
||||
|
||||
#ifndef FEAT_SIGND
|
||||
|
||||
@@ -990,6 +990,14 @@ SYS_Linux_SetPHCExtTimestamping(int fd, int pin, int channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(PTP_MASK_CLEAR_ALL) && defined(PTP_MASK_EN_SINGLE)
|
||||
/* Disable events from other channels on this descriptor */
|
||||
if (ioctl(fd, PTP_MASK_CLEAR_ALL))
|
||||
DEBUG_LOG("ioctl(%s) failed : %s", "PTP_MASK_CLEAR_ALL", strerror(errno));
|
||||
else if (ioctl(fd, PTP_MASK_EN_SINGLE, &channel))
|
||||
DEBUG_LOG("ioctl(%s) failed : %s", "PTP_MASK_EN_SINGLE", strerror(errno));
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,10 +66,9 @@ get_tempcomp(double temp)
|
||||
return k0 + (temp - T0) * k1 + (temp - T0) * (temp - T0) * k2;
|
||||
|
||||
/* Otherwise interpolate/extrapolate between two nearest points */
|
||||
|
||||
for (i = 1; i < ARR_GetSize(points); i++) {
|
||||
p2 = (struct Point *)ARR_GetElement(points, i);
|
||||
if (p2->temp >= temp)
|
||||
for (i = 1; ; i++) {
|
||||
p2 = ARR_GetElement(points, i);
|
||||
if (p2->temp >= temp || i + 1 >= ARR_GetSize(points))
|
||||
break;
|
||||
}
|
||||
p1 = p2 - 1;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
cd ../..
|
||||
|
||||
for opts in \
|
||||
"--enable-debug" \
|
||||
"--host-system=Linux" \
|
||||
"--host-system=NetBSD" \
|
||||
"--host-system=FreeBSD" \
|
||||
|
||||
@@ -41,7 +41,6 @@ for time_offset in -1e-1 1e-1; do
|
||||
export CLKNETSIM_START_DATE=$(awk "BEGIN {printf \"%.0f\", $ntp_start + $start_offset}")
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync && test_fail
|
||||
done
|
||||
|
||||
@@ -114,7 +114,7 @@ limit=1
|
||||
for chronyc_conf in \
|
||||
"accheck 1.2.3.4" \
|
||||
"add peer 10.0.0.0 minpoll 2 maxpoll 6" \
|
||||
"add server 10.0.0.0 minpoll 6 maxpoll 10 iburst burst key 1 certset 2 maxdelay 1e-3 maxdelayratio 10.0 maxdelaydevratio 10.0 maxdelayquant 0.5 mindelay 1e-4 asymmetry 0.5 offset 1e-5 minsamples 6 maxsamples 6 filter 3 offline auto_offline prefer noselect trust require xleave polltarget 20 port 123 presend 7 minstratum 3 version 4 nts ntsport 4460 copy extfield F323 extfield F324" \
|
||||
"add server 10.0.0.0 minpoll 6 maxpoll 10 iburst burst key 1 certset 2 maxdelay 1e-3 maxdelayratio 10.0 maxdelaydevratio 10.0 maxdelayquant 0.5 mindelay 1e-4 asymmetry 0.5 offset 1e-5 minsamples 6 maxsamples 6 filter 3 offline auto_offline prefer noselect trust require xleave polltarget 20 port 123 presend 7 minstratum 3 version 4 nts ntsport 4460 copy extfield F323 extfield F324 ipv6 ipv4" \
|
||||
"add server node1.net1.clk" \
|
||||
"allow 1.2.3.4" \
|
||||
"allow 1.2" \
|
||||
@@ -145,7 +145,7 @@ for chronyc_conf in \
|
||||
"dfreq 1.0e-3" \
|
||||
"doffset -1.0" \
|
||||
"dump" \
|
||||
"local stratum 5 distance 1.0 orphan" \
|
||||
"local stratum 5 distance 1.0 activate 0.5 orphan" \
|
||||
"local off" \
|
||||
"makestep 10.0 3" \
|
||||
"makestep" \
|
||||
@@ -165,6 +165,7 @@ for chronyc_conf in \
|
||||
"offline" \
|
||||
"offline 255.255.255.0/1.2.3.0" \
|
||||
"offline 1.2.3.0/24" \
|
||||
"offset 1.2.3.4 1.0" \
|
||||
"online" \
|
||||
"online 1.2.3.0/24" \
|
||||
"onoffline" \
|
||||
@@ -247,6 +248,10 @@ Total TX : 1
|
||||
Total RX : 1
|
||||
Total valid RX : 1
|
||||
Total good RX : 0
|
||||
Total kernel TX : [01]
|
||||
Total kernel RX : 1
|
||||
Total HW TX : 0
|
||||
Total HW RX : 0
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
M node1\.net1\.clk N ----- ----- 0 1\.0 \+0ns \+0ns N
|
||||
@@ -347,6 +352,7 @@ maxpoll 192.168.123.1 5
|
||||
maxupdateskew 192.168.123.1 10.0
|
||||
minpoll 192.168.123.1 3
|
||||
minstratum 192.168.123.1 1
|
||||
offset 192.168.123.1 -1.0
|
||||
polltarget 192.168.123.1 10
|
||||
selectopts 192.168.123.1 +trust +prefer -require
|
||||
selectdata
|
||||
@@ -371,6 +377,7 @@ check_chronyc_output "^200 OK
|
||||
200 OK
|
||||
200 OK
|
||||
200 OK
|
||||
200 OK
|
||||
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
M node1\.net1\.clk N \-PT\-\- \-PT\-\- 0 1\.0 \+0ns \+0ns \?
|
||||
@@ -433,7 +440,12 @@ server_conf="
|
||||
server 192.168.123.1
|
||||
noclientlog"
|
||||
|
||||
commands=(
|
||||
check_config_h 'FEAT_IPV6 1' && commands=(
|
||||
"add server ::1 ipv4" "^515 Invalid address family$"
|
||||
) || commands=()
|
||||
|
||||
commands+=(
|
||||
"add server 192.168.123.1 ipv6" "^515 Invalid address family$"
|
||||
"add server nosuchnode.net1.clk" "^Invalid host/IP address$"
|
||||
"allow nosuchnode.net1.clk" "^Could not read address$"
|
||||
"allow 192.168.123.0/2 4" "^Could not read address$"
|
||||
|
||||
@@ -8,54 +8,86 @@ check_config_h 'FEAT_REFCLOCK 1' || test_skip
|
||||
|
||||
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s')
|
||||
|
||||
leap=$[2 * 24 * 3600]
|
||||
limit=$[4 * 24 * 3600]
|
||||
client_start=$[2 * 3600]
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapsectz right/UTC"
|
||||
refclock_jitter=1e-9
|
||||
refclock_offset="(* -1.0 (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||
|
||||
for leapmode in system step slew; do
|
||||
client_conf="leapsecmode $leapmode"
|
||||
if [ $leapmode = slew ]; then
|
||||
max_sync_time=$[$leap + 12]
|
||||
else
|
||||
max_sync_time=$[$leap]
|
||||
fi
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
done
|
||||
|
||||
client_server_options="trust"
|
||||
client_conf="refclock SHM 0 dpoll 10 poll 10 delay 1e-3"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
client_server_options=""
|
||||
client_conf="leapsecmode system"
|
||||
min_sync_time=230000
|
||||
max_sync_time=240000
|
||||
|
||||
for smoothmode in "" "leaponly"; do
|
||||
for dir in "+1" "-1"; do
|
||||
leap=$[2 * 24 * 3600 + 1 + $dir]
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapsectz right/UTC
|
||||
leapsecmode slew
|
||||
smoothtime 400 0.001 $smoothmode"
|
||||
leapseclist tmp/leap.list"
|
||||
refclock_offset="(* $dir (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||
|
||||
cat > tmp/leap.list <<-EOF
|
||||
#$ 3676924800
|
||||
#@ 3928521600
|
||||
3345062400 33 # 1 Jan 2006
|
||||
3439756800 $[33 - $dir] # 1 Jan 2009 $(
|
||||
[ "$dir" = "+1" ] && echo -e "\n3471292800 33\n3502828800 34")
|
||||
3550089600 35 # 1 Jul 2012
|
||||
EOF
|
||||
|
||||
for leapmode in system step slew; do
|
||||
client_conf="leapsecmode $leapmode"
|
||||
if [ $leapmode = slew ]; then
|
||||
max_sync_time=$[2 * 24 * 3600 + 13]
|
||||
else
|
||||
max_sync_time=$[2 * 24 * 3600 + 1]
|
||||
fi
|
||||
min_sync_time=$[$max_sync_time - 2]
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
check_file_messages "System clock TAI offset set to" 1 1 log.1 || test_fail
|
||||
check_file_messages "System clock TAI offset set to 33" 1 1 log.1 || test_fail
|
||||
done
|
||||
|
||||
client_server_options="trust"
|
||||
client_conf="refclock SHM 0 dpoll 10 poll 10 delay 1e-3"
|
||||
min_sync_time=$[$leap - 2]
|
||||
max_sync_time=$[$leap]
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
client_server_options=""
|
||||
client_conf="leapsecmode system"
|
||||
min_sync_time=230000
|
||||
max_sync_time=240000
|
||||
|
||||
for smoothmode in "" "leaponly"; do
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapseclist tmp/leap.list
|
||||
leapsecmode slew
|
||||
smoothtime 400 0.001 $smoothmode"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
done
|
||||
done
|
||||
|
||||
if TZ=right/UTC date -d 'Dec 31 2008 23:59:60' 2> /dev/null | grep :60; then
|
||||
server_conf="refclock SHM 0 dpoll 10 poll 10
|
||||
leapsectz right/UTC"
|
||||
refclock_offset="(* -1 (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||
client_conf="leapsecmode system"
|
||||
min_sync_time=$[$leap - 2]
|
||||
max_sync_time=$[$leap]
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
fi
|
||||
|
||||
test_pass
|
||||
|
||||
@@ -14,7 +14,6 @@ client_server_options="maxpoll 6 maxdelay 3e-5 maxdelayratio 2.0 maxdelaydevrati
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ max_sync_time=800
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
limit=10000
|
||||
|
||||
90
test/simulation/121-local
Executable file
90
test/simulation/121-local
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. ./test.common
|
||||
|
||||
test_start "local options"
|
||||
|
||||
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||
|
||||
server_strata=3
|
||||
server_conf="local stratum 5 orphan
|
||||
server 192.168.123.1
|
||||
server 192.168.123.2
|
||||
server 192.168.123.3"
|
||||
max_sync_time=900
|
||||
client_start=140
|
||||
chronyc_start=700
|
||||
chronyc_conf="tracking"
|
||||
time_rms_limit=5e-4
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
check_chronyc_output "^.*Stratum *: 7.*$" || test_fail
|
||||
|
||||
limit=4000
|
||||
wander=0.0
|
||||
jitter=0.0
|
||||
server_strata=1
|
||||
server_conf=""
|
||||
client_server_options="minpoll 6 maxpoll 6 minsamples 64"
|
||||
chronyc_start=1
|
||||
chronyc_conf="timeout 1000000
|
||||
tracking
|
||||
tracking
|
||||
tracking
|
||||
tracking"
|
||||
base_delay=$(cat <<-EOF | tr -d '\n'
|
||||
(+ 1e-4
|
||||
(* 990
|
||||
(equal 0.1 from 3))
|
||||
(* -1
|
||||
(equal 0.1 from 1)
|
||||
(equal 0.1 (max (% time 2000) 1000) 1000)))
|
||||
EOF
|
||||
)
|
||||
|
||||
client_conf="local
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.*7F7F0101.*C0A87B01.*7F7F0101.*C0A87B01.*$" || test_fail
|
||||
|
||||
client_conf="local distance 0.5
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.*7F7F0101.*C0A87B01.*7F7F0101.*C0A87B01.*$" || test_fail
|
||||
|
||||
client_conf="local distance 2.0
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.*7F7F0101.*C0A87B01.*C0A87B01.*C0A87B01.*$" || test_fail
|
||||
|
||||
client_conf="local activate 1e-4
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.* 00000000 .*C0A87B01.*C0A87B01.*C0A87B01.*$" || test_fail
|
||||
|
||||
client_conf="local activate 1e-1
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.* 00000000 .*C0A87B01.*7F7F0101.*C0A87B01.*$" || test_fail
|
||||
|
||||
client_conf="local activate 1e-1 distance 2.0
|
||||
maxclockerror 1000"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_chronyc_output "^.* 00000000 .*C0A87B01.*C0A87B01.*C0A87B01.*$" || test_fail
|
||||
|
||||
test_pass
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. ./test.common
|
||||
|
||||
test_start "orphan option"
|
||||
|
||||
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||
|
||||
server_strata=3
|
||||
server_conf="local stratum 5 orphan
|
||||
server 192.168.123.1
|
||||
server 192.168.123.2
|
||||
server 192.168.123.3"
|
||||
max_sync_time=900
|
||||
client_start=140
|
||||
chronyc_start=700
|
||||
chronyc_conf="tracking"
|
||||
time_rms_limit=5e-4
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
check_chronyc_output "^.*Stratum *: 7.*$" || test_fail
|
||||
|
||||
test_pass
|
||||
@@ -53,7 +53,6 @@ for rpoll in 4 5 6; do
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
if [ $rpoll -le 5 ]; then
|
||||
|
||||
@@ -18,9 +18,17 @@ servers=0
|
||||
refclock_offset="(+ -34 (equal 0.1 (max (sum 1.0) $leap) $leap))"
|
||||
client_conf="
|
||||
refclock SHM 0 dpoll 0 poll 0 tai
|
||||
leapsectz right/UTC
|
||||
leapseclist tmp/leap.list
|
||||
leapsecmode ignore
|
||||
maxchange 1e-3 1 0"
|
||||
maxchange 1e-3 10 0"
|
||||
|
||||
cat > tmp/leap.list <<-EOF
|
||||
#$ 3676924800
|
||||
#@ 3928521600
|
||||
3345062400 33 # 1 Jan 2006
|
||||
3439756800 34 # 1 Jan 2009
|
||||
3550089600 35 # 1 Jul 2012
|
||||
EOF
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
@@ -33,9 +41,9 @@ time_offset=-1000
|
||||
refclock_offset="(+ -34)"
|
||||
client_conf="
|
||||
refclock SHM 0 dpoll 0 poll 0 tai
|
||||
leapsectz right/UTC
|
||||
leapseclist tmp/leap.list
|
||||
makestep 1 1
|
||||
maxchange 1e-3 1 0"
|
||||
maxchange 1e-3 10 0"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
|
||||
@@ -22,7 +22,7 @@ client_min_mean_out_interval=150.0
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ client_min_mean_out_interval=15.9
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
|
||||
@@ -15,4 +15,15 @@ check_sync || test_fail
|
||||
check_file_messages " 2 1 " 1200 1300 log.packets || test_fail
|
||||
check_file_messages " 1 2 " 180 220 log.packets || test_fail
|
||||
|
||||
server_conf="ratelimit interval 6 burst 2 leak 4 kod 2"
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_packet_interval || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
check_file_messages " 2 1 " 700 850 log.packets || test_fail
|
||||
check_file_messages " 1 2 " 350 450 log.packets || test_fail
|
||||
check_log_messages "Received KoD RATE.*\.123.1" 100 140 || test_fail
|
||||
|
||||
test_pass
|
||||
|
||||
@@ -16,6 +16,7 @@ peers=2
|
||||
max_sync_time=420
|
||||
|
||||
server_conf="
|
||||
ptpdomain 123
|
||||
ptpport 319"
|
||||
client_conf="
|
||||
ptpport 319
|
||||
@@ -103,4 +104,20 @@ if check_config_h 'FEAT_DEBUG 1'; then
|
||||
check_log_messages "apply_net_correction.*Applied" 0 0 || test_fail
|
||||
fi
|
||||
|
||||
freq_offset=-1e-4
|
||||
delay_correction=""
|
||||
server_conf="ptpport 319"
|
||||
client_conf="ptpport 319
|
||||
ptpdomain 124
|
||||
authselectmode ignore
|
||||
keyfile tmp/peer.keys"
|
||||
time_max_limit=$default_time_max_limit
|
||||
time_rms_limit=$default_time_rms_limit
|
||||
freq_max_limit=$default_freq_max_limit
|
||||
freq_rms_limit=$default_freq_rms_limit
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_sync && test_fail
|
||||
|
||||
test_pass
|
||||
|
||||
@@ -20,7 +20,7 @@ for options in "extfield F323" "xleave extfield F323"; do
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_sync || test_fail
|
||||
done
|
||||
|
||||
@@ -47,7 +47,7 @@ for lpoll in 5 6 7; do
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_source_selection && test_fail
|
||||
check_sync || test_fail
|
||||
done
|
||||
done
|
||||
|
||||
26
test/simulation/203-initreload
Executable file
26
test/simulation/203-initreload
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. ./test.common
|
||||
|
||||
check_config_h 'FEAT_CMDMON 1' || test_skip
|
||||
|
||||
# Test fix "conf: don't load sourcedir during initstepslew and RTC init"
|
||||
|
||||
test_start "reload during initstepslew"
|
||||
|
||||
client_conf="initstepslew 5 192.168.123.1
|
||||
sourcedir tmp"
|
||||
client_server_conf="#"
|
||||
chronyc_conf="reload sources"
|
||||
chronyc_start=4
|
||||
|
||||
echo 'server 192.168.123.1' > tmp/sources.sources
|
||||
|
||||
run_test || test_fail
|
||||
check_chronyd_exit || test_fail
|
||||
check_source_selection || test_fail
|
||||
check_sync || test_fail
|
||||
|
||||
check_log_messages "Added source 192\.168\.123\.1" 1 1 || test_fail
|
||||
|
||||
test_pass
|
||||
@@ -28,6 +28,7 @@ for command in \
|
||||
"local" \
|
||||
"online" \
|
||||
"onoffline" \
|
||||
"offset $server 0.0" \
|
||||
"maxdelay $server 1e-1" \
|
||||
"maxdelaydevratio $server 5.0" \
|
||||
"maxdelayratio $server 3.0" \
|
||||
@@ -97,12 +98,16 @@ RX timestamping : (Daemon|Kernel)
|
||||
Total TX : [0-9]+
|
||||
Total RX : [0-9]+
|
||||
Total valid RX : [0-9]+
|
||||
Total good RX : [0-9]+$" || test_fail
|
||||
Total good RX : [0-9]+
|
||||
Total kernel TX : [0-9]+
|
||||
Total kernel RX : [0-9]+
|
||||
Total HW TX : 0
|
||||
Total HW RX : 0$" || test_fail
|
||||
|
||||
run_chronyc "selectdata" || test_fail
|
||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||
=======================================================================
|
||||
s 127\.0\.0\.1 N -PTR- -PTR- 0 1\.0 \+0ns \+0ns \?$" || test_fail
|
||||
M 127\.0\.0\.1 N -PTR- -PTR- 0 1\.0 \+0ns \+0ns \?$" || test_fail
|
||||
|
||||
run_chronyc "serverstats" || test_fail
|
||||
check_chronyc_output "^NTP packets received : [0-9]+
|
||||
|
||||
@@ -45,6 +45,11 @@ check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atm
|
||||
=========================================================================
|
||||
127\.0\.0\.1 NTS 1 (30|15) (128|256) [0-9] 0 0 [78] ( 64|100)$" || test_fail
|
||||
|
||||
run_chronyc "serverstats" || test_fail
|
||||
check_chronyc_output "NTS-KE connections accepted: 1
|
||||
NTS-KE connections dropped : 0
|
||||
Authenticated NTP packets : [1-9][0-9]*" || test_fail
|
||||
|
||||
stop_chronyd || test_fail
|
||||
check_chronyd_messages || test_fail
|
||||
check_chronyd_files || test_fail
|
||||
|
||||
@@ -35,18 +35,18 @@ void
|
||||
test_unit(void)
|
||||
{
|
||||
uint64_t ts64, prev_first_ts64, prev_last_ts64, max_step;
|
||||
int i, j, k, kod, passes, kods, drops, index, shift;
|
||||
uint32_t index2, prev_first, prev_size;
|
||||
NTP_Timestamp_Source ts_src, ts_src2;
|
||||
struct timespec ts, ts2;
|
||||
int i, j, k, index, shift;
|
||||
CLG_Service s;
|
||||
NTP_int64 ntp_ts;
|
||||
IPAddr ip;
|
||||
char conf[][100] = {
|
||||
"clientloglimit 20000",
|
||||
"ratelimit interval 3 burst 4 leak 3",
|
||||
"cmdratelimit interval 3 burst 4 leak 3",
|
||||
"ntsratelimit interval 6 burst 8 leak 3",
|
||||
"ntsratelimit interval 4 burst 8 leak 3",
|
||||
"cmdratelimit interval 6 burst 4 leak 3",
|
||||
};
|
||||
|
||||
CNF_Initialise(0, 0);
|
||||
@@ -80,19 +80,51 @@ test_unit(void)
|
||||
DEBUG_LOG("records %u", ARR_GetSize(records));
|
||||
TEST_CHECK(ARR_GetSize(records) == 128);
|
||||
|
||||
s = CLG_NTP;
|
||||
for (kod = 0; kod <= 2; kod += 2) {
|
||||
for (s = CLG_NTP; s <= CLG_CMDMON; s++) {
|
||||
for (i = passes = kods = drops = 0; i < 10000; i++) {
|
||||
kod_rate[s] = kod;
|
||||
ts.tv_sec += 1;
|
||||
index = CLG_LogServiceAccess(s, &ip, &ts);
|
||||
TEST_CHECK(index >= 0);
|
||||
switch (CLG_LimitServiceRate(s, index)) {
|
||||
case CLG_PASS:
|
||||
passes += 1;
|
||||
break;
|
||||
case CLG_DROP:
|
||||
drops += 1;
|
||||
break;
|
||||
case CLG_KOD:
|
||||
kods += 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = j = 0; i < 10000; i++) {
|
||||
ts.tv_sec += 1;
|
||||
index = CLG_LogServiceAccess(s, &ip, &ts);
|
||||
TEST_CHECK(index >= 0);
|
||||
if (!CLG_LimitServiceRate(s, index))
|
||||
j++;
|
||||
DEBUG_LOG("service %d requests %d passes %d kods %d drops %d",
|
||||
(int)s, i, passes, kods, drops);
|
||||
if (kod)
|
||||
TEST_CHECK(kods * 2.5 < drops && kods * 3.5 > drops);
|
||||
else
|
||||
TEST_CHECK(kods == 0);
|
||||
|
||||
switch (s) {
|
||||
case CLG_NTP:
|
||||
TEST_CHECK(passes > 1750 && passes < 2050);
|
||||
break;
|
||||
case CLG_NTSKE:
|
||||
TEST_CHECK(passes > 1300 && passes < 1600);
|
||||
break;
|
||||
case CLG_CMDMON:
|
||||
TEST_CHECK(passes > 1100 && passes < 1400);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG("requests %d responses %d", i, j);
|
||||
TEST_CHECK(j * 4 < i && j * 6 > i);
|
||||
|
||||
TEST_CHECK(!ntp_ts_map.timestamps);
|
||||
|
||||
UTI_ZeroNtp64(&ntp_ts);
|
||||
|
||||
106
test/unit/leapdb.c
Normal file
106
test/unit/leapdb.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) Patrick Oppenlander 2023
|
||||
*
|
||||
* 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 <leapdb.c>
|
||||
#include "test.h"
|
||||
|
||||
struct test_vector {
|
||||
time_t when;
|
||||
int tai_offset;
|
||||
NTP_Leap leap;
|
||||
int fake;
|
||||
} tests[] = {
|
||||
/* leapdb.list is a cut down version of leap-seconds.list */
|
||||
{3439756800, 34, LEAP_InsertSecond, 0}, /* 1 Jan 2009 */
|
||||
{3550089600, 35, LEAP_InsertSecond, 0}, /* 1 Jul 2012 */
|
||||
{3644697600, 36, LEAP_InsertSecond, 0}, /* 1 Jul 2015 */
|
||||
{3692217600, 37, LEAP_InsertSecond, 0}, /* 1 Jan 2017 */
|
||||
{3786825600, 36, LEAP_DeleteSecond, 1}, /* 1 Jan 2020 fake in leapdb.list */
|
||||
};
|
||||
|
||||
static void
|
||||
test_leap_source(NTP_Leap (*fn)(time_t when, int *tai_offset),
|
||||
int skip_fakes)
|
||||
{
|
||||
int i, prev_tai_offset = 34;
|
||||
|
||||
for (i = 0; i < sizeof tests / sizeof tests[0]; ++i) {
|
||||
struct test_vector *t = tests + i;
|
||||
|
||||
NTP_Leap leap;
|
||||
int tai_offset = -1;
|
||||
|
||||
/* Our unit test leapdb.list contains a fake entry removing a leap second.
|
||||
* Skip this when testing with the right/UTC timezone using mktime(). */
|
||||
if (skip_fakes && t->fake)
|
||||
continue;
|
||||
|
||||
/* One second before leap second */
|
||||
leap = fn(t->when - LEAP_SEC_LIST_OFFSET - 1, &tai_offset);
|
||||
TEST_CHECK(leap == t->leap);
|
||||
TEST_CHECK(tai_offset = prev_tai_offset);
|
||||
|
||||
/* Exactly on leap second */
|
||||
leap = fn(t->when - LEAP_SEC_LIST_OFFSET, &tai_offset);
|
||||
TEST_CHECK(leap == LEAP_Normal);
|
||||
TEST_CHECK(tai_offset == t->tai_offset);
|
||||
|
||||
/* One second after leap second */
|
||||
leap = fn(t->when - LEAP_SEC_LIST_OFFSET + 1, &tai_offset);
|
||||
TEST_CHECK(leap == LEAP_Normal);
|
||||
TEST_CHECK(tai_offset == t->tai_offset);
|
||||
|
||||
prev_tai_offset = t->tai_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_unit(void)
|
||||
{
|
||||
char conf[][100] = {
|
||||
"leapsectz right/UTC",
|
||||
"leapseclist leapdb.list"
|
||||
};
|
||||
int i;
|
||||
|
||||
CNF_Initialise(0, 0);
|
||||
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
|
||||
CNF_ParseLine(NULL, i + 1, conf[i]);
|
||||
LDB_Initialise();
|
||||
|
||||
if (check_leap_source(get_tz_leap)) {
|
||||
DEBUG_LOG("testing get_tz_leap");
|
||||
test_leap_source(get_tz_leap, 1);
|
||||
} else {
|
||||
DEBUG_LOG("Skipping get_tz_leap test. Either the right/UTC timezone is "
|
||||
"missing, or mktime() doesn't support leap seconds.");
|
||||
}
|
||||
|
||||
DEBUG_LOG("testing get_list_leap");
|
||||
TEST_CHECK(check_leap_source(get_list_leap));
|
||||
test_leap_source(get_list_leap, 0);
|
||||
|
||||
/* This exercises the twice-per-day logic */
|
||||
DEBUG_LOG("testing LDB_GetLeap");
|
||||
test_leap_source(LDB_GetLeap, 1);
|
||||
|
||||
LDB_Finalise();
|
||||
CNF_Finalise();
|
||||
}
|
||||
22
test/unit/leapdb.list
Normal file
22
test/unit/leapdb.list
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Cut down version of leap-seconds.list for unit test.
|
||||
#
|
||||
# Blank lines need to be ignored, so include a few for testing.
|
||||
# Whitespace errors on non-blank lines below are copied from the original file.
|
||||
#
|
||||
|
||||
# Leap second data update time
|
||||
#$ 3676924800
|
||||
#
|
||||
# File update time
|
||||
#@ 3928521600
|
||||
|
||||
3439756800 34 # 1 Jan 2009
|
||||
3550089600 35 # 1 Jul 2012
|
||||
3644697600 36 # 1 Jul 2015
|
||||
3692217600 37 # 1 Jan 2017
|
||||
3786825600 36 # 1 Jan 2020 (fake entry to test negative leap second)
|
||||
|
||||
# FIPS 180-1 hash
|
||||
# NOTE! this value has not been recomputed for this unit test file.
|
||||
#h 16edd0f0 3666784f 37db6bdd e74ced87 59af48f1
|
||||
@@ -125,7 +125,7 @@ void
|
||||
test_unit(void)
|
||||
{
|
||||
char source_line[] = "127.0.0.1 offline", conf[] = "port 0", name[64];
|
||||
int i, j, k, slot, found, pool, prev_n;
|
||||
int i, j, k, family, slot, found, pool, prev_n;
|
||||
uint32_t hash = 0, conf_id;
|
||||
NTP_Remote_Address addrs[256], addr;
|
||||
NTP_Local_Address local_addr;
|
||||
@@ -216,7 +216,7 @@ test_unit(void)
|
||||
|
||||
TEST_CHECK(n_sources == 0);
|
||||
|
||||
status = NSR_AddSourceByName("a b", 0, 0, 0, &source.params, &conf_id);
|
||||
status = NSR_AddSourceByName("a b", IPADDR_UNSPEC, 0, 0, 0, &source.params, &conf_id);
|
||||
TEST_CHECK(status == NSR_InvalidName);
|
||||
|
||||
local_addr.ip_addr.family = IPADDR_INET4;
|
||||
@@ -228,11 +228,13 @@ test_unit(void)
|
||||
for (i = 0; i < 500; i++) {
|
||||
for (j = 0; j < 20; j++) {
|
||||
snprintf(name, sizeof (name), "ntp%d.example.net", (int)(random() % 10));
|
||||
family = random() % 2 ? IPADDR_UNSPEC : random() % 2 ? IPADDR_INET4 : IPADDR_INET6;
|
||||
pool = random() % 2;
|
||||
prev_n = n_sources;
|
||||
|
||||
DEBUG_LOG("%d/%d adding source %s pool=%d", i, j, name, pool);
|
||||
status = NSR_AddSourceByName(name, 0, pool, random() % 2 ? NTP_SERVER : NTP_PEER,
|
||||
status = NSR_AddSourceByName(name, family, 0, pool,
|
||||
random() % 2 ? NTP_SERVER : NTP_PEER,
|
||||
&source.params, &conf_id);
|
||||
TEST_CHECK(status == NSR_UnresolvedName);
|
||||
|
||||
@@ -242,11 +244,13 @@ test_unit(void)
|
||||
for (us = unresolved_sources; us->next; us = us->next)
|
||||
;
|
||||
TEST_CHECK(strcmp(us->name, name) == 0);
|
||||
TEST_CHECK(us->family == family);
|
||||
if (pool) {
|
||||
TEST_CHECK(us->address.ip_addr.family == IPADDR_UNSPEC && us->pool_id >= 0);
|
||||
} else {
|
||||
TEST_CHECK(strcmp(NSR_GetName(&us->address.ip_addr), name) == 0);
|
||||
TEST_CHECK(find_slot2(&us->address, &slot) == 2);
|
||||
TEST_CHECK(get_record(slot)->family == family);
|
||||
}
|
||||
|
||||
if (random() % 2) {
|
||||
|
||||
Reference in New Issue
Block a user