mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-05 04:55:08 -05:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe2dbfb6cb | ||
|
|
032ac800aa | ||
|
|
5e86eeacfb | ||
|
|
75b7d33fb7 | ||
|
|
a6e532442b | ||
|
|
a123a12f59 | ||
|
|
f261251a9b | ||
|
|
a0e1154bfb | ||
|
|
e261278a5c | ||
|
|
dbb550e6db | ||
|
|
27a9b0e7b1 | ||
|
|
8a00758cf5 | ||
|
|
15e154c09d | ||
|
|
52d0c9a057 | ||
|
|
4593471ad5 | ||
|
|
a3288d4284 | ||
|
|
22f0da4da6 | ||
|
|
baa977a3ed | ||
|
|
b4b2491015 | ||
|
|
902ed3c694 | ||
|
|
4a9205b341 |
12
NEWS
12
NEWS
@@ -1,6 +1,14 @@
|
|||||||
New in version 1.24
|
New in version 1.24
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
Security fixes
|
||||||
|
--------------
|
||||||
|
* Don't reply to invalid cmdmon packets (CVE-2010-0292)
|
||||||
|
* Limit client log memory size (CVE-2010-0293)
|
||||||
|
* Limit rate of syslog messages (CVE-2010-0294)
|
||||||
|
|
||||||
|
Bug fixes/Enhancements
|
||||||
|
----------------------
|
||||||
* Support for reference clocks (SHM, SOCK, PPS drivers)
|
* Support for reference clocks (SHM, SOCK, PPS drivers)
|
||||||
* IPv6 support
|
* IPv6 support
|
||||||
* Linux capabilities support (to drop root privileges)
|
* Linux capabilities support (to drop root privileges)
|
||||||
@@ -12,8 +20,10 @@ New in version 1.24
|
|||||||
* NTP client support for KoD RATE
|
* NTP client support for KoD RATE
|
||||||
* Read kernel timestamps for received NTP packets
|
* Read kernel timestamps for received NTP packets
|
||||||
* Reply to NTP requests with correct address on multihomed hosts
|
* Reply to NTP requests with correct address on multihomed hosts
|
||||||
* Add option to limit client log memory size
|
|
||||||
* Retry name resolving after temporary failure
|
* Retry name resolving after temporary failure
|
||||||
|
* Fix makestep command, make it available on all systems
|
||||||
|
* Add makestep directive for automatic clock stepping
|
||||||
|
* Don't require _bigadj kernel symbol on NetBSD
|
||||||
* Avoid blocking read in Linux RTC driver
|
* Avoid blocking read in Linux RTC driver
|
||||||
* Support for Linux on S/390 and PowerPC
|
* Support for Linux on S/390 and PowerPC
|
||||||
* Fix various bugs on 64-bit systems
|
* Fix various bugs on 64-bit systems
|
||||||
|
|||||||
52
chrony.texi
52
chrony.texi
@@ -1184,6 +1184,7 @@ directives can occur in any order in the file.
|
|||||||
* logchange directive:: Generate syslog messages if large offsets occur
|
* logchange directive:: Generate syslog messages if large offsets occur
|
||||||
* logdir directive:: Specify directory for logging
|
* logdir directive:: Specify directory for logging
|
||||||
* mailonchange directive:: Send email if a clock correction above a threshold occurs
|
* mailonchange directive:: Send email if a clock correction above a threshold occurs
|
||||||
|
* makestep directive:: Step system clock if large correction is needed
|
||||||
* manual directive:: Allow manual entry using chronyc's settime cmd.
|
* manual directive:: Allow manual entry using chronyc's settime cmd.
|
||||||
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
|
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
|
||||||
* noclientlog directive:: Prevent chronyd from gathering data about clients
|
* noclientlog directive:: Prevent chronyd from gathering data about clients
|
||||||
@@ -2085,6 +2086,32 @@ mailonchange root@@localhost 0.5
|
|||||||
This would send a mail message to root if a change of more than 0.5
|
This would send a mail message to root if a change of more than 0.5
|
||||||
seconds were applied to the system clock.
|
seconds were applied to the system clock.
|
||||||
@c }}}
|
@c }}}
|
||||||
|
@c {{{ makestep
|
||||||
|
@node makestep directive
|
||||||
|
@subsection makestep
|
||||||
|
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, the system clock may be so far adrift that this
|
||||||
|
slewing process would take a very long time to correct the system clock.
|
||||||
|
|
||||||
|
This directive forces @code{chronyd} to step system clock if the
|
||||||
|
adjustment is larger than a threshold value, but only if there were no
|
||||||
|
more clock updates since @code{chronyd} was started than a specified
|
||||||
|
limit (a negative value can be used to disable the limit).
|
||||||
|
|
||||||
|
This is particularly useful when using reference clocks, because the
|
||||||
|
@code{initstepslew} directive (@pxref{initstepslew directive}) works
|
||||||
|
only with NTP sources.
|
||||||
|
|
||||||
|
An example of the use of this directive is
|
||||||
|
|
||||||
|
@example
|
||||||
|
makestep 1000 10
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This would step system clock if the adjustment is larger than 1000
|
||||||
|
seconds, but only in the first ten clock updates.
|
||||||
|
@c }}}
|
||||||
@c {{{ manual
|
@c {{{ manual
|
||||||
@node manual directive
|
@node manual directive
|
||||||
@subsection manual
|
@subsection manual
|
||||||
@@ -2202,8 +2229,8 @@ There are currently three drivers implemented:
|
|||||||
@table @code
|
@table @code
|
||||||
@item PPS
|
@item PPS
|
||||||
Pulse per second (PPS) API driver. The parameter is a path to the PPS
|
Pulse per second (PPS) API driver. The parameter is a path to the PPS
|
||||||
device. Assert events are used by default. The path can have
|
device. Assert events are used by default. Driver option
|
||||||
:1 appended to use clear events instead.
|
@code{:clear} can be appended to the path to use clear events instead.
|
||||||
|
|
||||||
PPS refclock needs another source (NTP or non-PPS refclock) or local
|
PPS refclock needs another source (NTP or non-PPS refclock) or local
|
||||||
directive (@pxref{local directive}) enabled to function. For example:
|
directive (@pxref{local directive}) enabled to function. For example:
|
||||||
@@ -2215,14 +2242,18 @@ refclock PPS /dev/pps0
|
|||||||
|
|
||||||
@item SHM
|
@item SHM
|
||||||
NTP shared memory driver. The parameter is the number of the
|
NTP shared memory driver. The parameter is the number of the
|
||||||
shared memory segment that should be used to read timestamps, usually
|
shared memory segment that should be used for receiving timestamps, usually
|
||||||
0, 1, 2 or 3. For example:
|
0, 1, 2 or 3. For example:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
refclock SHM 1 poll 3 refid GPS1
|
refclock SHM 1 poll 3 refid GPS1
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Software that can be used as a source of timestamps includes
|
A driver option in form @code{:perm=NNN} can be appended to the
|
||||||
|
segment number to create the segment with permissions other than the
|
||||||
|
default @code{0600}.
|
||||||
|
|
||||||
|
Software that can be used as a source of reference time includes
|
||||||
@code{gpsd} and @code{shmpps}.
|
@code{gpsd} and @code{shmpps}.
|
||||||
@item SOCK
|
@item SOCK
|
||||||
Unix domain socket driver. The parameter is a path to the socket
|
Unix domain socket driver. The parameter is a path to the socket
|
||||||
@@ -2262,6 +2293,12 @@ PPS signal frequency (in Hz). This option only controls how the
|
|||||||
received pulses are aligned. To actually receive more than one
|
received pulses are aligned. To actually receive more than one
|
||||||
pulse per second, a negative @code{dpoll} has to be specified (-3 for
|
pulse per second, a negative @code{dpoll} has to be specified (-3 for
|
||||||
5Hz signal). The default is 1.
|
5Hz signal). The default is 1.
|
||||||
|
@item lock
|
||||||
|
This option can be used to lock a PPS refclock to another refclock
|
||||||
|
whose reference id is specified by this option. In this mode received
|
||||||
|
pulses are aligned directly to unfiltered samples from the refclock.
|
||||||
|
By default, pulses are aligned to local clock, but only when it is
|
||||||
|
well synchronised.
|
||||||
@item offset
|
@item offset
|
||||||
This option can be used to compensate a constant error. The specified
|
This option can be used to compensate a constant error. The specified
|
||||||
offset (in seconds) is applied to all samples produced by the
|
offset (in seconds) is applied to all samples produced by the
|
||||||
@@ -2586,6 +2623,8 @@ Only the following commands can be used @emph{without} providing a
|
|||||||
password:
|
password:
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
|
@item @code{activity}
|
||||||
|
@item @code{clients}
|
||||||
@item @code{dns}
|
@item @code{dns}
|
||||||
@item @code{exit}
|
@item @code{exit}
|
||||||
@item @code{help}
|
@item @code{help}
|
||||||
@@ -3076,8 +3115,9 @@ BE WARNED - certain software will be seriously affected by such jumps to
|
|||||||
the system time. (That is the reason why chronyd uses slewing
|
the system time. (That is the reason why chronyd uses slewing
|
||||||
normally.)
|
normally.)
|
||||||
|
|
||||||
The @code{makestep} command is currently only available on the Linux
|
The @code{makestep} directive in the configuration file can be used
|
||||||
version of chrony.
|
to step the clock automatically when the adjustment is larger than a
|
||||||
|
specified threshold, see @ref{makestep directive}.
|
||||||
@c }}}
|
@c }}}
|
||||||
@c {{{ manual
|
@c {{{ manual
|
||||||
@node manual command
|
@node manual command
|
||||||
|
|||||||
8
client.c
8
client.c
@@ -1558,7 +1558,7 @@ process_cmd_sources(char *line)
|
|||||||
uint32_t latest_meas_ago;
|
uint32_t latest_meas_ago;
|
||||||
uint16_t poll, stratum;
|
uint16_t poll, stratum;
|
||||||
uint16_t state, mode;
|
uint16_t state, mode;
|
||||||
char hostname_buf[32];
|
char hostname_buf[50];
|
||||||
|
|
||||||
/* Check whether to output verbose headers */
|
/* Check whether to output verbose headers */
|
||||||
verbose = check_for_verbose_flag(line);
|
verbose = check_for_verbose_flag(line);
|
||||||
@@ -1658,7 +1658,7 @@ process_cmd_sourcestats(char *line)
|
|||||||
int n_sources, i;
|
int n_sources, i;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
|
||||||
char hostname_buf[32];
|
char hostname_buf[50];
|
||||||
unsigned long n_samples, n_runs, span_seconds;
|
unsigned long n_samples, n_runs, span_seconds;
|
||||||
double resid_freq_ppm, skew_ppm, sd, est_offset, est_offset_err;
|
double resid_freq_ppm, skew_ppm, sd, est_offset, est_offset_err;
|
||||||
unsigned long ref_id;
|
unsigned long ref_id;
|
||||||
@@ -1859,7 +1859,7 @@ process_cmd_clients(char *line)
|
|||||||
unsigned long cmd_hits_bad;
|
unsigned long cmd_hits_bad;
|
||||||
unsigned long last_ntp_hit_ago;
|
unsigned long last_ntp_hit_ago;
|
||||||
unsigned long last_cmd_hit_ago;
|
unsigned long last_cmd_hit_ago;
|
||||||
char hostname_buf[32];
|
char hostname_buf[50];
|
||||||
|
|
||||||
int n_replies;
|
int n_replies;
|
||||||
|
|
||||||
@@ -2044,7 +2044,7 @@ process_cmd_clients(char *line)
|
|||||||
unsigned long cmd_hits_bad;
|
unsigned long cmd_hits_bad;
|
||||||
unsigned long last_ntp_hit_ago;
|
unsigned long last_ntp_hit_ago;
|
||||||
unsigned long last_cmd_hit_ago;
|
unsigned long last_cmd_hit_ago;
|
||||||
char hostname_buf[32];
|
char hostname_buf[50];
|
||||||
|
|
||||||
int n_replies;
|
int n_replies;
|
||||||
int n_indices_in_table;
|
int n_indices_in_table;
|
||||||
|
|||||||
74
cmdmon.c
74
cmdmon.c
@@ -746,7 +746,7 @@ transmit_reply(CMD_Reply *msg, union sockaddr_in46 *where_to)
|
|||||||
status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
|
status = sendto(sock_fd, (void *) msg, tx_message_length, 0,
|
||||||
&where_to->u, addrlen);
|
&where_to->u, addrlen);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0 && !LOG_RateLimited()) {
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
IPAddr ip;
|
IPAddr ip;
|
||||||
|
|
||||||
@@ -1676,13 +1676,8 @@ handle_manual_delete(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
static void
|
static void
|
||||||
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
|
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||||
{
|
{
|
||||||
int status;
|
LCL_MakeStep(0.0);
|
||||||
status = LCL_MakeStep();
|
tx_message->status = htons(STT_SUCCESS);
|
||||||
if (status) {
|
|
||||||
tx_message->status = htons(STT_SUCCESS);
|
|
||||||
} else {
|
|
||||||
tx_message->status = htons(STT_NOTENABLED);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1739,6 +1734,7 @@ read_from_cmd_socket(void *anything)
|
|||||||
int valid_ts;
|
int valid_ts;
|
||||||
int authenticated;
|
int authenticated;
|
||||||
int localhost;
|
int localhost;
|
||||||
|
int allowed;
|
||||||
unsigned short rx_command;
|
unsigned short rx_command;
|
||||||
unsigned long rx_message_token;
|
unsigned long rx_message_token;
|
||||||
unsigned long tx_message_token;
|
unsigned long tx_message_token;
|
||||||
@@ -1809,26 +1805,7 @@ read_from_cmd_socket(void *anything)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!ADF_IsAllowed(access_auth_table, &remote_ip)) &&
|
allowed = ADF_IsAllowed(access_auth_table, &remote_ip) || localhost;
|
||||||
(!localhost)) {
|
|
||||||
/* The client is not allowed access, so don't waste any more time
|
|
||||||
on him. Note that localhost is always allowed access
|
|
||||||
regardless of the defined access rules - otherwise, we could
|
|
||||||
shut ourselves out completely! */
|
|
||||||
|
|
||||||
/* We ought to find another way to log this, there is an attack
|
|
||||||
here against the host because an adversary can just keep
|
|
||||||
hitting us with bad packets until our log file(s) fill up. */
|
|
||||||
|
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
|
|
||||||
UTI_IPToString(&remote_ip),
|
|
||||||
remote_port);
|
|
||||||
|
|
||||||
tx_message.status = htons(STT_NOHOSTACCESS);
|
|
||||||
transmit_reply(&tx_message, &where_from);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_length < offsetof(CMD_Request, data) ||
|
if (read_length < offsetof(CMD_Request, data) ||
|
||||||
rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
|
rx_message.pkt_type != PKT_TYPE_CMD_REQUEST ||
|
||||||
@@ -1836,15 +1813,19 @@ read_from_cmd_socket(void *anything)
|
|||||||
rx_message.res2 != 0) {
|
rx_message.res2 != 0) {
|
||||||
|
|
||||||
/* We don't know how to process anything like this */
|
/* We don't know how to process anything like this */
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
if (allowed)
|
||||||
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
if (rx_message.version != PROTO_VERSION_NUMBER) {
|
||||||
tx_message.status = htons(STT_NOHOSTACCESS);
|
tx_message.status = htons(STT_NOHOSTACCESS);
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Read packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
|
if (!LOG_RateLimited()) {
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Read packet with protocol version %d (expected %d) from %s:%hu", rx_message.version, PROTO_VERSION_NUMBER, UTI_IPToString(&remote_ip), remote_port);
|
||||||
|
}
|
||||||
|
if (allowed)
|
||||||
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT) {
|
if (rx_message.version >= PROTO_VERSION_MISMATCH_COMPAT) {
|
||||||
tx_message.status = htons(STT_BADPKTVERSION);
|
tx_message.status = htons(STT_BADPKTVERSION);
|
||||||
@@ -1854,14 +1835,35 @@ read_from_cmd_socket(void *anything)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (read_length != expected_length) {
|
if (read_length != expected_length) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
if (!LOG_RateLimited()) {
|
||||||
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Read incorrectly sized packet from %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
||||||
|
}
|
||||||
|
if (allowed)
|
||||||
|
CLG_LogCommandAccess(&remote_ip, CLG_CMD_BAD_PKT, cooked_now.tv_sec);
|
||||||
|
|
||||||
tx_message.status = htons(STT_BADPKTLENGTH);
|
tx_message.status = htons(STT_BADPKTLENGTH);
|
||||||
transmit_reply(&tx_message, &where_from);
|
transmit_reply(&tx_message, &where_from);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!allowed) {
|
||||||
|
/* The client is not allowed access, so don't waste any more time
|
||||||
|
on him. Note that localhost is always allowed access
|
||||||
|
regardless of the defined access rules - otherwise, we could
|
||||||
|
shut ourselves out completely! */
|
||||||
|
|
||||||
|
if (!LOG_RateLimited()) {
|
||||||
|
LOG(LOGS_WARN, LOGF_CmdMon, "Command packet received from unauthorised host %s port %d",
|
||||||
|
UTI_IPToString(&remote_ip),
|
||||||
|
remote_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_message.status = htons(STT_NOHOSTACCESS);
|
||||||
|
transmit_reply(&tx_message, &where_from);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rx_command = ntohs(rx_message.command);
|
rx_command = ntohs(rx_message.command);
|
||||||
|
|
||||||
/* OK, we have a valid message. Now dispatch on message type and process it. */
|
/* OK, we have a valid message. Now dispatch on message type and process it. */
|
||||||
@@ -1938,7 +1940,7 @@ read_from_cmd_socket(void *anything)
|
|||||||
tx_message_length = PKL_ReplyLength(prev_tx_message);
|
tx_message_length = PKL_ReplyLength(prev_tx_message);
|
||||||
status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
|
status = sendto(sock_fd, (void *) prev_tx_message, tx_message_length, 0,
|
||||||
&where_from.u, from_length);
|
&where_from.u, from_length);
|
||||||
if (status < 0) {
|
if (status < 0 && !LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
LOG(LOGS_WARN, LOGF_CmdMon, "Could not send response to %s:%hu", UTI_IPToString(&remote_ip), remote_port);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1994,7 +1996,7 @@ read_from_cmd_socket(void *anything)
|
|||||||
tx_message.status = htons(STT_INVALID);
|
tx_message.status = htons(STT_INVALID);
|
||||||
tx_message.reply = htons(RPY_NULL);
|
tx_message.reply = htons(RPY_NULL);
|
||||||
} else {
|
} else {
|
||||||
int allowed = 0;
|
allowed = 0;
|
||||||
|
|
||||||
/* Check level of authority required to issue the command */
|
/* Check level of authority required to issue the command */
|
||||||
switch(permissions[rx_command]) {
|
switch(permissions[rx_command]) {
|
||||||
@@ -2064,7 +2066,7 @@ read_from_cmd_socket(void *anything)
|
|||||||
|
|
||||||
case REQ_LOGON:
|
case REQ_LOGON:
|
||||||
/* If the log-on fails, record the reason why */
|
/* If the log-on fails, record the reason why */
|
||||||
if (!issue_token) {
|
if (!issue_token && !LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_CmdMon,
|
LOG(LOGS_WARN, LOGF_CmdMon,
|
||||||
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
|
"Bad command logon from %s port %d (md5_ok=%d valid_ts=%d)\n",
|
||||||
UTI_IPToString(&remote_ip),
|
UTI_IPToString(&remote_ip),
|
||||||
|
|||||||
36
conf.c
36
conf.c
@@ -92,6 +92,7 @@ static void parse_cmdport(const char *);
|
|||||||
static void parse_rtconutc(const char *);
|
static void parse_rtconutc(const char *);
|
||||||
static void parse_noclientlog(const char *);
|
static void parse_noclientlog(const char *);
|
||||||
static void parse_clientloglimit(const char *);
|
static void parse_clientloglimit(const char *);
|
||||||
|
static void parse_makestep(const char *);
|
||||||
static void parse_logchange(const char *);
|
static void parse_logchange(const char *);
|
||||||
static void parse_mailonchange(const char *);
|
static void parse_mailonchange(const char *);
|
||||||
static void parse_bindaddress(const char *);
|
static void parse_bindaddress(const char *);
|
||||||
@@ -146,6 +147,10 @@ static int enable_manual=0;
|
|||||||
incl. daylight saving). */
|
incl. daylight saving). */
|
||||||
static int rtc_on_utc = 0;
|
static int rtc_on_utc = 0;
|
||||||
|
|
||||||
|
/* Limit and threshold for clock stepping */
|
||||||
|
static int make_step_limit = 0;
|
||||||
|
static double make_step_threshold = 0.0;
|
||||||
|
|
||||||
/* Flag set if we should log to syslog when a time adjustment
|
/* Flag set if we should log to syslog when a time adjustment
|
||||||
exceeding the threshold is initiated */
|
exceeding the threshold is initiated */
|
||||||
static int do_log_change = 0;
|
static int do_log_change = 0;
|
||||||
@@ -220,6 +225,7 @@ static const Command commands[] = {
|
|||||||
{"rtconutc", 8, parse_rtconutc},
|
{"rtconutc", 8, parse_rtconutc},
|
||||||
{"noclientlog", 11, parse_noclientlog},
|
{"noclientlog", 11, parse_noclientlog},
|
||||||
{"clientloglimit", 14, parse_clientloglimit},
|
{"clientloglimit", 14, parse_clientloglimit},
|
||||||
|
{"makestep", 8, parse_makestep},
|
||||||
{"logchange", 9, parse_logchange},
|
{"logchange", 9, parse_logchange},
|
||||||
{"mailonchange", 12, parse_mailonchange},
|
{"mailonchange", 12, parse_mailonchange},
|
||||||
{"bindaddress", 11, parse_bindaddress},
|
{"bindaddress", 11, parse_bindaddress},
|
||||||
@@ -430,7 +436,7 @@ static void
|
|||||||
parse_refclock(const char *line)
|
parse_refclock(const char *line)
|
||||||
{
|
{
|
||||||
int i, n, poll, dpoll, filter_length, pps_rate;
|
int i, n, poll, dpoll, filter_length, pps_rate;
|
||||||
unsigned long ref_id;
|
unsigned long ref_id, lock_ref_id;
|
||||||
double offset, delay;
|
double offset, delay;
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
char name[5], cmd[10 + 1], *param;
|
char name[5], cmd[10 + 1], *param;
|
||||||
@@ -447,6 +453,7 @@ parse_refclock(const char *line)
|
|||||||
offset = 0.0;
|
offset = 0.0;
|
||||||
delay = 1e-9;
|
delay = 1e-9;
|
||||||
ref_id = 0;
|
ref_id = 0;
|
||||||
|
lock_ref_id = 0;
|
||||||
|
|
||||||
if (sscanf(line, "%4s%n", name, &n) != 1) {
|
if (sscanf(line, "%4s%n", name, &n) != 1) {
|
||||||
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name at line %d", line_number);
|
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name at line %d", line_number);
|
||||||
@@ -475,6 +482,10 @@ parse_refclock(const char *line)
|
|||||||
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
|
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
|
||||||
break;
|
break;
|
||||||
ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
|
ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
|
||||||
|
} else if (!strncasecmp(cmd, "lock", 4)) {
|
||||||
|
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
|
||||||
|
break;
|
||||||
|
lock_ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
|
||||||
} else if (!strncasecmp(cmd, "poll", 4)) {
|
} else if (!strncasecmp(cmd, "poll", 4)) {
|
||||||
if (sscanf(line, "%d%n", &poll, &n) != 1) {
|
if (sscanf(line, "%d%n", &poll, &n) != 1) {
|
||||||
break;
|
break;
|
||||||
@@ -512,6 +523,7 @@ parse_refclock(const char *line)
|
|||||||
refclock_sources[i].offset = offset;
|
refclock_sources[i].offset = offset;
|
||||||
refclock_sources[i].delay = delay;
|
refclock_sources[i].delay = delay;
|
||||||
refclock_sources[i].ref_id = ref_id;
|
refclock_sources[i].ref_id = ref_id;
|
||||||
|
refclock_sources[i].lock_ref_id = lock_ref_id;
|
||||||
|
|
||||||
n_refclock_sources++;
|
n_refclock_sources++;
|
||||||
}
|
}
|
||||||
@@ -788,6 +800,19 @@ parse_clientloglimit(const char *line)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_makestep(const char *line)
|
||||||
|
{
|
||||||
|
if (sscanf(line, "%lf %d", &make_step_threshold, &make_step_limit) != 2) {
|
||||||
|
make_step_limit = 0;
|
||||||
|
LOG(LOGS_WARN, LOGF_Configure,
|
||||||
|
"Could not read threshold or update limit for stepping clock at line %d\n",
|
||||||
|
line_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_logchange(const char *line)
|
parse_logchange(const char *line)
|
||||||
{
|
{
|
||||||
@@ -1319,6 +1344,15 @@ CNF_GetRTCOnUTC(void)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
CNF_GetMakeStep(int *limit, double *threshold)
|
||||||
|
{
|
||||||
|
*limit = make_step_limit;
|
||||||
|
*threshold = make_step_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
CNF_GetLogChange(int *enabled, double *threshold)
|
CNF_GetLogChange(int *enabled, double *threshold)
|
||||||
{
|
{
|
||||||
|
|||||||
1
conf.h
1
conf.h
@@ -60,6 +60,7 @@ extern int CNF_GetDumpOnExit(void);
|
|||||||
extern int CNF_GetManualEnabled(void);
|
extern int CNF_GetManualEnabled(void);
|
||||||
extern int CNF_GetCommandPort(void);
|
extern int CNF_GetCommandPort(void);
|
||||||
extern int CNF_GetRTCOnUTC(void);
|
extern int CNF_GetRTCOnUTC(void);
|
||||||
|
extern void CNF_GetMakeStep(int *limit, double *threshold);
|
||||||
extern void CNF_GetLogChange(int *enabled, double *threshold);
|
extern void CNF_GetLogChange(int *enabled, double *threshold);
|
||||||
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
|
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
|
||||||
extern int CNF_GetNoClientLog(void);
|
extern int CNF_GetNoClientLog(void);
|
||||||
|
|||||||
30
local.c
30
local.c
@@ -53,7 +53,6 @@ static lcl_SetFrequencyDriver drv_set_freq;
|
|||||||
static lcl_AccrueOffsetDriver drv_accrue_offset;
|
static lcl_AccrueOffsetDriver drv_accrue_offset;
|
||||||
static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
|
static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
|
||||||
static lcl_OffsetCorrectionDriver drv_offset_convert;
|
static lcl_OffsetCorrectionDriver drv_offset_convert;
|
||||||
static lcl_ImmediateStepDriver drv_immediate_step;
|
|
||||||
static lcl_SetLeapDriver drv_set_leap;
|
static lcl_SetLeapDriver drv_set_leap;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -536,7 +535,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
|||||||
lcl_AccrueOffsetDriver accrue_offset,
|
lcl_AccrueOffsetDriver accrue_offset,
|
||||||
lcl_ApplyStepOffsetDriver apply_step_offset,
|
lcl_ApplyStepOffsetDriver apply_step_offset,
|
||||||
lcl_OffsetCorrectionDriver offset_convert,
|
lcl_OffsetCorrectionDriver offset_convert,
|
||||||
lcl_ImmediateStepDriver immediate_step,
|
|
||||||
lcl_SetLeapDriver set_leap)
|
lcl_SetLeapDriver set_leap)
|
||||||
{
|
{
|
||||||
drv_read_freq = read_freq;
|
drv_read_freq = read_freq;
|
||||||
@@ -544,7 +542,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
|||||||
drv_accrue_offset = accrue_offset;
|
drv_accrue_offset = accrue_offset;
|
||||||
drv_apply_step_offset = apply_step_offset;
|
drv_apply_step_offset = apply_step_offset;
|
||||||
drv_offset_convert = offset_convert;
|
drv_offset_convert = offset_convert;
|
||||||
drv_immediate_step = immediate_step;
|
|
||||||
drv_set_leap = set_leap;
|
drv_set_leap = set_leap;
|
||||||
|
|
||||||
current_freq_ppm = (*drv_read_freq)();
|
current_freq_ppm = (*drv_read_freq)();
|
||||||
@@ -558,20 +555,27 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Look at the current difference between the system time and the NTP
|
/* Look at the current difference between the system time and the NTP
|
||||||
time, and make a step to cancel it. */
|
time, and make a step to cancel it if it's larger than the threshold. */
|
||||||
|
|
||||||
int
|
int
|
||||||
LCL_MakeStep(void)
|
LCL_MakeStep(double threshold)
|
||||||
{
|
{
|
||||||
if (drv_immediate_step) {
|
struct timeval raw;
|
||||||
(drv_immediate_step)();
|
double correction;
|
||||||
#ifdef TRACEON
|
|
||||||
LOG(LOGS_INFO, LOGF_Local, "Made step to system time to apply remaining slew");
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
LCL_ReadRawTime(&raw);
|
||||||
|
correction = LCL_GetOffsetCorrection(&raw);
|
||||||
|
|
||||||
|
if (fabs(correction) <= threshold)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Cancel remaining slew and make the step */
|
||||||
|
LCL_AccumulateOffset(correction);
|
||||||
|
LCL_ApplyStepOffset(-correction);
|
||||||
|
|
||||||
|
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.3f seconds", correction);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
2
local.h
2
local.h
@@ -179,7 +179,7 @@ extern void LCL_Finalise(void);
|
|||||||
/* Routine to convert the outstanding system clock error to a step and
|
/* Routine to convert the outstanding system clock error to a step and
|
||||||
apply it, e.g. if the system clock has ended up an hour wrong due
|
apply it, e.g. if the system clock has ended up an hour wrong due
|
||||||
to a timezone problem. */
|
to a timezone problem. */
|
||||||
extern int LCL_MakeStep(void);
|
extern int LCL_MakeStep(double threshold);
|
||||||
|
|
||||||
/* Routine to schedule a leap second. Leap second will be inserted
|
/* Routine to schedule a leap second. Leap second will be inserted
|
||||||
at the end of the day if argument is positive, deleted if negative,
|
at the end of the day if argument is positive, deleted if negative,
|
||||||
|
|||||||
5
localp.h
5
localp.h
@@ -56,10 +56,6 @@ typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
|
|||||||
raw time to get the corrected time */
|
raw time to get the corrected time */
|
||||||
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
|
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
|
||||||
|
|
||||||
/* System driver to stop slewing the current offset and to apply is
|
|
||||||
as an immediate step instead */
|
|
||||||
typedef void (*lcl_ImmediateStepDriver)(void);
|
|
||||||
|
|
||||||
/* System driver to schedule leap second */
|
/* System driver to schedule leap second */
|
||||||
typedef void (*lcl_SetLeapDriver)(int leap);
|
typedef void (*lcl_SetLeapDriver)(int leap);
|
||||||
|
|
||||||
@@ -71,7 +67,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
|
|||||||
lcl_AccrueOffsetDriver accrue_offset,
|
lcl_AccrueOffsetDriver accrue_offset,
|
||||||
lcl_ApplyStepOffsetDriver apply_step_offset,
|
lcl_ApplyStepOffsetDriver apply_step_offset,
|
||||||
lcl_OffsetCorrectionDriver offset_convert,
|
lcl_OffsetCorrectionDriver offset_convert,
|
||||||
lcl_ImmediateStepDriver immediate_step_driver,
|
|
||||||
lcl_SetLeapDriver set_leap);
|
lcl_SetLeapDriver set_leap);
|
||||||
|
|
||||||
#endif /* GOT_LOCALP_H */
|
#endif /* GOT_LOCALP_H */
|
||||||
|
|||||||
18
logging.c
18
logging.c
@@ -40,6 +40,8 @@ static int initialised = 0;
|
|||||||
|
|
||||||
static int is_detached = 0;
|
static int is_detached = 0;
|
||||||
|
|
||||||
|
static time_t last_limited = 0;
|
||||||
|
|
||||||
#ifdef WINNT
|
#ifdef WINNT
|
||||||
static FILE *logfile;
|
static FILE *logfile;
|
||||||
#endif
|
#endif
|
||||||
@@ -213,6 +215,22 @@ LOG_GoDaemon(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
LOG_RateLimited(void)
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
now = time(NULL);
|
||||||
|
|
||||||
|
if (last_limited + 10 > now && last_limited <= now)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
last_limited = now;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Force a core dump and exit without doing abort() or assert(0).
|
/* Force a core dump and exit without doing abort() or assert(0).
|
||||||
These do funny things with the call stack in the core file that is
|
These do funny things with the call stack in the core file that is
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ extern void LOG_Position(const char *filename, int line_number, const char *func
|
|||||||
|
|
||||||
extern void LOG_GoDaemon(void);
|
extern void LOG_GoDaemon(void);
|
||||||
|
|
||||||
|
/* Return zero once per 10 seconds */
|
||||||
|
extern int LOG_RateLimited(void);
|
||||||
|
|
||||||
/* Line logging macro. If the compiler is GNU C, we take advantage of
|
/* Line logging macro. If the compiler is GNU C, we take advantage of
|
||||||
being able to get the function name also. */
|
being able to get the function name also. */
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
|||||||
2
main.c
2
main.c
@@ -255,7 +255,7 @@ int main
|
|||||||
} else if (!strcmp("-6", *argv)) {
|
} else if (!strcmp("-6", *argv)) {
|
||||||
DNS_SetAddressFamily(IPADDR_INET6);
|
DNS_SetAddressFamily(IPADDR_INET6);
|
||||||
} else {
|
} else {
|
||||||
LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
nameserv.c
33
nameserv.c
@@ -127,33 +127,38 @@ try_again:
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
int
|
||||||
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
||||||
{
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
int result;
|
|
||||||
struct sockaddr_in in4;
|
struct sockaddr_in in4;
|
||||||
struct sockaddr_in6 in6;
|
struct sockaddr_in6 in6;
|
||||||
|
char hbuf[NI_MAXHOST];
|
||||||
|
|
||||||
switch (ip_addr->family) {
|
switch (ip_addr->family) {
|
||||||
case IPADDR_INET4:
|
case IPADDR_INET4:
|
||||||
memset(&in4, 0, sizeof (in4));
|
memset(&in4, 0, sizeof (in4));
|
||||||
|
#ifdef SIN6_LEN
|
||||||
|
in4.sin_len = sizeof (in4);
|
||||||
|
#endif
|
||||||
in4.sin_family = AF_INET;
|
in4.sin_family = AF_INET;
|
||||||
in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
|
in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
|
||||||
result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
|
if (!getnameinfo((const struct sockaddr *)&in4, sizeof (in4), hbuf, sizeof (hbuf), NULL, 0, 0))
|
||||||
|
result = hbuf;
|
||||||
break;
|
break;
|
||||||
case IPADDR_INET6:
|
case IPADDR_INET6:
|
||||||
memset(&in6, 0, sizeof (in6));
|
memset(&in6, 0, sizeof (in6));
|
||||||
|
#ifdef SIN6_LEN
|
||||||
|
in6.sin6_len = sizeof (in6);
|
||||||
|
#endif
|
||||||
in6.sin6_family = AF_INET6;
|
in6.sin6_family = AF_INET6;
|
||||||
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
|
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
|
||||||
result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
|
if (!getnameinfo((const struct sockaddr *)&in6, sizeof (in6), hbuf, sizeof (hbuf), NULL, 0, 0))
|
||||||
|
result = hbuf;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
result = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
|
||||||
snprintf(name, len, "%s", UTI_IPToString(ip_addr));
|
|
||||||
#else
|
#else
|
||||||
struct hostent *host;
|
struct hostent *host;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
@@ -171,8 +176,16 @@ DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
|
|||||||
default:
|
default:
|
||||||
host = NULL;
|
host = NULL;
|
||||||
}
|
}
|
||||||
snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
|
if (host)
|
||||||
|
result = host->h_name;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
result = UTI_IPToString(ip_addr);
|
||||||
|
if (snprintf(name, len, "%s", result) >= len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ extern void DNS_SetAddressFamily(int family);
|
|||||||
|
|
||||||
extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
|
extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
|
||||||
|
|
||||||
extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
|
extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
|
||||||
|
|
||||||
#endif /* GOT_NAMESERV_H */
|
#endif /* GOT_NAMESERV_H */
|
||||||
|
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
|
|||||||
result->local_rx.tv_usec = 0;
|
result->local_rx.tv_usec = 0;
|
||||||
result->local_tx.tv_sec = 0;
|
result->local_tx.tv_sec = 0;
|
||||||
result->local_tx.tv_usec = 0;
|
result->local_tx.tv_usec = 0;
|
||||||
|
result->local_ntp_tx.hi = 0;
|
||||||
|
result->local_ntp_tx.lo = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1391,7 +1393,7 @@ process_known
|
|||||||
&inst->local_ntp_tx,
|
&inst->local_ntp_tx,
|
||||||
&inst->remote_addr);
|
&inst->remote_addr);
|
||||||
|
|
||||||
} else {
|
} else if (!LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
|
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
|
||||||
UTI_IPToString(&inst->remote_addr.ip_addr),
|
UTI_IPToString(&inst->remote_addr.ip_addr),
|
||||||
inst->remote_addr.port);
|
inst->remote_addr.port);
|
||||||
@@ -1559,7 +1561,7 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
|
|||||||
remote_addr);
|
remote_addr);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
|
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
|
||||||
UTI_IPToString(&remote_addr->ip_addr),
|
UTI_IPToString(&remote_addr->ip_addr),
|
||||||
remote_addr->port);
|
remote_addr->port);
|
||||||
|
|||||||
2
ntp_io.c
2
ntp_io.c
@@ -460,7 +460,7 @@ send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
|
|||||||
if (!cmsglen)
|
if (!cmsglen)
|
||||||
msg.msg_control = NULL;
|
msg.msg_control = NULL;
|
||||||
|
|
||||||
if (sendmsg(sock_fd, &msg, 0) < 0) {
|
if (sendmsg(sock_fd, &msg, 0) < 0 && !LOG_RateLimited()) {
|
||||||
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
|
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
|
||||||
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
|
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|||||||
126
refclock.c
126
refclock.c
@@ -50,6 +50,7 @@ struct MedianFilter {
|
|||||||
int length;
|
int length;
|
||||||
int index;
|
int index;
|
||||||
int used;
|
int used;
|
||||||
|
int last;
|
||||||
struct FilterSample *samples;
|
struct FilterSample *samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ struct RCL_Instance_Record {
|
|||||||
RefclockDriver *driver;
|
RefclockDriver *driver;
|
||||||
void *data;
|
void *data;
|
||||||
char *driver_parameter;
|
char *driver_parameter;
|
||||||
|
int driver_parameter_length;
|
||||||
int driver_poll;
|
int driver_poll;
|
||||||
int driver_polled;
|
int driver_polled;
|
||||||
int poll;
|
int poll;
|
||||||
@@ -65,6 +67,7 @@ struct RCL_Instance_Record {
|
|||||||
int pps_rate;
|
int pps_rate;
|
||||||
struct MedianFilter filter;
|
struct MedianFilter filter;
|
||||||
unsigned long ref_id;
|
unsigned long ref_id;
|
||||||
|
unsigned long lock_ref;
|
||||||
double offset;
|
double offset;
|
||||||
double delay;
|
double delay;
|
||||||
SCH_TimeoutID timeout_id;
|
SCH_TimeoutID timeout_id;
|
||||||
@@ -92,6 +95,7 @@ static void filter_init(struct MedianFilter *filter, int length);
|
|||||||
static void filter_fini(struct MedianFilter *filter);
|
static void filter_fini(struct MedianFilter *filter);
|
||||||
static void filter_reset(struct MedianFilter *filter);
|
static void filter_reset(struct MedianFilter *filter);
|
||||||
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset);
|
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset);
|
||||||
|
static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset);
|
||||||
static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
|
static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
|
||||||
static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
|
static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
|
||||||
|
|
||||||
@@ -166,17 +170,28 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
|
|
||||||
inst->data = NULL;
|
inst->data = NULL;
|
||||||
inst->driver_parameter = params->driver_parameter;
|
inst->driver_parameter = params->driver_parameter;
|
||||||
|
inst->driver_parameter_length = 0;
|
||||||
inst->driver_poll = params->driver_poll;
|
inst->driver_poll = params->driver_poll;
|
||||||
inst->poll = params->poll;
|
inst->poll = params->poll;
|
||||||
inst->missed_samples = 0;
|
inst->missed_samples = 0;
|
||||||
inst->driver_polled = 0;
|
inst->driver_polled = 0;
|
||||||
inst->leap_status = 0;
|
inst->leap_status = 0;
|
||||||
inst->pps_rate = params->pps_rate;
|
inst->pps_rate = params->pps_rate;
|
||||||
|
inst->lock_ref = params->lock_ref_id;
|
||||||
inst->offset = params->offset;
|
inst->offset = params->offset;
|
||||||
inst->delay = params->delay;
|
inst->delay = params->delay;
|
||||||
inst->timeout_id = -1;
|
inst->timeout_id = -1;
|
||||||
inst->source = NULL;
|
inst->source = NULL;
|
||||||
|
|
||||||
|
if (inst->driver_parameter) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
inst->driver_parameter_length = strlen(inst->driver_parameter);
|
||||||
|
for (i = 0; i < inst->driver_parameter_length; i++)
|
||||||
|
if (inst->driver_parameter[i] == ':')
|
||||||
|
inst->driver_parameter[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
if (pps_source) {
|
if (pps_source) {
|
||||||
if (inst->pps_rate < 1)
|
if (inst->pps_rate < 1)
|
||||||
inst->pps_rate = 1;
|
inst->pps_rate = 1;
|
||||||
@@ -216,13 +231,21 @@ RCL_AddRefclock(RefclockParameters *params)
|
|||||||
void
|
void
|
||||||
RCL_StartRefclocks(void)
|
RCL_StartRefclocks(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < n_sources; i++) {
|
for (i = 0; i < n_sources; i++) {
|
||||||
RCL_Instance inst = &refclocks[i];
|
RCL_Instance inst = &refclocks[i];
|
||||||
|
|
||||||
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
|
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
|
||||||
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
|
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
|
||||||
|
|
||||||
|
if (inst->lock_ref) {
|
||||||
|
/* Replace lock refid with index to refclocks */
|
||||||
|
for (j = 0; j < n_sources && refclocks[j].ref_id != inst->lock_ref; j++)
|
||||||
|
;
|
||||||
|
inst->lock_ref = (j < n_sources) ? j : -1;
|
||||||
|
} else
|
||||||
|
inst->lock_ref = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_sources > 0)
|
if (n_sources > 0)
|
||||||
@@ -266,6 +289,31 @@ RCL_GetDriverParameter(RCL_Instance instance)
|
|||||||
return instance->driver_parameter;
|
return instance->driver_parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
RCL_GetDriverOption(RCL_Instance instance, char *name)
|
||||||
|
{
|
||||||
|
char *s, *e;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
s = instance->driver_parameter;
|
||||||
|
e = s + instance->driver_parameter_length;
|
||||||
|
n = strlen(name);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
s += strlen(s) + 1;
|
||||||
|
if (s >= e)
|
||||||
|
break;
|
||||||
|
if (!strncmp(name, s, n)) {
|
||||||
|
if (s[n] == '=')
|
||||||
|
return s + n + 1;
|
||||||
|
if (s[n] == '\0')
|
||||||
|
return s + n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
|
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
|
||||||
{
|
{
|
||||||
@@ -313,22 +361,6 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
|
|||||||
rate = instance->pps_rate;
|
rate = instance->pps_rate;
|
||||||
assert(rate > 0);
|
assert(rate > 0);
|
||||||
|
|
||||||
/* Ignore the pulse if we are not well synchronized */
|
|
||||||
|
|
||||||
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
|
|
||||||
&ref_id, &ref_time, &root_delay, &root_dispersion);
|
|
||||||
distance = fabs(root_delay) / 2 + root_dispersion;
|
|
||||||
|
|
||||||
if (!is_synchronised || distance >= 0.5 / rate) {
|
|
||||||
#if 0
|
|
||||||
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse dropped second=%.9f sync=%d dist=%.9f",
|
|
||||||
second, is_synchronised, distance);
|
|
||||||
#endif
|
|
||||||
/* Drop also all stored samples */
|
|
||||||
filter_reset(&instance->filter);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = -second - correction + instance->offset;
|
offset = -second - correction + instance->offset;
|
||||||
|
|
||||||
/* Adjust the offset to [-0.5/rate, 0.5/rate) interval */
|
/* Adjust the offset to [-0.5/rate, 0.5/rate) interval */
|
||||||
@@ -338,9 +370,54 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
|
|||||||
else if (offset >= 0.5 / rate)
|
else if (offset >= 0.5 / rate)
|
||||||
offset -= 1.0 / rate;
|
offset -= 1.0 / rate;
|
||||||
|
|
||||||
|
if (instance->lock_ref != -1) {
|
||||||
|
struct timeval ref_sample_time;
|
||||||
|
double sample_diff, ref_offset, shift;
|
||||||
|
|
||||||
|
if (!filter_get_last_sample(&refclocks[instance->lock_ref].filter,
|
||||||
|
&ref_sample_time, &ref_offset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
|
||||||
|
if (fabs(sample_diff) >= 2.0 / rate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Align the offset to the reference sample */
|
||||||
|
if ((ref_offset - offset) >= 0.0)
|
||||||
|
shift = (long)((ref_offset - offset) * rate + 0.5) / (double)rate;
|
||||||
|
else
|
||||||
|
shift = (long)((ref_offset - offset) * rate - 0.5) / (double)rate;
|
||||||
|
|
||||||
|
offset += shift;
|
||||||
|
|
||||||
|
if (fabs(ref_offset - offset) >= 0.2 / rate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
|
||||||
|
second, offset, ref_offset - offset, sample_diff);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* Ignore the pulse if we are not well synchronized */
|
||||||
|
|
||||||
|
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
|
||||||
|
&ref_id, &ref_time, &root_delay, &root_dispersion);
|
||||||
|
distance = fabs(root_delay) / 2 + root_dispersion;
|
||||||
|
|
||||||
|
if (!is_synchronised || distance >= 0.5 / rate) {
|
||||||
|
#if 0
|
||||||
|
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse dropped second=%.9f sync=%d dist=%.9f",
|
||||||
|
second, is_synchronised, distance);
|
||||||
|
#endif
|
||||||
|
/* Drop also all stored samples */
|
||||||
|
filter_reset(&instance->filter);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f",
|
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f",
|
||||||
second, offset + instance->offset);
|
second, offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
filter_add_sample(&instance->filter, &cooked_time, offset);
|
filter_add_sample(&instance->filter, &cooked_time, offset);
|
||||||
@@ -511,6 +588,7 @@ filter_init(struct MedianFilter *filter, int length)
|
|||||||
filter->length = length;
|
filter->length = length;
|
||||||
filter->index = -1;
|
filter->index = -1;
|
||||||
filter->used = 0;
|
filter->used = 0;
|
||||||
|
filter->last = -1;
|
||||||
filter->samples = MallocArray(struct FilterSample, filter->length);
|
filter->samples = MallocArray(struct FilterSample, filter->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,6 +610,7 @@ filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
|
|||||||
{
|
{
|
||||||
filter->index++;
|
filter->index++;
|
||||||
filter->index %= filter->length;
|
filter->index %= filter->length;
|
||||||
|
filter->last = filter->index;
|
||||||
if (filter->used < filter->length)
|
if (filter->used < filter->length)
|
||||||
filter->used++;
|
filter->used++;
|
||||||
|
|
||||||
@@ -539,6 +618,17 @@ filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
|
|||||||
filter->samples[filter->index].offset = offset;
|
filter->samples[filter->index].offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset)
|
||||||
|
{
|
||||||
|
if (filter->last < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*sample_time = filter->samples[filter->last].sample_time;
|
||||||
|
*offset = filter->samples[filter->last].offset;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sample_compare(const void *a, const void *b)
|
sample_compare(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ typedef struct {
|
|||||||
int filter_length;
|
int filter_length;
|
||||||
int pps_rate;
|
int pps_rate;
|
||||||
unsigned long ref_id;
|
unsigned long ref_id;
|
||||||
|
unsigned long lock_ref_id;
|
||||||
double offset;
|
double offset;
|
||||||
double delay;
|
double delay;
|
||||||
} RefclockParameters;
|
} RefclockParameters;
|
||||||
@@ -63,6 +64,7 @@ extern void RCL_CycleLogFile(void);
|
|||||||
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
|
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
|
||||||
extern void *RCL_GetDriverData(RCL_Instance instance);
|
extern void *RCL_GetDriverData(RCL_Instance instance);
|
||||||
extern char *RCL_GetDriverParameter(RCL_Instance instance);
|
extern char *RCL_GetDriverParameter(RCL_Instance instance);
|
||||||
|
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
|
||||||
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
|
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
|
||||||
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
|
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
|
||||||
|
|
||||||
|
|||||||
@@ -46,15 +46,10 @@ static int pps_initialise(RCL_Instance instance) {
|
|||||||
pps_params_t params;
|
pps_params_t params;
|
||||||
struct pps_instance *pps;
|
struct pps_instance *pps;
|
||||||
int fd, edge_clear, mode;
|
int fd, edge_clear, mode;
|
||||||
char *path, *s;
|
char *path;
|
||||||
|
|
||||||
path = RCL_GetDriverParameter(instance);
|
path = RCL_GetDriverParameter(instance);
|
||||||
|
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
|
||||||
edge_clear = 0;
|
|
||||||
if ((s = strrchr(path, ':')) != NULL) {
|
|
||||||
*s = '\0';
|
|
||||||
edge_clear = atoi(s + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|||||||
@@ -56,12 +56,15 @@ struct shmTime {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int shm_initialise(RCL_Instance instance) {
|
static int shm_initialise(RCL_Instance instance) {
|
||||||
int id, param;
|
int id, param, perm;
|
||||||
|
char *s;
|
||||||
struct shmTime *shm;
|
struct shmTime *shm;
|
||||||
|
|
||||||
param = atoi(RCL_GetDriverParameter(instance));
|
param = atoi(RCL_GetDriverParameter(instance));
|
||||||
|
s = RCL_GetDriverOption(instance, "perm");
|
||||||
|
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
|
||||||
|
|
||||||
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | 0700);
|
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | perm);
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
LOG_FATAL(LOGF_Refclock, "shmget() failed");
|
LOG_FATAL(LOGF_Refclock, "shmget() failed");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
86
reference.c
86
reference.c
@@ -61,6 +61,10 @@ static double max_update_skew;
|
|||||||
/* Flag indicating that we are initialised */
|
/* Flag indicating that we are initialised */
|
||||||
static int initialised = 0;
|
static int initialised = 0;
|
||||||
|
|
||||||
|
/* Threshold and update limit for stepping clock */
|
||||||
|
static int make_step_limit;
|
||||||
|
static double make_step_threshold;
|
||||||
|
|
||||||
/* Flag and threshold for logging clock changes to syslog */
|
/* Flag and threshold for logging clock changes to syslog */
|
||||||
static int do_log_change;
|
static int do_log_change;
|
||||||
static double log_change_threshold;
|
static double log_change_threshold;
|
||||||
@@ -87,9 +91,6 @@ static unsigned long logwrites = 0;
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
/* Day number of 1 Jan 1970 */
|
|
||||||
#define MJD_1970 40587
|
|
||||||
|
|
||||||
/* Reference ID supplied when we are locally referenced */
|
/* Reference ID supplied when we are locally referenced */
|
||||||
#define LOCAL_REFERENCE_ID 0x7f7f0101UL
|
#define LOCAL_REFERENCE_ID 0x7f7f0101UL
|
||||||
|
|
||||||
@@ -164,6 +165,7 @@ REF_Initialise(void)
|
|||||||
|
|
||||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
|
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
|
||||||
|
|
||||||
|
CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
|
||||||
CNF_GetLogChange(&do_log_change, &log_change_threshold);
|
CNF_GetLogChange(&do_log_change, &log_change_threshold);
|
||||||
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
|
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
|
||||||
|
|
||||||
@@ -246,7 +248,9 @@ update_drift_file(double freq_ppm, double skew)
|
|||||||
/* Clone the file attributes from the existing file if there is one. */
|
/* Clone the file attributes from the existing file if there is one. */
|
||||||
|
|
||||||
if (!stat(drift_file,&buf)) {
|
if (!stat(drift_file,&buf)) {
|
||||||
chown(temp_drift_file,buf.st_uid,buf.st_gid);
|
if (chown(temp_drift_file,buf.st_uid,buf.st_gid)) {
|
||||||
|
LOG(LOGS_WARN, LOGF_Reference, "Could not change ownership of temporary driftfile %s.tmp", drift_file);
|
||||||
|
}
|
||||||
chmod(temp_drift_file,buf.st_mode&0777);
|
chmod(temp_drift_file,buf.st_mode&0777);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +323,19 @@ maybe_log_offset(double offset)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_make_step()
|
||||||
|
{
|
||||||
|
if (make_step_limit == 0) {
|
||||||
|
return;
|
||||||
|
} else if (make_step_limit > 0) {
|
||||||
|
make_step_limit--;
|
||||||
|
}
|
||||||
|
LCL_MakeStep(make_step_threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_leap_status(NTP_Leap leap)
|
update_leap_status(NTP_Leap leap)
|
||||||
{
|
{
|
||||||
@@ -357,6 +374,26 @@ update_leap_status(NTP_Leap leap)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_log(struct timeval *ref_time, char *ref, int stratum, double freq, double skew, double offset)
|
||||||
|
{
|
||||||
|
if (logfile) {
|
||||||
|
|
||||||
|
if (((logwrites++) % 32) == 0) {
|
||||||
|
fprintf(logfile,
|
||||||
|
"=======================================================================\n"
|
||||||
|
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset\n"
|
||||||
|
"=======================================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
|
||||||
|
UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew, offset);
|
||||||
|
|
||||||
|
fflush(logfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
REF_SetReference(int stratum,
|
REF_SetReference(int stratum,
|
||||||
@@ -468,28 +505,17 @@ REF_SetReference(int stratum,
|
|||||||
our_residual_freq = frequency;
|
our_residual_freq = frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_make_step();
|
||||||
|
|
||||||
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
|
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
|
||||||
|
|
||||||
if (logfile) {
|
write_log(ref_time,
|
||||||
|
|
||||||
if (((logwrites++) % 32) == 0) {
|
|
||||||
fprintf(logfile,
|
|
||||||
"=======================================================================\n"
|
|
||||||
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset\n"
|
|
||||||
"=======================================================================\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
|
|
||||||
UTI_TimeToLogForm(ref_time->tv_sec),
|
|
||||||
our_ref_ip.family != IPADDR_UNSPEC ? UTI_IPToString(&our_ref_ip) : UTI_RefidToString(our_ref_id),
|
our_ref_ip.family != IPADDR_UNSPEC ? UTI_IPToString(&our_ref_ip) : UTI_RefidToString(our_ref_id),
|
||||||
our_stratum,
|
our_stratum,
|
||||||
abs_freq_ppm,
|
abs_freq_ppm,
|
||||||
1.0e6*our_skew,
|
1.0e6*our_skew,
|
||||||
our_offset);
|
our_offset);
|
||||||
|
|
||||||
fflush(logfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drift_file) {
|
if (drift_file) {
|
||||||
update_drift_file(abs_freq_ppm, our_skew);
|
update_drift_file(abs_freq_ppm, our_skew);
|
||||||
}
|
}
|
||||||
@@ -512,7 +538,6 @@ REF_SetManualReference
|
|||||||
double skew
|
double skew
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int millisecond;
|
|
||||||
double abs_freq_ppm;
|
double abs_freq_ppm;
|
||||||
|
|
||||||
/* We are not synchronised to an external source, as such. This is
|
/* We are not synchronised to an external source, as such. This is
|
||||||
@@ -525,23 +550,17 @@ REF_SetManualReference
|
|||||||
|
|
||||||
maybe_log_offset(offset);
|
maybe_log_offset(offset);
|
||||||
LCL_AccumulateFrequencyAndOffset(frequency, offset);
|
LCL_AccumulateFrequencyAndOffset(frequency, offset);
|
||||||
|
maybe_make_step();
|
||||||
|
|
||||||
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
|
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
|
||||||
|
|
||||||
if (logfile) {
|
write_log(ref_time,
|
||||||
millisecond = ref_time->tv_usec / 1000;
|
|
||||||
|
|
||||||
fprintf(logfile, "%5s %-15s %2d %10.3f %10.3f %10.3e\n",
|
|
||||||
UTI_TimeToLogForm(ref_time->tv_sec),
|
|
||||||
"127.127.1.1",
|
"127.127.1.1",
|
||||||
our_stratum,
|
our_stratum,
|
||||||
abs_freq_ppm,
|
abs_freq_ppm,
|
||||||
1.0e6*our_skew,
|
1.0e6*our_skew,
|
||||||
our_offset);
|
our_offset);
|
||||||
|
|
||||||
fflush(logfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drift_file) {
|
if (drift_file) {
|
||||||
update_drift_file(abs_freq_ppm, our_skew);
|
update_drift_file(abs_freq_ppm, our_skew);
|
||||||
}
|
}
|
||||||
@@ -553,27 +572,20 @@ void
|
|||||||
REF_SetUnsynchronised(void)
|
REF_SetUnsynchronised(void)
|
||||||
{
|
{
|
||||||
/* Variables required for logging to statistics log */
|
/* Variables required for logging to statistics log */
|
||||||
int millisecond;
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
double local_clock_err;
|
double local_clock_err;
|
||||||
|
|
||||||
assert(initialised);
|
assert(initialised);
|
||||||
|
|
||||||
if (logfile) {
|
LCL_ReadCookedTime(&now, &local_clock_err);
|
||||||
LCL_ReadCookedTime(&now, &local_clock_err);
|
|
||||||
|
|
||||||
millisecond = now.tv_usec / 1000;
|
write_log(&now,
|
||||||
|
|
||||||
fprintf(logfile, "%s %-15s 0 %10.3f %10.3f %10.3e\n",
|
|
||||||
UTI_TimeToLogForm(now.tv_sec),
|
|
||||||
"0.0.0.0",
|
"0.0.0.0",
|
||||||
|
0,
|
||||||
LCL_ReadAbsoluteFrequency(),
|
LCL_ReadAbsoluteFrequency(),
|
||||||
1.0e6*our_skew,
|
1.0e6*our_skew,
|
||||||
0.0);
|
0.0);
|
||||||
|
|
||||||
fflush(logfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
are_we_synchronised = 0;
|
are_we_synchronised = 0;
|
||||||
|
|
||||||
update_leap_status(LEAP_Unsynchronised);
|
update_leap_status(LEAP_Unsynchronised);
|
||||||
|
|||||||
@@ -511,7 +511,9 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
|
|||||||
/* Clone the file attributes from the existing file if there is one. */
|
/* Clone the file attributes from the existing file if there is one. */
|
||||||
|
|
||||||
if (!stat(coefs_file_name,&buf)) {
|
if (!stat(coefs_file_name,&buf)) {
|
||||||
chown(temp_coefs_file_name,buf.st_uid,buf.st_gid);
|
if (chown(temp_coefs_file_name,buf.st_uid,buf.st_gid)) {
|
||||||
|
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not change ownership of temporary RTC file %s.tmp", coefs_file_name);
|
||||||
|
}
|
||||||
chmod(temp_coefs_file_name,buf.st_mode&0777);
|
chmod(temp_coefs_file_name,buf.st_mode&0777);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
sched.c
2
sched.c
@@ -440,7 +440,7 @@ dispatch_timeouts(struct timeval *now) {
|
|||||||
TimerQueueEntry *ptr;
|
TimerQueueEntry *ptr;
|
||||||
int n_done = 0;
|
int n_done = 0;
|
||||||
|
|
||||||
while ((n_timer_queue_entries > 0) &&
|
if ((n_timer_queue_entries > 0) &&
|
||||||
(UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
|
(UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
|
||||||
ptr = timer_queue.next;
|
ptr = timer_queue.next;
|
||||||
|
|
||||||
|
|||||||
42
sys_linux.c
42
sys_linux.c
@@ -353,7 +353,9 @@ initiate_slew(void)
|
|||||||
fast_slewing = 1;
|
fast_slewing = 1;
|
||||||
slew_start_tv = T0a;
|
slew_start_tv = T0a;
|
||||||
|
|
||||||
/* Set up timeout for end of slew */
|
/* Set up timeout for end of slew, limit to one week */
|
||||||
|
if (dseconds > 3600 * 24 * 7)
|
||||||
|
dseconds = 3600 * 24 * 7;
|
||||||
UTI_AddDoubleToTimeval(&T0a, dseconds, &end_of_slew);
|
UTI_AddDoubleToTimeval(&T0a, dseconds, &end_of_slew);
|
||||||
|
|
||||||
slew_timeout_id = SCH_AddTimeout(&end_of_slew, handle_end_of_slew, NULL);
|
slew_timeout_id = SCH_AddTimeout(&end_of_slew, handle_end_of_slew, NULL);
|
||||||
@@ -606,42 +608,6 @@ again:
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
|
||||||
immediate_step(void)
|
|
||||||
{
|
|
||||||
struct timeval old_time, new_time;
|
|
||||||
struct timezone tz;
|
|
||||||
long offset;
|
|
||||||
|
|
||||||
if (fast_slewing) {
|
|
||||||
abort_slew();
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
if (TMX_ApplyOffset(&offset) < 0) {
|
|
||||||
CROAK("adjtimex() failed in immediate_step");
|
|
||||||
}
|
|
||||||
|
|
||||||
offset_register -= (double) offset / 1.0e6;
|
|
||||||
slow_slewing = 0;
|
|
||||||
|
|
||||||
if (gettimeofday(&old_time, &tz) < 0) {
|
|
||||||
CROAK("gettimeofday() failed in immediate_step");
|
|
||||||
}
|
|
||||||
|
|
||||||
UTI_AddDoubleToTimeval(&old_time, -offset_register, &new_time);
|
|
||||||
|
|
||||||
if (settimeofday(&new_time, &tz) < 0) {
|
|
||||||
CROAK("settimeofday() failed in immediate_step");
|
|
||||||
}
|
|
||||||
|
|
||||||
offset_register = 0.0;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_leap(int leap)
|
set_leap(int leap)
|
||||||
{
|
{
|
||||||
@@ -884,7 +850,7 @@ SYS_Linux_Initialise(void)
|
|||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, apply_step_offset,
|
accrue_offset, apply_step_offset,
|
||||||
get_offset_correction, immediate_step, set_leap);
|
get_offset_correction, set_leap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ SYS_NetBSD_Initialise(void)
|
|||||||
kvm_t *kt;
|
kvm_t *kt;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
|
kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
||||||
if (!kt) {
|
if (!kt) {
|
||||||
CROAK("Cannot open kvm\n");
|
CROAK("Cannot open kvm\n");
|
||||||
}
|
}
|
||||||
@@ -299,7 +299,8 @@ SYS_NetBSD_Initialise(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {
|
if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {
|
||||||
CROAK("Cannot read from _bigadj\n");
|
/* kernel doesn't have the symbol, use one second instead */
|
||||||
|
kern_bigadj = 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
kvm_close(kt);
|
kvm_close(kt);
|
||||||
@@ -308,7 +309,7 @@ SYS_NetBSD_Initialise(void)
|
|||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, apply_step_offset,
|
accrue_offset, apply_step_offset,
|
||||||
get_offset_correction, NULL /* immediate_step */,
|
get_offset_correction,
|
||||||
NULL /* set_leap */);
|
NULL /* set_leap */);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ SYS_Solaris_Initialise(void)
|
|||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, apply_step_offset,
|
accrue_offset, apply_step_offset,
|
||||||
get_offset_correction, NULL /* immediate_step */,
|
get_offset_correction,
|
||||||
NULL /* set_leap */);
|
NULL /* set_leap */);
|
||||||
|
|
||||||
/* Turn off the kernel switch that keeps the system clock in step
|
/* Turn off the kernel switch that keeps the system clock in step
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ SYS_SunOS_Initialise(void)
|
|||||||
|
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, apply_step_offset,
|
accrue_offset, apply_step_offset,
|
||||||
get_offset_correction, NULL /* immediate_step */,
|
get_offset_correction,
|
||||||
NULL /* set_leap */);
|
NULL /* set_leap */);
|
||||||
|
|
||||||
/* Turn off the kernel switch that keeps the system clock in step
|
/* Turn off the kernel switch that keeps the system clock in step
|
||||||
|
|||||||
19
util.c
19
util.c
@@ -244,14 +244,19 @@ UTI_TimestampToString(NTP_int64 *ts)
|
|||||||
char *
|
char *
|
||||||
UTI_RefidToString(unsigned long ref_id)
|
UTI_RefidToString(unsigned long ref_id)
|
||||||
{
|
{
|
||||||
unsigned int a, b, c, d;
|
unsigned int i, j, c;
|
||||||
char *result;
|
char buf[5], *result;
|
||||||
a = (ref_id>>24) & 0xff;
|
|
||||||
b = (ref_id>>16) & 0xff;
|
for (i = j = 0; i < 4; i++) {
|
||||||
c = (ref_id>> 8) & 0xff;
|
c = (ref_id >> (24 - i * 8)) & 0xff;
|
||||||
d = (ref_id>> 0) & 0xff;
|
if (isprint(c))
|
||||||
|
buf[j++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[j] = '\0';
|
||||||
|
|
||||||
result = NEXT_BUFFER;
|
result = NEXT_BUFFER;
|
||||||
snprintf(result, BUFFER_LENGTH, "%c%c%c%c", a, b, c, d);
|
snprintf(result, BUFFER_LENGTH, "%s", buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user