mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-05 11:55:07 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b197953e8 | ||
|
|
9dcace0fc4 | ||
|
|
a07ac38331 | ||
|
|
166e43b13e | ||
|
|
b84d6759f9 |
3
candm.h
3
candm.h
@@ -734,7 +734,8 @@ typedef struct {
|
|||||||
uint32_t total_tx_count;
|
uint32_t total_tx_count;
|
||||||
uint32_t total_rx_count;
|
uint32_t total_rx_count;
|
||||||
uint32_t total_valid_count;
|
uint32_t total_valid_count;
|
||||||
uint32_t reserved[4];
|
uint32_t total_good_count;
|
||||||
|
uint32_t reserved[3];
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} RPY_NTPData;
|
} RPY_NTPData;
|
||||||
|
|
||||||
|
|||||||
6
client.c
6
client.c
@@ -2346,7 +2346,8 @@ process_cmd_ntpdata(char *line)
|
|||||||
"RX timestamping : %N\n"
|
"RX timestamping : %N\n"
|
||||||
"Total TX : %U\n"
|
"Total TX : %U\n"
|
||||||
"Total RX : %U\n"
|
"Total RX : %U\n"
|
||||||
"Total valid RX : %U\n",
|
"Total valid RX : %U\n"
|
||||||
|
"Total good RX : %U\n",
|
||||||
UTI_IPToString(&remote_addr), (unsigned long)UTI_IPToRefid(&remote_addr),
|
UTI_IPToString(&remote_addr), (unsigned long)UTI_IPToRefid(&remote_addr),
|
||||||
ntohs(reply.data.ntp_data.remote_port),
|
ntohs(reply.data.ntp_data.remote_port),
|
||||||
UTI_IPToString(&local_addr), (unsigned long)UTI_IPToRefid(&local_addr),
|
UTI_IPToString(&local_addr), (unsigned long)UTI_IPToRefid(&local_addr),
|
||||||
@@ -2374,6 +2375,7 @@ process_cmd_ntpdata(char *line)
|
|||||||
(unsigned long)ntohl(reply.data.ntp_data.total_tx_count),
|
(unsigned long)ntohl(reply.data.ntp_data.total_tx_count),
|
||||||
(unsigned long)ntohl(reply.data.ntp_data.total_rx_count),
|
(unsigned long)ntohl(reply.data.ntp_data.total_rx_count),
|
||||||
(unsigned long)ntohl(reply.data.ntp_data.total_valid_count),
|
(unsigned long)ntohl(reply.data.ntp_data.total_valid_count),
|
||||||
|
(unsigned long)ntohl(reply.data.ntp_data.total_good_count),
|
||||||
REPORT_END);
|
REPORT_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3298,7 +3300,7 @@ static void
|
|||||||
display_gpl(void)
|
display_gpl(void)
|
||||||
{
|
{
|
||||||
printf("chrony version %s\n"
|
printf("chrony version %s\n"
|
||||||
"Copyright (C) 1997-2003, 2007, 2009-2021 Richard P. Curnow and others\n"
|
"Copyright (C) 1997-2003, 2007, 2009-2022 Richard P. Curnow and others\n"
|
||||||
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
"chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
|
||||||
"you are welcome to redistribute it under certain conditions. See the\n"
|
"you are welcome to redistribute it under certain conditions. See the\n"
|
||||||
"GNU General Public License version 2 for details.\n\n",
|
"GNU General Public License version 2 for details.\n\n",
|
||||||
|
|||||||
1
cmdmon.c
1
cmdmon.c
@@ -1224,6 +1224,7 @@ handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||||||
tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
|
tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
|
||||||
tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
|
tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
|
||||||
tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
|
tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
|
||||||
|
tx_message->data.ntp_data.total_good_count = htonl(report.total_good_count);
|
||||||
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
|
memset(tx_message->data.ntp_data.reserved, 0xff, sizeof (tx_message->data.ntp_data.reserved));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Stephen Wadeley 2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Bryan Christianson 2017
|
// Copyright (C) Bryan Christianson 2017
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2021
|
// Copyright (C) Miroslav Lichvar 2009-2022
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -63,10 +63,22 @@ source. The client-server relationship is strictly hierarchical: a client might
|
|||||||
synchronise its system time to that of the server, but the server's system time
|
synchronise its system time to that of the server, but the server's system time
|
||||||
will never be influenced by that of a client.
|
will never be influenced by that of a client.
|
||||||
+
|
+
|
||||||
|
The server can be specified by its hostname or IP address. If the hostname cannot
|
||||||
|
be resolved on start, *chronyd* will try it again in increasing intervals, and
|
||||||
|
also when the <<chronyc.adoc#online,*online*>> command is issued in *chronyc*.
|
||||||
|
+
|
||||||
|
The DNS record can change over time. The used address will be replaced with a
|
||||||
|
newly resolved address when the server becomes unreachable (i.e. no valid
|
||||||
|
response to last 8 requests), unsynchronised, a falseticker (i.e. does not
|
||||||
|
agree with a majority of other sources), or the root distance is too large (the
|
||||||
|
limit can be configured by the <<maxdistance,*maxdistance*>> directive). The
|
||||||
|
automatic replacement happens at most once per 30 minutes. It can also be
|
||||||
|
triggered manually for all sources by the <<chronyc.adoc#refresh,*refresh*>>
|
||||||
|
command in *chronyc*.
|
||||||
|
+
|
||||||
This directive can be used multiple times to specify multiple servers.
|
This directive can be used multiple times to specify multiple servers.
|
||||||
+
|
+
|
||||||
The directive is immediately followed by either the name of the
|
The directive supports the following options:
|
||||||
server, or its IP address. It supports the following options:
|
|
||||||
+
|
+
|
||||||
*minpoll* _poll_:::
|
*minpoll* _poll_:::
|
||||||
This option specifies the minimum interval between requests sent to the server
|
This option specifies the minimum interval between requests sent to the server
|
||||||
@@ -341,12 +353,6 @@ This option sets the desired number of sources to be used from the pool.
|
|||||||
sources responding to requests. The default value is 4 and the maximum value is
|
sources responding to requests. The default value is 4 and the maximum value is
|
||||||
16.
|
16.
|
||||||
+
|
+
|
||||||
{blank}::
|
|
||||||
When an NTP source is unreachable,
|
|
||||||
marked as a falseticker, or has a distance larger than the limit set by the
|
|
||||||
<<maxdistance,*maxdistance*>> directive, *chronyd* will try to replace the
|
|
||||||
source with a newly resolved address of the name.
|
|
||||||
+
|
|
||||||
An example of the *pool* directive is
|
An example of the *pool* directive is
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Stephen Wadeley 2016
|
// Copyright (C) Stephen Wadeley 2016
|
||||||
// Copyright (C) Miroslav Lichvar 2009-2017, 2019-2020
|
// Copyright (C) Miroslav Lichvar 2009-2017, 2019-2022
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -180,15 +180,19 @@ stratum-2 and is synchronised from a stratum-1).
|
|||||||
This is the time (UTC) at which the last measurement from the reference
|
This is the time (UTC) at which the last measurement from the reference
|
||||||
source was processed.
|
source was processed.
|
||||||
*System time*:::
|
*System time*:::
|
||||||
In normal operation, *chronyd* by default never steps the system clock, because
|
This is the current offset between the NTP clock and system clock. The NTP
|
||||||
any jump in the time can have adverse consequences for certain application
|
clock is a software (virtual) clock maintained by *chronyd*, which is
|
||||||
programs. Instead, any error in the system clock is corrected by slightly
|
synchronised to the configured time sources and provides time to NTP clients.
|
||||||
speeding up or slowing down the system clock until the error has been removed,
|
The system clock is synchronised to the NTP clock. To avoid steps in the
|
||||||
and then returning to the system clock's normal speed. A consequence of this is
|
system time, which might have adverse consequences for certain applications,
|
||||||
that there will be a period when the system clock (as read by other programs)
|
the system clock is normally corrected only by speeding up or slowing down (up
|
||||||
will be different from *chronyd*'s estimate of the current true time (which it
|
to the rate configured by the <<chrony.conf.adoc#maxslewrate,*maxslewrate*>>
|
||||||
reports to NTP clients when it is operating as a server). The value reported
|
directive). If the offset is too large, this correction will take a very long
|
||||||
on this line is the difference due to this effect.
|
time. A step can be forced by the <<makestep,*makestep*>> command, or the
|
||||||
|
<<chrony.conf.adoc#makestep,*makestep*>> directive in the configuration file.
|
||||||
|
+
|
||||||
|
Note that all other offsets reported by *chronyc* and most offsets in the log
|
||||||
|
files are relative to the NTP clock, not the system clock.
|
||||||
*Last offset*:::
|
*Last offset*:::
|
||||||
This is the estimated local offset on the last clock update. A positive value
|
This is the estimated local offset on the last clock update. A positive value
|
||||||
indicates the local time (as previously estimated true time) was ahead of the
|
indicates the local time (as previously estimated true time) was ahead of the
|
||||||
@@ -662,6 +666,7 @@ RX timestamping : Kernel
|
|||||||
Total TX : 24
|
Total TX : 24
|
||||||
Total RX : 24
|
Total RX : 24
|
||||||
Total valid RX : 24
|
Total valid RX : 24
|
||||||
|
Total good RX : 22
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
The fields are explained as follows:
|
The fields are explained as follows:
|
||||||
@@ -715,7 +720,10 @@ The number of packets sent to the source.
|
|||||||
*Total RX*:::
|
*Total RX*:::
|
||||||
The number of all packets received from the source.
|
The number of all packets received from the source.
|
||||||
*Total valid RX*:::
|
*Total valid RX*:::
|
||||||
The number of valid packets received from the source.
|
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.
|
||||||
|
|
||||||
[[add_peer]]*add peer* _name_ [_option_]...::
|
[[add_peer]]*add peer* _name_ [_option_]...::
|
||||||
The *add peer* command allows a new NTP peer to be added whilst
|
The *add peer* command allows a new NTP peer to be added whilst
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// This file is part of chrony
|
// This file is part of chrony
|
||||||
//
|
//
|
||||||
// Copyright (C) Richard P. Curnow 1997-2003
|
// Copyright (C) Richard P. Curnow 1997-2003
|
||||||
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2021
|
// Copyright (C) Miroslav Lichvar 2014-2016, 2020-2022
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of version 2 of the GNU General Public License as
|
// it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016-2018
|
* Copyright (C) Miroslav Lichvar 2016-2018, 2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
22
ntp_core.c
22
ntp_core.c
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2021
|
* Copyright (C) Miroslav Lichvar 2009-2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
@@ -556,6 +556,16 @@ take_offline(NCR_Instance inst)
|
|||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_report(NCR_Instance inst)
|
||||||
|
{
|
||||||
|
memset(&inst->report, 0, sizeof (inst->report));
|
||||||
|
inst->report.remote_addr = inst->remote_addr.ip_addr;
|
||||||
|
inst->report.remote_port = inst->remote_addr.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
NCR_Instance
|
NCR_Instance
|
||||||
NCR_CreateInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
NCR_CreateInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
||||||
SourceParameters *params, const char *name)
|
SourceParameters *params, const char *name)
|
||||||
@@ -672,12 +682,13 @@ NCR_CreateInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
|||||||
zero_local_timestamp(&result->local_tx);
|
zero_local_timestamp(&result->local_tx);
|
||||||
result->burst_good_samples_to_go = 0;
|
result->burst_good_samples_to_go = 0;
|
||||||
result->burst_total_samples_to_go = 0;
|
result->burst_total_samples_to_go = 0;
|
||||||
memset(&result->report, 0, sizeof (result->report));
|
|
||||||
|
|
||||||
NCR_ResetInstance(result);
|
NCR_ResetInstance(result);
|
||||||
|
|
||||||
set_connectivity(result, params->connectivity);
|
set_connectivity(result, params->connectivity);
|
||||||
|
|
||||||
|
reset_report(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +788,6 @@ NCR_ResetPoll(NCR_Instance instance)
|
|||||||
void
|
void
|
||||||
NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int ntp_only)
|
NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int ntp_only)
|
||||||
{
|
{
|
||||||
memset(&inst->report, 0, sizeof (inst->report));
|
|
||||||
NCR_ResetInstance(inst);
|
NCR_ResetInstance(inst);
|
||||||
|
|
||||||
if (!ntp_only)
|
if (!ntp_only)
|
||||||
@@ -798,6 +808,8 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int
|
|||||||
SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr),
|
SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr),
|
||||||
&inst->remote_addr.ip_addr);
|
&inst->remote_addr.ip_addr);
|
||||||
SRC_ResetInstance(inst->source);
|
SRC_ResetInstance(inst->source);
|
||||||
|
|
||||||
|
reset_report(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
@@ -2179,9 +2191,7 @@ process_response(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update the NTP report */
|
/* Update the NTP report */
|
||||||
inst->report.remote_addr = inst->remote_addr.ip_addr;
|
|
||||||
inst->report.local_addr = inst->local_addr.ip_addr;
|
inst->report.local_addr = inst->local_addr.ip_addr;
|
||||||
inst->report.remote_port = inst->remote_addr.port;
|
|
||||||
inst->report.leap = pkt_leap;
|
inst->report.leap = pkt_leap;
|
||||||
inst->report.version = pkt_version;
|
inst->report.version = pkt_version;
|
||||||
inst->report.mode = NTP_LVM_TO_MODE(message->lvm);
|
inst->report.mode = NTP_LVM_TO_MODE(message->lvm);
|
||||||
@@ -2206,6 +2216,8 @@ process_response(NCR_Instance inst, NTP_Local_Address *local_addr,
|
|||||||
inst->report.rx_tss_char = tss_chars[local_receive.source];
|
inst->report.rx_tss_char = tss_chars[local_receive.source];
|
||||||
|
|
||||||
inst->report.total_valid_count++;
|
inst->report.total_valid_count++;
|
||||||
|
if (good_packet)
|
||||||
|
inst->report.total_good_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do measurement logging */
|
/* Do measurement logging */
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016-2019
|
* Copyright (C) Miroslav Lichvar 2016-2019, 2021-2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2019
|
* Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014, 2016-2019, 2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Richard P. Curnow 1997-2003
|
* Copyright (C) Richard P. Curnow 1997-2003
|
||||||
* Copyright (C) Miroslav Lichvar 2009-2018, 2020
|
* Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ typedef struct {
|
|||||||
uint32_t total_tx_count;
|
uint32_t total_tx_count;
|
||||||
uint32_t total_rx_count;
|
uint32_t total_rx_count;
|
||||||
uint32_t total_valid_count;
|
uint32_t total_valid_count;
|
||||||
|
uint32_t total_good_count;
|
||||||
} RPT_NTPReport;
|
} RPT_NTPReport;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ RX timestamping : Kernel
|
|||||||
Total TX : 1
|
Total TX : 1
|
||||||
Total RX : 1
|
Total RX : 1
|
||||||
Total valid RX : 1
|
Total valid RX : 1
|
||||||
|
Total good RX : 0
|
||||||
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||||
=======================================================================
|
=======================================================================
|
||||||
M node1\.net1\.clk N ----- ----- 0 1\.0 \+0ns \+0ns N
|
M node1\.net1\.clk N ----- ----- 0 1\.0 \+0ns \+0ns N
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ TX timestamping : (Daemon|Kernel)
|
|||||||
RX timestamping : (Daemon|Kernel)
|
RX timestamping : (Daemon|Kernel)
|
||||||
Total TX : [0-9]+
|
Total TX : [0-9]+
|
||||||
Total RX : [0-9]+
|
Total RX : [0-9]+
|
||||||
Total valid RX : [0-9]+$" || test_fail
|
Total valid RX : [0-9]+
|
||||||
|
Total good RX : [0-9]+$" || test_fail
|
||||||
|
|
||||||
run_chronyc "selectdata" || test_fail
|
run_chronyc "selectdata" || test_fail
|
||||||
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016-2018
|
* Copyright (C) Miroslav Lichvar 2016-2018, 2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* Copyright (C) Miroslav Lichvar 2016, 2018
|
* Copyright (C) Miroslav Lichvar 2016, 2018, 2022
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of version 2 of the GNU General Public License as
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
|||||||
Reference in New Issue
Block a user