diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/FAQ b/FAQ new file mode 100644 index 0000000..7c43481 --- /dev/null +++ b/FAQ @@ -0,0 +1,1217 @@ +Frequently Asked Questions + +Table of Contents + + o 1. chrony compared to other programs + ? 1.1. How does chrony compare to ntpd? + ? 1.2. Should I prefer chrony over timesyncd if I do not need to run a + server? + o 2. Configuration issues + ? 2.1. What is the minimum recommended configuration for an NTP client? + ? 2.2. How do I make an NTP server? + ? 2.3. Should all computers on a LAN be clients of an external server? + ? 2.4. Must I specify servers by IP address if DNS is not available on + chronyd start? + ? 2.5. How can I make chronyd more secure? + ? 2.6. How can I make the system clock more secure? + ? 2.7. How can I improve the accuracy of the system clock with NTP + sources? + ? 2.8. Does chronyd have an ntpdate mode? + ? 2.9. Can chronyd be configured to control the clock like ntpd? + ? 2.10. Can NTP server be separated from NTP client? + ? 2.11. How can chronyd be configured to minimise downtime during + restarts? + ? 2.12. Should be a leap smear enabled on NTP server? + ? 2.13. How should chronyd be configured with gpsd? + ? 2.14. Does chrony support PTP? + ? 2.15. How can I avoid using wrong PHC refclock? + ? 2.16. Why are client log records dropped before reaching + clientloglimit? + ? 2.17. What happened to the commandkey and generatecommandkey + directives? + o 3. Computer is not synchronising + ? 3.1. Behind a firewall? + ? 3.2. Are NTP servers specified with the offline option? + ? 3.3. Is name resolution working correctly? + ? 3.4. Is chronyd allowed to step the system clock? + ? 3.5. Using NTS? + ? 3.6. Using a Windows NTP server? + ? 3.7. An unreachable source is selected? + ? 3.8. Does selected source drop new measurements? + ? 3.9. Using a PPS reference clock? + o 4. Issues with chronyc + ? 4.1. I keep getting the error 506 Cannot talk to daemon + ? 4.2. I keep getting the error 501 Not authorised + ? 4.3. What is the reference ID reported by the tracking command? + ? 4.4. Is the chronyc / chronyd protocol documented anywhere? + o 5. Real-time clock issues + ? 5.1. What is the real-time clock (RTC)? + ? 5.2. Does hwclock have to be disabled? + ? 5.3. I just keep getting the 513 RTC driver not running message + ? 5.4. I get Could not open /dev/rtc, Device or resource busy in my + syslog file + ? 5.5. When I start chronyd, the log says Could not enable RTC interrupt + : Invalid argument (or it may say disable) + ? 5.6. What if my computer does not have an RTC or backup battery? + o 6. NTP-specific issues + ? 6.1. Can chronyd be driven from broadcast/multicast NTP servers? + ? 6.2. Can chronyd transmit broadcast NTP packets? + ? 6.3. Can chronyd keep the system clock a fixed offset away from real + time? + ? 6.4. What happens if the network connection is dropped without using + chronyc's offline command first? + ? 6.5. Why is an offset measured between two computers synchronised to + each another? + o 7. Operation + ? 7.1. What clocks does chronyd use? + ? 7.2. How accurate is my system clock? + o 8. Operating systems + ? 8.1. Does chrony support Windows? + ? 8.2. Are there any plans to support Windows? + +1. chrony compared to other programs + +1.1. How does chrony compare to ntpd? + +chrony and ntpd are two different implementations of the Network Time Protocol +(NTP). + +chrony is a newer implementation, which was designed to work well in a wider +range of conditions. It can usually synchronise the system clock faster and +with better time accuracy. It has many features, but it does not implement some +of the less useful NTP modes like broadcast client or multicast server/client. + +If your computer is connected to the Internet only for few minutes at a time, +the network connection is often congested, you turn your computer off or +suspend it frequently, the clock is not very stable (e.g. there are rapid +changes in the temperature or it is a virtual machine), or you want to use NTP +on an isolated network with no hardware reference clocks in sight, chrony will +probably work better for you. + +For a more detailed comparison of features and performance, see the comparison +page on the chrony website. + +1.2. Should I prefer chrony over timesyncd if I do not need to run a server? + +Generally, yes. + +systemd-timesyncd is a very simple NTP client included in the systemd suite. It +lacks almost all features of chrony and other advanced client implementations +listed on the comparison page. One of its main limitations is that it cannot +poll multiple servers at the same time and detect servers having incorrect time +(falsetickers in the NTP terminology). It should be used only with trusted +reliable servers, ideally in local network. + +Using timesyncd with pool.ntp.org is problematic. The pool is very robust as a +whole, but the individual servers run by volunteers cannot be relied on. +Occasionally, servers drift away or make a step to distant past or future due +to misconfiguration, problematic implementation, and other bugs (e.g. in +firmware of a GPS receiver). The pool monitoring system detects such servers +and quickly removes them from the pool DNS, but clients like timesyncd cannot +recover from that. They follow the server as long as it claims to be +synchronised. They need to be restarted in order to get a new address from the +pool DNS. + +Note that the complexity of NTP and clock synchronisation is on the client +side. The amount of code in chrony specific to NTP server is very small and it +is disabled by default. If it was removed, it would not significantly reduce +the amount of memory or storage needed. + +2. Configuration issues + +2.1. What is the minimum recommended configuration for an NTP client? + +First, the client needs to know which NTP servers it should ask for the current +time. They are specified by the server or pool directive. The pool directive is +used with names that resolve to multiple addresses of different servers. For +reliable operation, the client should have at least three servers. + +The iburst option enables a burst of requests to speed up the initial +synchronisation. + +To stabilise the initial synchronisation on the next start, the estimated drift +of the system clock is saved to a file specified by the driftfile directive. + +If the system clock can be far from the true time after boot for any reason, +chronyd should be allowed to correct it quickly by stepping instead of slewing, +which would take a very long time. The makestep directive does that. + +In order to keep the real-time clock (RTC) close to the true time, so the +system time is reasonably close to the true time when it is initialised on the +next boot from the RTC, the rtcsync directive enables a mode in which the +system time is periodically copied to the RTC. It is supported on Linux and +macOS. + +If you wanted to use public NTP servers from the pool.ntp.org project, the +minimal chrony.conf file could be: + +pool pool.ntp.org iburst +driftfile /var/lib/chrony/drift +makestep 1 3 +rtcsync + +2.2. How do I make an NTP server? + +By default, chronyd does not operate as an NTP server. You need to add an allow +directive to the chrony.conf file in order for chronyd to open the server NTP +port and respond to client requests. + +allow 192.168.1.0/24 + +An allow directive with no specified subnet allows access from all IPv4 and +IPv6 addresses. + +2.3. Should all computers on a LAN be clients of an external server? + +It depends on the requirements. Usually, the best configuration is to make one +computer the server, with the others as clients of it. Add a local directive to +the server's chrony.conf file. This configuration will be better because + + o the load on the external connection is less + + o the load on the external NTP server(s) is less + + o if your external connection goes down, the computers on the LAN will + maintain a common time with each other. + +2.4. Must I specify servers by IP address if DNS is not available on chronyd +start? + +No, chronyd will keep trying to resolve the names specified by the server, +pool, and peer directives in an increasing interval until it succeeds. The +online command can be issued from chronyc to force chronyd to try to resolve +the names immediately. + +2.5. How can I make chronyd more secure? + +If you do not need to use chronyc, or you want to run chronyc only under the +root or chrony user (which can access chronyd through a Unix domain socket), +you can disable the IPv4 and IPv6 command sockets (by default listening on +localhost) by adding cmdport 0 to the configuration file. + +You can specify an unprivileged user with the -u option, or the user directive +in the chrony.conf file, to which chronyd will switch after start in order to +drop root privileges. The configure script has a --with-user option, which sets +the default user. On Linux, chronyd needs to be compiled with support for the +libcap library. On other systems, chronyd forks into two processes. The child +process retains root privileges, but can only perform a very limited range of +privileged system calls on behalf of the parent. + +Also, if chronyd is compiled with support for the Linux secure computing +(seccomp) facility, you can enable a system call filter with the -F option. It +will significantly reduce the kernel attack surface and possibly prevent kernel +exploits from the chronyd process if it is compromised. It is recommended to +enable the filter only when it is known to work on the version of the system +where chrony is installed as the filter needs to allow also system calls made +from libraries that chronyd is using (e.g. libc) and different versions or +implementations of the libraries might make different system calls. If the +filter is missing some system call, chronyd could be killed even in normal +operation. + +2.6. How can I make the system clock more secure? + +An NTP client synchronising the system clock to an NTP server is susceptible to +various attacks, which can break applications and network protocols relying on +accuracy of the clock (e.g. DNSSEC, Kerberos, TLS, WireGuard). + +Generally, a man-in-the-middle (MITM) attacker between the client and server +can + + o make fake responses, or modify real responses from the server, to create an + arbitrarily large time and frequency offset, make the server appear more + accurate, insert a leap second, etc. + + o delay the requests and/or responses to create a limited time offset and + temporarily also a limited frequency offset + + o drop the requests or responses to prevent updates of the clock with new + measurements + + o redirect the requests to a different server + +The attacks can be combined for a greater effect. The attacker can delay +packets to create a significant frequency offset first and then drop all +subsequent packets to let the clock quickly drift away from the true time. The +attacker might also be able to control the server's clock. + +Some attacks cannot be prevented. Monitoring is needed for detection, e.g. the +reachability register in the sources report shows missing packets. The extent +to which the attacker can control the client's clock depends on its +configuration. + +Enable authentication to prevent chronyd from accepting modified, fake, or +redirected packets. It can be enabled with a symmetric key specified by the key +option, or Network Time Security (NTS) by the nts option (supported since +chrony version 4.0). The server needs to support the selected authentication +mechanism. Symmetric keys have to be configured on both client and server, and +each client must have its own key (one per server). + +The maximum offset that the attacker can insert in an NTP measurement by +delaying packets can be limited by the maxdelay option. The default value is 3 +seconds. The measured delay is reported as the peer delay in the ntpdata report +and measurements log. Set the maxdelay option to a value larger than the +maximum value that is normally observed. Note that the delay can increase +significantly even when not under an attack, e.g. when the network is congested +or the routing has changed. + +The maximum accepted change in time offset between clock updates can be limited +by the maxchange directive. Larger changes in the offset will be ignored or +cause chronyd to exit. Note that the attacker can get around this limit by +splitting the offset into multiple smaller offsets and/or creating a large +frequency offset. When this directive is used, chronyd will have to be +restarted after a successful attack. It will not be able to recover on its own. +It must not be restarted automatically (e.g. by the service manager). + +The impact of a large accepted time offset can be reduced by disabling clock +steps, i.e. by not using the makestep and initstepslew directives. The offset +will be slowly corrected by speeding up or slowing down the clock at a rate +which can be limited by the maxslewrate directive. Disabling clock steps +completely is practical only if the clock cannot gain a larger error on its +own, e.g. when the computer is shut down or suspended, and the maxslewrate +limit is large enough to correct an expected error in an acceptable time. The +rtcfile directive with the -s option can be used to compensate for the RTC +drift. + +A more practical approach is to enable makestep for a limited number of clock +updates (the 2nd argument of the directive) and limit the offset change in all +updates by the maxchange directive. The attacker will be able to make only a +limited step and only if the attack starts in a short window after booting the +computer, or when chronyd is restarted without the -R option. + +The frequency offset can be limited by the maxdrift directive. The measured +frequency offset is reported in the drift file, tracking report, and tracking +log. Set maxdrift to a value larger than the maximum absolute value that is +normally observed. Note that the frequency of the clock can change due to aging +of the crystal, differences in calibration of the clock source between reboots, +migrated virtual machine, etc. A typical computer clock has a drift smaller +than 100 parts per million (ppm), but much larger drifts are possible (e.g. in +some virtual machines). + +Use only trusted servers, which you expect to be well configured and managed, +using authentication for their own servers, etc. Use multiple servers, ideally +in different locations. The attacker will have to deal with a majority of the +servers in order to pass the source selection and update the clock with a large +offset. Use the minsources directive to increase the required number of +selectable sources to make the selection more robust. + +Do not specify servers as peers. The symmetric mode is less secure than the +client/server mode. If not authenticated, it is vulnerable to off-path +denial-of-service attacks, and even when it is authenticated, it is still +susceptible to replay attacks. + +Mixing of authenticated and unauthenticated servers should generally be +avoided. If mixing is necessary (e.g. for a more accurate and stable +synchronisation to a closer server which does not support authentication), the +authenticated servers should be configured as trusted and required to not allow +the unauthenticated servers to override the authenticated servers in the source +selection. Since chrony version 4.0, the selection options are enabled in such +a case automatically. This behaviour can be disabled or modified by the +authselectmode directive. + +An example of a client configuration limiting the impact of the attacks could +be + +server ntp1.example.net iburst nts maxdelay 0.1 +server ntp2.example.net iburst nts maxdelay 0.2 +server ntp3.example.net iburst nts maxdelay 0.05 +server ntp4.example.net iburst nts maxdelay 0.1 +server ntp5.example.net iburst nts maxdelay 0.1 +minsources 3 +maxchange 100 0 0 +makestep 0.001 1 +maxdrift 100 +maxslewrate 100 +driftfile /var/lib/chrony/drift +ntsdumpdir /var/lib/chrony +rtcsync + +2.7. How can I improve the accuracy of the system clock with NTP sources? + +Select NTP servers that are well synchronised, stable and close to your +network. It is better to use more than one server. Three or four is usually +recommended as the minimum, so chronyd can detect servers that serve false time +and combine measurements from multiple sources. + +If you have a network card with hardware timestamping supported on Linux, it +can be enabled by the hwtimestamp directive. It should make local receive and +transmit timestamps of NTP packets much more stable and accurate. + +The server directive has some useful options: minpoll, maxpoll, polltarget, +maxdelay, maxdelayratio, maxdelaydevratio, xleave, filter. + +The first three options set the minimum and maximum allowed polling interval, +and how should be the actual interval adjusted in the specified range. Their +default values are 6 (64 seconds) for minpoll, 10 (1024 seconds) for maxpoll +and 8 (samples) for polltarget. The default values should be used for general +servers on the Internet. With your own NTP servers, or if you have permission +to poll some servers more frequently, setting these options for shorter polling +intervals might significantly improve the accuracy of the system clock. + +The optimal polling interval depends mainly on two factors, stability of the +network latency and stability of the system clock (which mainly depends on the +temperature sensitivity of the crystal oscillator and the maximum rate of the +temperature change). + +Generally, if the sourcestats command usually reports a small number of samples +retained for a source (e.g. fewer than 16), a shorter polling interval should +be considered. If the number of samples is usually at the maximum of 64, a +longer polling interval might work better. + +An example of the directive for an NTP server on the Internet that you are +allowed to poll frequently could be + +server ntp.example.net minpoll 4 maxpoll 6 polltarget 16 + +An example using shorter polling intervals with a server located in the same +LAN could be + +server ntp.local minpoll 2 maxpoll 4 polltarget 30 + +The maxdelay options are useful to ignore measurements with an unusually large +delay (e.g. due to congestion in the network) and improve the stability of the +synchronisation. The maxdelaydevratio option could be added to the example with +local NTP server + +server ntp.local minpoll 2 maxpoll 4 polltarget 30 maxdelaydevratio 2 + +If your server supports the interleaved mode (e.g. it is running chronyd), the +xleave option should be added to the server directive to enable the server to +provide the client with more accurate transmit timestamps (kernel or preferably +hardware). For example: + +server ntp.local minpoll 2 maxpoll 4 xleave + +When combined with local hardware timestamping, good network switches, and even +shorter polling intervals, a sub-microsecond accuracy and stability of a few +tens of nanoseconds might be possible. For example: + +server ntp.local minpoll 0 maxpoll 0 xleave +hwtimestamp eth0 + +For best stability, the CPU should be running at a constant frequency (i.e. +disabled power saving and performance boosting). Energy-Efficient Ethernet +(EEE) should be disabled in the network. The switches should be configured to +prioritize NTP packets, especially if the network is expected to be heavily +loaded. The dscp directive can be used to set the Differentiated Services Code +Point in transmitted NTP packets if needed. + +If it is acceptable for NTP clients in the network to send requests at a high +rate, a sub-second polling interval can be specified. A median filter can be +enabled in order to update the clock at a reduced rate with more stable +measurements. For example: + +server ntp.local minpoll -6 maxpoll -6 filter 15 xleave +hwtimestamp eth0 minpoll -6 + +Since chrony version 4.3, the minimum minpoll is -7 and a filter using a +long-term estimate of a delay quantile can be enabled by the maxdelayquant +option to replace the default maxdelaydevratio filter, which is sensitive to +outliers corrupting the minimum delay. For example: + +server ntp.local minpoll -7 maxpoll -7 filter 31 maxdelayquant 0.3 xleave + +Since version 4.2, chronyd supports an NTPv4 extension field containing an +additional timestamp to enable frequency transfer and significantly improve +stability of synchronisation. It can be enabled by the extfield F323 option. +For example: + +server ntp.local minpoll 0 maxpoll 0 xleave extfield F323 + +Since version 4.5, chronyd can apply corrections from PTP one-step end-to-end +transparent clocks (e.g. network switches) to significantly improve accuracy of +synchronisation in local networks. It requires the PTP transport to be enabled +by the ptpport directive, HW timestamping, and the extfield F324 option. For +example: + +server ntp.local minpoll -4 maxpoll -4 xleave extfield F323 extfield F324 port 319 +ptpport 319 +hwtimestamp eth0 minpoll -4 + +2.8. Does chronyd have an ntpdate mode? + +Yes. With the -q option chronyd will set the system clock once and exit. With +the -Q option it will print the measured offset without setting the clock. If +you do not want to use a configuration file, NTP servers can be specified on +the command line. For example: + +# chronyd -q 'pool pool.ntp.org iburst' + +The command above would normally take about 5 seconds if the servers were well +synchronised and responding to all requests. If not synchronised or responding, +it would take about 10 seconds for chronyd to give up and exit with a non-zero +status. A faster configuration is possible. A single server can be used instead +of four servers, the number of measurements can be reduced with the maxsamples +option to one (supported since chrony version 4.0), and a timeout can be +specified with the -t option. The following command would take only up to about +one second. + +# chronyd -q -t 1 'server pool.ntp.org iburst maxsamples 1' + +It is not recommended to run chronyd with the -q option periodically (e.g. from +a cron job) as a replacement for the daemon mode, because it performs +significantly worse (e.g. the clock is stepped and its frequency is not +corrected). If you must run it this way and you are using a public NTP server, +make sure chronyd does not always start around the first second of a minute, +e.g. by adding a random sleep before the chronyd command. Public servers +typically receive large bursts of requests around the first second as there is +a large number of NTP clients started from cron with no delay. + +2.9. Can chronyd be configured to control the clock like ntpd? + +It is not possible to perfectly emulate ntpd, but there are some options that +can configure chronyd to behave more like ntpd if there is a reason to prefer +that. + +In the following example the minsamples directive slows down the response to +changes in the frequency and offset of the clock. The maxslewrate and +corrtimeratio directives reduce the maximum frequency error due to an offset +correction and the maxdrift directive reduces the maximum assumed frequency +error of the clock. The makestep directive enables a step threshold and the +maxchange directive enables a panic threshold. The maxclockerror directive +increases the minimum dispersion rate. + +minsamples 32 +maxslewrate 500 +corrtimeratio 100 +maxdrift 500 +makestep 0.128 -1 +maxchange 1000 1 1 +maxclockerror 15 + +Note that increasing minsamples might cause the offsets in the tracking and +sourcestats reports/logs to be significantly smaller than the actual offsets +and be unsuitable for monitoring. + +2.10. Can NTP server be separated from NTP client? + +Yes, it is possible to run multiple instances of chronyd on a computer at the +same time. One can operate primarily as an NTP client to synchronise the system +clock and another as a server for other computers. If they use the same +filesystem, they need to be configured with different pidfiles, Unix domain +command sockets, and any other file or directory specified in the configuration +file. If they run in the same network namespace, they need to use different NTP +and command ports, or bind the ports to different addresses or interfaces. + +The server instance should be started with the -x option to prevent it from +adjusting the system clock and interfering with the client instance. It can be +configured as a client to synchronise its NTP clock to other servers, or the +client instance running on the same computer. In the latter case, the copy +option (added in chrony version 4.1) can be used to assume the reference ID and +stratum of the client instance, which enables detection of synchronisation +loops with its own clients. + +On Linux, starting with chrony version 4.0, it is possible to run multiple +server instances sharing a port to better utilise multiple cores of the CPU. +Note that for rate limiting and client/server interleaved mode to work well it +is necessary that all packets received from the same address are handled by the +same server instance. + +An example configuration of the client instance could be + +pool pool.ntp.org iburst +allow 127.0.0.1 +port 11123 +driftfile /var/lib/chrony/drift +makestep 1 3 +rtcsync + +and configuration of the first server instance could be + +server 127.0.0.1 port 11123 minpoll 0 maxpoll 0 copy +allow +cmdport 11323 +bindcmdaddress /var/run/chrony/chronyd-server1.sock +pidfile /var/run/chronyd-server1.pid +driftfile /var/lib/chrony/drift-server1 + +2.11. How can chronyd be configured to minimise downtime during restarts? + +The dumpdir directive in chrony.conf provides chronyd a location to save a +measurement history of the sources it uses when the service exits. The -r +option then enables chronyd to load state from the dump files, reducing the +synchronisation time after a restart. + +Similarly, the ntsdumpdir directive provides a location for chronyd to save NTS +cookies received from the server to avoid making a NTS-KE request when chronyd +is started. When operating as an NTS server, chronyd also saves cookies keys to +this directory to allow clients to continue to use the old keys after a server +restart for a more seamless experience. + +On Linux systems, systemd socket activation provides a mechanism to reuse +server sockets across chronyd restarts, so that client requests will be +buffered until the service is again able to handle the requests. This allows +for zero-downtime service restarts, simplified dependency logic at boot, and +on-demand service spawning (for instance, for separated server chronyd +instances run with the -x flag). + +Socket activation is supported since chrony version 4.5. The service manager +(systemd) creates sockets and passes file descriptors to them to the process +via the LISTEN_FDS environment variable. Before opening new sockets, chronyd +first checks for and attempts to reuse matching sockets passed from the service +manager. For instance, if an IPv4 datagram socket bound on bindaddress and port +is available, it will be used by the NTP server to accept incoming IPv4 +requests. + +An example systemd socket unit is below, where chronyd is configured with +bindaddress 0.0.0.0, bindaddress ::, port 123, and ntsport 4460. + +[Unit] +Description=chronyd server sockets + +[Socket] +Service=chronyd.service +# IPv4 NTP server +ListenDatagram=0.0.0.0:123 +# IPv6 NTP server +ListenDatagram=[::]:123 +# IPv4 NTS-KE server +ListenStream=0.0.0.0:4460 +# IPv6 NTS-KE server +ListenStream=[::]:4460 +BindIPv6Only=ipv6-only + +[Install] +WantedBy=sockets.target + +2.12. Should be a leap smear enabled on NTP server? + +With the smoothtime and leapsecmode directives it is possible to enable a +server leap smear in order to hide leap seconds from clients and force them to +follow a slow server's adjustment instead. + +This feature should be used only in local networks and only when necessary, +e.g. when the clients cannot be configured to handle the leap seconds as +needed, or their number is so large that configuring them all would be +impractical. The clients should use only one leap-smearing server, or multiple +identically configured leap-smearing servers. Note that some clients can get +leap seconds from other sources (e.g. with the leapsectz directive in chrony) +and they will not work correctly with a leap smearing server. + +2.13. How should chronyd be configured with gpsd? + +A GPS or other GNSS receiver can be used as a reference clock with gpsd. It can +work as one or two separate time sources for each connected receiver. The first +time source is based on timestamping of messages sent by the receiver. +Typically, it is accurate to milliseconds. The other source is much more +accurate. It is timestamping a pulse-per-second (PPS) signal, usually connected +to a serial port (e.g. DCD pin) or GPIO pin. + +If the PPS signal is connected to the serial port which is receiving messages +from the GPS/GNSS receiver, gpsd should detect and use it automatically. If it +is connected to a GPIO pin, or another serial port, the PPS device needs to be +specified on the command line as an additional data source. On Linux, the +ldattach utility can be used to create a PPS device for a serial device. + +The PPS-based time source provided by gpsd is available as a SHM 1 refclock, or +other odd number if gpsd is configured with multiple receivers, and also as +SOCK /var/run/chrony.DEV.sock where DEV is the name of the serial device (e.g. +ttyS0). + +The message-based time source is available as a SHM 0 refclock (or other even +number) and since gpsd version 3.25 also as SOCK /var/run/chrony.clk.DEV.sock +where DEV is the name of the serial device. + +The SOCK refclocks should be preferred over SHM for better security (the shared +memory segment needs to be created by chronyd or gpsd with an expected owner +and permissions before an untrusted application or user has a chance to create +its own in order to feed chronyd with false measurements). gpsd needs to be +started after chronyd in order to connect to the socket. + +With chronyd and gpsd both supporting PPS, there are two different recommended +configurations: + +# First option +refclock SOCK /var/run/chrony.ttyS0.sock refid GPS + +# Second option +refclock PPS /dev/pps0 lock NMEA refid GPS +refclock SOCK /var/run/chrony.clk.ttyS0.sock offset 0.5 delay 0.1 refid NMEA noselect + +They both have some advantages: + + o SOCK can be more accurate than PPS if gpsd corrects for the sawtooth error + provided by the receiver in serial data + + o PPS can be used with higher PPS rates (specified by the rate option), but + it requires a second refclock or another time source to pair pulses with + seconds, and the SOCK offset needs to be specified correctly to compensate + for the message delay, while gpsd can apply HW-specific information + +If the PPS signal is not available, or cannot be used for some reason, the only +option is the message-based timing + +refclock SOCK /var/run/chrony.clk.ttyS0.sock offset 0.5 delay 0.1 refid GPS + +or the SHM equivalent if using gpsd version before 3.25 + +refclock SHM 0 offset 0.5 delay 0.1 refid GPS + +2.14. Does chrony support PTP? + +No, the Precision Time Protocol (PTP) is not supported as a protocol for +synchronisation of clocks and there are no plans to support it. It is a complex +protocol, which shares some issues with the NTP broadcast mode. One of the main +differences between NTP and PTP is that PTP was designed to be easily supported +in hardware (e.g. network switches and routers) in order to make more stable +and accurate measurements. PTP relies on the hardware support. NTP does not +rely on any support in the hardware, but if it had the same support as PTP, it +could perform equally well. + +On Linux, chrony supports hardware clocks that some NICs have for PTP. They are +called PTP hardware clocks (PHC). They can be used as reference clocks +(specified by the refclock directive) and for hardware timestamping of NTP +packets (enabled by the hwtimestamp directive) if the NIC can timestamp other +packets than PTP, which is usually the case at least for transmitted packets. +The ethtool -T command can be used to verify the timestamping support. + +As an experimental feature added in version 4.2, chrony can use PTP as a +transport for NTP messages (NTP over PTP) to enable hardware timestamping on +hardware which can timestamp PTP packets only. It can be enabled by the ptpport +directive. Since version 4.5, chrony can also apply corrections provided by PTP +one-step end-to-end transparent clocks to reach the accuracy of ordinary PTP +clocks. The application of PTP corrections can be enabled by the extfield F324 +option. + +2.15. How can I avoid using wrong PHC refclock? + +If your system has multiple PHC devices, normally named by udev as /dev/ptp0, / +dev/ptp1, and so on, their order can change randomly across reboots depending +on the order of initialisation of their drivers. If a PHC refclock is specified +by this name, chronyd could be using a wrong refclock after reboot. To prevent +that, you can configure udev to create a stable symlink for chronyd with a rule +like this (e.g. written to /etc/udev/rules.d/80-phc.rules): + +KERNEL=="ptp[0-9]*", DEVPATH=="/devices/pci0000:00/0000:00:01.2/0000:02:00.0/ptp/*", SYMLINK+="ptp-i350-1" + +You can get the full DEVPATH of an existing PHC device with the udevadm info +command. You will need to execute the udevadm trigger command, or reboot the +system, for these changes to take effect. + +2.16. Why are client log records dropped before reaching clientloglimit? + +The number of dropped client log records reported by the serverstats command +can be increasing before the number of clients reported by the clients command +reaches the maximum value corresponding to the memory limit set by the +clientloglimit directive. + +This is due to the design of the data structure keeping the client records. It +is a hash table which can store only up to 16 colliding addresses per slot. If +a slot has more collisions and the table already has the maximum size, the +oldest record will be dropped and replaced by the new client. + +Note that the size of the table is always a power of two and it can only grow. +The limit set by the clientloglimit directive takes into account that two +copies of the table exist when it is being resized. This means the actual +memory usage reported by top and other utilities can be significantly smaller +than the limit even when the maximum number of records is used. + +The absolute maximum number of client records kept at the same time is +16777216. + +2.17. What happened to the commandkey and generatecommandkey directives? + +They were removed in version 2.2. Authentication is no longer supported in the +command protocol. Commands that required authentication are now allowed only +through a Unix domain socket, which is accessible only by the root and chrony +users. If you need to configure chronyd remotely or locally without the root +password, please consider using ssh and/or sudo to run chronyc under the root +or chrony user on the host where chronyd is running. + +3. Computer is not synchronising + +This is the most common problem. There are a number of reasons, see the +following questions. + +3.1. Behind a firewall? + +Check the Reach value printed by the chronyc's sources command. If it is zero, +it means chronyd did not get any valid responses from the NTP server you are +trying to use. If there is a firewall between you and the server, the requests +sent to the UDP port 123 of the server or responses sent back from the port +might be blocked. Try using a tool like wireshark or tcpdump to see if you are +getting any responses from the server. + +When chronyd is receiving responses from the servers, the output of the sources +command issued few minutes after chronyd start might look like this: + +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +^* ntp1.example.net 2 6 377 34 +484us[ -157us] +/- 30ms +^- ntp2.example.net 2 6 377 34 +33ms[ +32ms] +/- 47ms +^+ ntp3.example.net 3 6 377 35 -1397us[-2033us] +/- 60ms + +3.2. Are NTP servers specified with the offline option? + +Check that the chronyc's online and offline commands are used appropriately +(e.g. in the system networking scripts). The activity command prints the number +of sources that are currently online and offline. For example: + +200 OK +3 sources online +0 sources offline +0 sources doing burst (return to online) +0 sources doing burst (return to offline) +0 sources with unknown address + +3.3. Is name resolution working correctly? + +NTP servers specified by their hostname (instead of an IP address) have to have +their names resolved before chronyd can send any requests to them. If the +activity command prints a non-zero number of sources with unknown address, +there is an issue with the resolution. Typically, a DNS server is specified in +/etc/resolv.conf. Make sure it is working correctly. + +Since chrony version 4.0, you can run chronyc -N sources -a command to print +all sources, even those that do not have a known address yet, with their names +as they were specified in the configuration. This can be useful to verify that +the names specified in the configuration are used as expected. + +When DNSSEC is enabled, it will not work until the time is synchronized, as it +requires validating a signature timestamp and its expiration date, so if the +system time is too far in the future or the past DNSSEC validation will fail +and chronyd will be unable to resolve the address of the NTP server. In such +cases, if hostnames are the only options and bare IP addresses cannot be used, +DNSSEC can be disabled for chronyd using resolver-specific mechanisms, if +available, although of course that means losing the protection afforded by +DNSSEC. For example, when using systemd-resolved, the +SYSTEMD_NSS_RESOLVE_VALIDATE=0 environment variable can be set, for example in +the chronyd systemd unit via Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0. + +3.4. Is chronyd allowed to step the system clock? + +By default, chronyd adjusts the clock gradually by slowing it down or speeding +it up. If the clock is too far from the true time, it will take a long time to +correct the error. The System time value printed by the chronyc's tracking +command is the remaining correction that needs to be applied to the system +clock. + +The makestep directive can be used to allow chronyd to step the clock. For +example, if chrony.conf had + +makestep 1 3 + +the clock would be stepped in the first three updates if its offset was larger +than one second. Normally, it is recommended to allow the step only in the +first few updates, but in some cases (e.g. a computer without an RTC or virtual +machine which can be suspended and resumed with an incorrect time) it might be +necessary to allow the step on any clock update. The example above would change +to + +makestep 1 -1 + +3.5. Using NTS? + +The Network Time Security (NTS) mechanism uses Transport Layer Security (TLS) +to establish the keys needed for authentication of NTP packets. + +Run the authdata command to check whether the key establishment was successful: + +# chronyc -N authdata +Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen +========================================================================= +ntp1.example.net NTS 1 15 256 33m 0 0 8 100 +ntp2.example.net NTS 1 15 256 33m 0 0 8 100 +ntp3.example.net NTS 1 15 256 33m 0 0 8 100 + +The KeyID, Type, and KLen columns should have non-zero values. If they are +zero, check the system log for error messages from chronyd. One possible cause +of failure is a firewall blocking the client's connection to the server's TCP +port 4460. + +Another possible cause of failure is a certificate that is failing to verify +because the client's clock is wrong. This is a chicken-and-egg problem with +NTS. You might need to manually correct the date, or temporarily disable NTS, +in order to get NTS working. If your computer has an RTC and it is backed up by +a good battery, this operation should be needed only once, assuming the RTC +will be set periodically with the rtcsync directive, or compensated with the +rtcfile directive and the -s option. + +If the computer does not have an RTC or battery, you can use the -s option +without rtcfile directive to restore time of the last shutdown or reboot from +the drift file. The clock will start behind the true time, but if the computer +was not shut down for too long and the server's certificate was not renewed too +close to its expiration, it should be sufficient for the time checks to +succeed. + +If you run your own server, you can use a self-signed certificate covering all +dates where the client can start (e.g. years 1970-2100). The certificate needs +to be installed on the client and specified with the ntstrustedcerts directive. +The server can have multiple names and certificates. To avoid trusting a +certificate for too long, a new certificate can be added to the server +periodically (e.g. once per year) and the client can have the server name and +trusted certificate updated automatically (e.g. using a package repository, or +a cron script downloading the files directly from the server over HTTPS). A +client that was shut down for years will still be able to synchronise its clock +and perform the update as long as the server keeps the old certificate. + +As a last resort, you can disable the time checks by the nocerttimecheck +directive. This has some important security implications. To reduce the +security risk, you can use the nosystemcert and ntstrustedcerts directives to +disable the system's default trusted certificate authorities and trust only a +minimal set of selected authorities needed to validate the certificates of used +NTP servers. + +3.6. Using a Windows NTP server? + +A common issue with Windows NTP servers is that they report a very large root +dispersion (e.g. three seconds or more), which causes chronyd to ignore the +server for being too inaccurate. The sources command might show a valid +measurement, but the server is not selected for synchronisation. You can check +the root dispersion of the server with the chronyc's ntpdata command. + +The maxdistance value needs to be increased in chrony.conf to enable +synchronisation to such a server. For example: + +maxdistance 16.0 + +3.7. An unreachable source is selected? + +When chronyd is configured with multiple time sources, it tries to select the +most accurate and stable sources for synchronisation of the system clock. They +are marked with the * or + symbol in the report printed by the sources command. + +When the best source (marked with the * symbol) becomes unreachable (e.g. NTP +server stops responding), chronyd will not immediately switch to the second +best source in an attempt to minimise the error of the clock. It will let the +clock run free for as long as its estimated error (in terms of root distance) +based on previous measurements is smaller than the estimated error of the +second source, and there is still an interval which contains some measurements +from both sources. + +If the first source was significantly better than the second source, it can +take many hours before the second source is selected, depending on its polling +interval. You can force a faster reselection by increasing the clock error rate +(maxclockerror directive), shortening the polling interval (maxpoll option), or +reducing the number of samples (maxsamples option). + +3.8. Does selected source drop new measurements? + +chronyd can drop a large number of successive NTP measurements if they are not +passing some of the NTP tests. The sources command can report for a selected +source the fully-reachable value of 377 in the Reach column and at the same +time a LastRx value that is much larger than the current polling interval. If +the source is online, this indicates that a number of measurements was dropped. +You can use the ntpdata command to check the NTP tests for the last +measurement. Usually, it is the test C which fails. + +This can be an issue when there is a long-lasting increase in the measured +delay, e.g. due to a routing change in the network. Unfortunately, chronyd does +not know for how long it should wait for the delay to come back to the original +values, or whether it is a permanent increase and it should start from scratch. + +The test C is an adaptive filter. It can take many hours before it accepts a +measurement with the larger delay, and even much longer before it drops all +measurements with smaller delay, which determine an expected delay used by the +test. You can use the reset sources command to drop all measurements +immediately (available in chrony 4.0 and later). If this issue happens +frequently, you can effectively disable the test by setting the +maxdelaydevratio option to a very large value (e.g. 1000000), or speed up the +recovery by increasing the clock error rate with the maxclockerror directive. + +3.9. Using a PPS reference clock? + +A pulse-per-second (PPS) reference clock requires a non-PPS time source to +determine which second of UTC corresponds to each pulse. If it is another +reference clock specified with the lock option in the refclock directive, the +offset between the two reference clocks must be smaller than 0.4 seconds (0.2 +seconds with chrony versions before 4.1) in order for the PPS reference clock +to work. With NMEA reference clocks it is common to have a larger offset. It +needs to be corrected with the offset option. + +One approach to find out a good value of the offset option is to configure the +reference clocks with the noselect option and compare them to an NTP server. +For example, if the sourcestats command showed + +Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev +============================================================================== +PPS0 0 0 0 +0.000 2000.000 +0ns 4000ms +NMEA 58 30 231 -96.494 38.406 +504ms 6080us +ntp1.example.net 7 3 200 -2.991 16.141 -107us 492us + +the offset of the NMEA source would need to be increased by about 0.504 +seconds. It does not have to be very accurate. As long as the offset of the +NMEA reference clock stays below the limit, the PPS reference clock should be +able to determine the seconds corresponding to the pulses and allow the samples +to be used for synchronisation. + +4. Issues with chronyc + +4.1. I keep getting the error 506 Cannot talk to daemon + +When accessing chronyd remotely, make sure that the chrony.conf file (on the +computer where chronyd is running) has a cmdallow entry for the computer you +are running chronyc on and an appropriate bindcmdaddress directive. This is not +necessary for localhost. + +Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, ps +-auxw) to see if it is running. Or try netstat -a and see if the UDP port 323 +is listening. If chronyd is not running, you might have a problem with the way +you are trying to start it (e.g. at boot time). + +Perhaps you have a firewall set up in a way that blocks packets on the UDP port +323. You need to amend the firewall configuration in this case. + +4.2. I keep getting the error 501 Not authorised + +This error indicates that chronyc sent the command to chronyd using a UDP +socket instead of the Unix domain socket (e.g. /var/run/chrony/chronyd.sock), +which is required for some commands. For security reasons, only the root and +chrony users are allowed to access the socket. + +It is also possible that the socket does not exist. chronyd will not create the +socket if the directory has a wrong owner or permissions. In this case there +should be an error message from chronyd in the system log. + +4.3. What is the reference ID reported by the tracking command? + +The reference ID is a 32-bit value used in NTP to prevent synchronisation +loops. + +In chrony versions before 3.0 it was printed in the quad-dotted notation, even +if the reference source did not actually have an IPv4 address. For IPv4 +addresses, the reference ID is equal to the address, but for IPv6 addresses it +is the first 32 bits of the MD5 sum of the address. For reference clocks, the +reference ID is the value specified with the refid option in the refclock +directive. + +Since version 3.0, the reference ID is printed as a hexadecimal number to avoid +confusion with IPv4 addresses. + +If you need to get the IP address of the current reference source, use the -n +option to disable resolving of IP addresses and read the second field (printed +in parentheses) on the Reference ID line. + +4.4. Is the chronyc / chronyd protocol documented anywhere? + +Only by the source code. See cmdmon.c (chronyd side) and client.c (chronyc +side). + +Note that this protocol is not compatible with the mode 6 or mode 7 protocol +supported by ntpd, i.e. the ntpq or ntpdc utility cannot be used to monitor +chronyd, and chronyc cannot be used to monitor ntpd. + +5. Real-time clock issues + +5.1. What is the real-time clock (RTC)? + +This is the clock which keeps the time even when your computer is turned off. +It is used to initialise the system clock on boot. It normally does not drift +more than few seconds per day. + +There are two approaches how chronyd can work with it. One is to use the +rtcsync directive, which tells chronyd to enable a kernel mode which sets the +RTC from the system clock every 11 minutes. chronyd itself will not touch the +RTC. If the computer is not turned off for a long time, the RTC should still be +close to the true time when the system clock will be initialised from it on the +next boot. + +The other option is to use the rtcfile directive, which tells chronyd to +monitor the rate at which the RTC gains or loses time. When chronyd is started +with the -s option on the next boot, it will set the system time from the RTC +and also compensate for the drift it has measured previously. The rtcautotrim +directive can be used to keep the RTC close to the true time, but it is not +strictly necessary if its only purpose is to set the system clock when chronyd +is started on boot. See the documentation for details. + +5.2. Does hwclock have to be disabled? + +The hwclock program is run by default in the boot and/or shutdown scripts in +some Linux installations. With the kernel RTC synchronisation (rtcsync +directive), the RTC will be set also every 11 minutes as long as the system +clock is synchronised. If you want to use chronyd's RTC monitoring (rtcfile +directive), it is important to disable hwclock in the shutdown procedure. If +you do not do that, it will overwrite the RTC with a new value, unknown to +chronyd. At the next reboot, chronyd started with the -s option will compensate +this (wrong) time with its estimate of how far the RTC has drifted whilst the +power was off, giving a meaningless initial system time. + +There is no need to remove hwclock from the boot process, as long as chronyd is +started after it has run. + +5.3. I just keep getting the 513 RTC driver not running message + +For the real-time clock support to work, you need the following three things + + o an RTC in your computer + + o a Linux kernel with enabled RTC support + + o an rtcfile directive in your chrony.conf file + +5.4. I get Could not open /dev/rtc, Device or resource busy in my syslog file + +Some other program running on the system might be using the device. + +5.5. When I start chronyd, the log says Could not enable RTC interrupt : +Invalid argument (or it may say disable) + +Your real-time clock hardware might not support the required ioctl requests: + + o RTC_UIE_ON + + o RTC_UIE_OFF + +A possible solution could be to build the Linux kernel with support for +software emulation instead; try enabling the following configuration option +when building the Linux kernel: + + o CONFIG_RTC_INTF_DEV_UIE_EMUL + +5.6. What if my computer does not have an RTC or backup battery? + +In this case you can still use the -s option to set the system clock to the +last modification time of the drift file, which should correspond to the system +time when chronyd was previously stopped. The initial system time will be +increasing across reboots and applications started after chronyd will not +observe backward steps. + +6. NTP-specific issues + +6.1. Can chronyd be driven from broadcast/multicast NTP servers? + +No, the broadcast/multicast client mode is not supported and there is currently +no plan to implement it. While this mode can simplify configuration of clients +in large networks, it is inherently less accurate and less secure (even with +authentication) than the ordinary client/server mode. + +When configuring a large number of clients in a network, it is recommended to +use the pool directive with a DNS name which resolves to addresses of multiple +NTP servers. The clients will automatically replace the servers when they +become unreachable, or otherwise unsuitable for synchronisation, with new +servers from the pool. + +Even with very modest hardware, an NTP server can serve time to hundreds of +thousands of clients using the ordinary client/server mode. + +6.2. Can chronyd transmit broadcast NTP packets? + +Yes, the broadcast directive can be used to enable the broadcast server mode to +serve time to clients in the network which support the broadcast client mode +(it is not supported in chronyd). Note that this mode should generally be +avoided. See the previous question. + +6.3. Can chronyd keep the system clock a fixed offset away from real time? + +Yes. Starting from version 3.0, an offset can be specified by the offset option +for all time sources in the chrony.conf file. + +6.4. What happens if the network connection is dropped without using chronyc's +offline command first? + +chronyd will keep trying to access the sources that it thinks are online, and +it will take longer before new measurements are actually made and the clock is +corrected when the network is connected again. If the sources were set to +offline, chronyd would make new measurements immediately after issuing the +online command. + +Unless the network connection lasts only few minutes (less than the maximum +polling interval), the delay is usually not a problem, and it might be +acceptable to keep all sources online all the time. + +6.5. Why is an offset measured between two computers synchronised to each +another? + +When two computers are synchronised to each other using the client/server or +symmetric NTP mode, there is an expectation that NTP measurements between the +two computers made on both ends show an average offset close to zero. + +With chronyd that can be expected only when the interleaved mode is enabled by +the xleave option. Otherwise, chronyd will use different transmit timestamps +(e.g. daemon timestamp vs kernel timestamp) for serving time and +synchronisation of its own clock, which will cause the other computer to +measure a significant offset. + +7. Operation + +7.1. What clocks does chronyd use? + +There are several different clocks used by chronyd: + + o System clock: software clock maintained by the kernel. It is the main clock + used by applications running on the computer. It is synchronised by chronyd + to its NTP clock, unless started with the -x option. + + o NTP clock: software clock (virtual) based on the system clock and internal + to chronyd. It keeps the best estimate of the true time according to the + configured time sources, which is served to NTP clients unless time + smoothing is enabled by the smoothtime directive. The System time value in + the tracking report is the current offset between the system and NTP clock. + + o Real-time clock (RTC): hardware clock keeping time even when the computer + is turned off. It is used by the kernel to initialise the system clock on + boot and also by chronyd to compensate for its measured drift if configured + with the rtcfile directive and started with the -s option. The clock can be + kept accurate only by stepping enabled by the rtcsync or rtcautotrim + directive. + + o Reference clock: hardware clock used as a time source. It is specified by + the refclock directive. + + o NIC clock (also known as PTP hardware clock): hardware clock timestamping + packets received and transmitted by a network device specified by the + hwtimestamp directive. The clock is expected to be running free. It is not + synchronised by chronyd. Its offset is tracked relative to the NTP clock in + order to convert the hardware timestamps. + +7.2. How accurate is my system clock? + +chronyd does not know how accurate really is the clock it is synchronizing. +Even if the measured offset of the clock is stable to nanoseconds, it could be +off by milliseconds due to asymmetric network delay, e.g. caused by asymmetric +routing or queuing delays in network switches. NTP provides root delay and root +dispersion to enable clients to estimate the maximum error of their clock. + +Root delay measures the sum of round-trip times between all NTP servers on the +path from the client to the primary time source (e.g. a GPS receiver). Half of +the root delay is the maximum error due to asymmetric delays, assuming one +direction (e.g. from the client to the server) has a zero delay and the other +direction (from the server to the client) takes all of the measured delay. The +root delay also covers timestamping errors if the server implementation and +hardware meet the NTP requirement for transmit timestamps to never be late and +receive timestamps to never be early. + +If you have additional information about the hardware and network between the +client and primary time source, you could modify the root delay to get a better +estimate of the maximum error. For example, from the physical distance of the +server and signal propagation speed in the cables a minimum symmetric +round-trip delay can be calculated and subtracted from the root delay measured +by NTP. + +Root dispersion estimates errors due to instability of clocks and NTP +measurements. chronyd adjusts the rate at which root dispersion grows between +updates of the clock according to the stability of its NTP measurements. The +minimum rate is set by the the maxclockerror directive. By default it is 1 ppm +(1 microsecond per second). + +The estimated maximum error of the NTP clock is the sum of the root dispersion +and half of the root delay. This value is called root distance. The current +values of root dispersion and delay are included in the tracking report. + +The estimated maximum error of the system clock, which is synchronized to the +NTP clock, is the sum of the root distance and remaining correction of the +system clock provided as System time in the tracking report. A maximum value of +this estimate between updates of the clock is included in the tracking log. + +Note that the resolution of the root delay and root dispersion fields in NTP +messages is about 15 microseconds and chronyd rounds the values up, i.e. the +minimum root distance an NTP client can normally observe is about 22.5 +microseconds. An NTP extension field containing root delay and dispersion in a +better resolution of about 4 nanoseconds can be enabled by the extfield F323 +option. + +8. Operating systems + +8.1. Does chrony support Windows? + +No. The chronyc program (the command-line client used for configuring chronyd +while it is running) has been successfully built and run under Cygwin in the +past. chronyd is not portable, because part of it is very system-dependent. It +needs adapting to work with Windows' equivalent of the adjtimex() call, and it +needs to be made to work as a service. + +8.2. Are there any plans to support Windows? + +We have no plans to do this. Anyone is welcome to pick this work up and +contribute it back to the project. + +Last updated 2024-10-08 14:49:43 +0200 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..000233d --- /dev/null +++ b/INSTALL @@ -0,0 +1,165 @@ +Installation + +The software is distributed as source code which has to be compiled. The source +code is supplied in the form of a gzipped tar file, which unpacks to a +subdirectory identifying the name and version of the program. + +A C compiler (e.g. gcc or clang) and GNU Make are needed to build chrony. The +following libraries with their development files, and programs, are needed to +enable optional features: + + o pkg-config: detection of development libraries + + o Nettle, GnuTLS, NSS, or LibTomCrypt: secure hash functions (SECHASH) + + o libcap: dropping root privileges on Linux (DROPROOT) + + o libseccomp: system call filter on Linux (SCFILTER) + + o GnuTLS and Nettle: Network Time Security (NTS) + + o Editline: line editing in chronyc (READLINE) + + o timepps.h header: PPS reference clock + + o Asciidoctor: documentation in HTML format + + o Bash: test suite + +The following programs are needed when building chrony from the git repository +instead of a released tar file: + + o Asciidoctor: manual pages + + o Bison: parser for chronyc settime command + +After unpacking the source code, change directory into it, and type + +./configure + +This is a shell script that automatically determines the system type. There is +an optional parameter --prefix, which indicates the directory tree where the +software should be installed. For example, + +./configure --prefix=/opt/free + +will install the chronyd daemon into /opt/free/sbin and the chronyc control +program into /opt/free/bin. The default value for the prefix is /usr/local. + +The configure script assumes you want to use gcc as your compiler. If you want +to use a different compiler, you can configure this way: + +CC=cc ./configure --prefix=/opt/free + +for Bourne-family shells, or + +setenv CC cc +setenv CFLAGS -O +./configure --prefix=/opt/free + +for C-family shells. + +If the software cannot (yet) be built on your system, an error message will be +shown. Otherwise, Makefile will be generated. + +On Linux, if development files for the libcap library are available, chronyd +will be built with support for dropping root privileges. On other systems no +extra library is needed. The default user which chronyd should run as can be +specified with the --with-user option of the configure script. + +If development files for the POSIX threads library are available, chronyd will +be built with support for asynchronous resolving of hostnames specified in the +server, peer, and pool directives. This allows chronyd operating as a server to +respond to client requests when resolving a hostname. If you don't want to +enable the support, specify the --disable-asyncdns flag to configure. + +If development files for the Nettle, NSS, or libtomcrypt library are available, +chronyd will be built with support for other cryptographic hash functions than +MD5, which can be used for NTP authentication with a symmetric key. If you +don't want to enable the support, specify the --disable-sechash flag to +configure. + +If development files for the editline library are available, chronyc will be +built with line editing support. If you don't want this, specify the +--disable-readline flag to configure. + +If a timepps.h header is available (e.g. from the LinuxPPS project), chronyd +will be built with PPS API reference clock driver. If the header is installed +in a location that isn't normally searched by the compiler, you can add it to +the searched locations by setting the CPPFLAGS variable to -I/path/to/timepps. + +The --help option can be specified to configure to print all options supported +by the script. + +Now type + +make + +to build the programs. + +If you want to build the manual in HTML, type + +make docs + +Once the programs have been successfully compiled, they need to be installed in +their target locations. This step normally needs to be performed by the +superuser, and requires the following command to be entered. + +make install + +This will install the binaries and man pages. + +To install the HTML version of the manual, enter the command + +make install-docs + +Now that the software is successfully installed, the next step is to set up a +configuration file. The default location of the file is /etc/chrony.conf. +Several examples of configuration with comments are included in the examples +directory. Suppose you want to use public NTP servers from the pool.ntp.org +project as your time reference. A minimal useful configuration file could be + +pool pool.ntp.org iburst +makestep 1.0 3 +rtcsync + +Then, chronyd can be run. For security reasons, it's recommended to create an +unprivileged user for chronyd and specify it with the -u command-line option or +the user directive in the configuration file, or set the default user with the +--with-user configure option before building. + +Support for system call filtering + +chronyd can be built with support for the Linux secure computing (seccomp) +facility. This requires development files for the libseccomp library and the +--enable-scfilter option specified to configure. The -F option of chronyd will +enable a system call filter, which should significantly reduce the kernel +attack surface and possibly prevent kernel exploits from chronyd if it is +compromised. + +Extra options for package builders + +The configure and make procedures have some extra options that may be useful if +you are building a distribution package for chrony. + +The --mandir=DIR option to configure specifies an installation directory for +the man pages. This overrides the man subdirectory of the argument to the +--prefix option. + +./configure --prefix=/usr --mandir=/usr/share/man + +to set both options together. + +The final option is the DESTDIR option to the make command. For example, you +could use the commands + +./configure --prefix=/usr --mandir=/usr/share/man +make all docs +make install DESTDIR=./tmp +cd tmp +tar cvf - . | gzip -9 > chrony.tar.gz + +to build a package. When untarred within the root directory, this will install +the files to the intended final locations. + +Last updated 2024-10-08 14:49:43 +0200 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..318109b --- /dev/null +++ b/Makefile.in @@ -0,0 +1,143 @@ +################################################## +# +# chronyd/chronyc - Programs for keeping computer clocks accurate. +# +# Copyright (C) Richard P. Curnow 1997-2003 +# +# 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. +# +# ======================================================================= +# +# Makefile template + +SYSCONFDIR = @SYSCONFDIR@ +BINDIR = @BINDIR@ +SBINDIR = @SBINDIR@ +LOCALSTATEDIR = @LOCALSTATEDIR@ +CHRONYVARDIR = @CHRONYVARDIR@ +DESTDIR = + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ + +GETDATE_CFLAGS = @GETDATE_CFLAGS@ + +EXTRA_OBJS = @EXTRA_OBJS@ + +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) + +EXTRA_CLI_OBJS = @EXTRA_CLI_OBJS@ + +CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \ + pktlength.o socket.o util.o $(EXTRA_CLI_OBJS) + +ALL_OBJS = $(OBJS) $(CLI_OBJS) + +LIBS = @LIBS@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_CLI_LIBS = @EXTRA_CLI_LIBS@ + +# Until we have a main procedure we can link, just build object files +# to test compilation + +all : chronyd chronyc + +chronyd : $(OBJS) + $(CC) $(CFLAGS) -o chronyd $(OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) + +chronyc : $(CLI_OBJS) + $(CC) $(CFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_CLI_LIBS) + +getdate.o: CFLAGS += $(GETDATE_CFLAGS) + +distclean : clean + $(MAKE) -C doc distclean + $(MAKE) -C test/unit distclean + -rm -f .DS_Store + -rm -f Makefile config.h config.log + +clean : + $(MAKE) -C test/unit clean + -rm -f *.o *.s chronyc chronyd core.* *~ + -rm -f *.gcda *.gcno + -rm -rf .deps + -rm -rf *.dSYM + +getdate.c : getdate.y + bison -o getdate.c getdate.y + +# This can be used to force regeneration of getdate.c +getdate : + bison -o getdate.c getdate.y + +# For install, don't use the install command, because its switches +# seem to vary between systems. + +install: chronyd chronyc + [ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR) + [ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR) + [ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR) + [ -d $(DESTDIR)$(CHRONYVARDIR) ] || mkdir -p $(DESTDIR)$(CHRONYVARDIR) + if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi + if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi + cp chronyd $(DESTDIR)$(SBINDIR)/chronyd + chmod 755 $(DESTDIR)$(SBINDIR)/chronyd + cp chronyc $(DESTDIR)$(BINDIR)/chronyc + chmod 755 $(DESTDIR)$(BINDIR)/chronyc + $(MAKE) -C doc install + +docs : + $(MAKE) -C doc docs + +install-docs : + $(MAKE) -C doc install-docs + +%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + +%.s : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -S $< + +quickcheck : chronyd chronyc + $(MAKE) -C test/unit check + cd test/simulation && ./run + cd test/system && ./run + +check : chronyd chronyc + $(MAKE) -C test/unit check + cd test/simulation && ./run -i 20 -m 2 + cd test/system && ./run + +print-chronyd-objects : + @echo $(OBJS) + +Makefile : Makefile.in configure + @echo + @echo Makefile needs to be regenerated, run ./configure + @echo + @exit 1 + +.deps: + @mkdir .deps + +.deps/%.d: %.c | .deps + @$(CC) -MM $(CPPFLAGS) -MT '$(<:%.c=%.o) $@' $< -o $@ + +ifndef NODEPS +-include $(ALL_OBJS:%.o=.deps/%.d) +endif diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3555789 --- /dev/null +++ b/NEWS @@ -0,0 +1,1052 @@ +New in version 4.6.1 +==================== + +Enhancements +------------ +* Add ntsaeads directive to enable only selected AEAD algorithms for NTS + +Workarounds +----------- +* Negotiate use of compliant NTS keys with AES-128-GCM-SIV AEAD algorithm + (by default the keys are generated differently than in RFC 8915 for + compatibility with chrony server and client versions 4.4, 4.5, and 4.6) +* Switch to compliant NTS keys if first response from server is NTS NAK + +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 +* Allow disabling pidfile +* 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 +================== + +Enhancements +------------ +* Add support for AES-GCM-SIV in GnuTLS +* Add support for corrections from PTP transparent clocks +* Add support for systemd socket activation + +Bug fixes +--------- +* Fix presend in interleaved mode +* Fix reloading of modified sources from sourcedir + +New in version 4.4 +================== + +Enhancements +------------ +* Add support for AES-GCM-SIV with Nettle >= 3.9 to shorten NTS + cookies to avoid some length-specific blocking of NTP on Internet +* Add support for multiple refclocks using extpps option on one PHC +* Add maxpoll option to hwtimestamp directive to improve PHC tracking + with low packet rates +* Add hwtstimeout directive to configure timeout for late timestamps +* Handle late hardware transmit timestamps of NTP requests on all sockets +* Handle mismatched 32/64-bit time_t in SOCK refclock samples +* Improve source replacement +* Log important changes made by command requests (chronyc) +* Refresh address of NTP sources periodically +* Request nanosecond kernel RX timestamping on FreeBSD +* Set DSCP for IPv6 packets +* Shorten NTS-KE retry interval when network is down +* Update seccomp filter for musl +* Warn if loading keys from file with unexpected permissions +* Warn if source selection fails or falseticker is detected +* Add selectopts command to modify source-specific selection options +* Add timestamp sources to serverstats report and make its fields 64-bit +* Add -e option to chronyc to indicate end of response + +New in version 4.3 +================== + +Enhancements +------------ +* Add local option to refclock directive to stabilise system clock + with more stable free-running clock (e.g. TCXO, OCXO) +* Add maxdelayquant option to server/pool/peer directive to replace + maxdelaydevratio filter with long-term quantile-based filtering +* Add selection option to log directive +* Allow external PPS in PHC refclock without configurable pin +* Don't accept first interleaved response to minimise error in delay +* Don't use arc4random on Linux to avoid server performance loss +* Improve filter option to better handle missing NTP samples +* Improve stability with hardware timestamping and PHC refclock +* Update seccomp filter + +Bug fixes +--------- +* Fix waitsync command to reconnect when not getting response + +New in version 4.2 +================== + +Enhancements +------------ +* Add support for NTPv4 extension field improving synchronisation + stability and resolution of root delay and dispersion (experimental) +* Add support for NTP over PTP (experimental) +* Add support for AES-CMAC and hash functions in GnuTLS +* Improve server interleaved mode to be more reliable and support + multiple clients behind NAT +* Update seccomp filter +* Add statistics about interleaved mode to serverstats report + +Bug fixes +--------- +* Fix RTC support with 64-bit time_t on 32-bit Linux +* Fix seccomp filter to work correctly with bind*device directives +* Suppress kernel adjustments of system clock (dosynctodr) on illumos + +Other changes +------------- +* Switch Solaris support to illumos + +New in version 4.1 +================== + +Enhancements +------------ +* Add support for NTS servers specified by IP address (matching + Subject Alternative Name in server certificate) +* Add source-specific configuration of trusted certificates +* Allow multiple files and directories with trusted certificates +* Allow multiple pairs of server keys and certificates +* Add copy option to server/pool directive +* Increase PPS lock limit to 40% of pulse interval +* Perform source selection immediately after loading dump files +* Reload dump files for addresses negotiated by NTS-KE server +* Update seccomp filter and add less restrictive level +* Restart ongoing name resolution on online command + +Bug fixes +--------- +* Fix responding to IPv4 command requests on FreeBSD +* Fix dump files to not include uncorrected offset +* Fix initstepslew to accept time from own NTP clients +* Reset NTP address and port when no longer negotiated by NTS-KE server + +New in version 4.0 +================== + +Enhancements +------------ +* Add support for Network Time Security (NTS) authentication +* Add support for AES-CMAC keys (AES128, AES256) with Nettle +* Add authselectmode directive to control selection of unauthenticated sources +* Add binddevice, bindacqdevice, bindcmddevice directives +* Add confdir directive to better support fragmented configuration +* Add sourcedir directive and "reload sources" command to support dynamic + NTP sources specified in files +* Add clockprecision directive +* Add dscp directive to set Differentiated Services Code Point (DSCP) +* Add -L option to limit log messages by severity +* Add -p option to print whole configuration with included files +* Add -U option to allow start under non-root user +* Allow maxsamples to be set to 1 for faster update with -q/-Q option +* Avoid replacing NTP sources with sources that have unreachable address +* Improve pools to repeat name resolution to get "maxsources" sources +* Improve source selection with trusted sources +* Improve NTP loop test to prevent synchronisation to itself +* Repeat iburst when NTP source is switched from offline state to online +* Update clock synchronisation status and leap status more frequently +* Update seccomp filter +* Add "add pool" command +* Add "reset sources" command to drop all measurements +* Add authdata command to print details about NTP authentication +* Add selectdata command to print details about source selection +* Add -N option and sourcename command to print original names of sources +* Add -a option to some commands to print also unresolved sources +* Add -k, -p, -r options to clients command to select, limit, reset data + +Bug fixes +--------- +* Don't set interface for NTP responses to allow asymmetric routing +* Handle RTCs that don't support interrupts +* Respond to command requests with correct address on multihomed hosts + +Removed features +---------------- +* Drop support for RIPEMD keys (RMD128, RMD160, RMD256, RMD320) +* Drop support for long (non-standard) MACs in NTPv4 packets (chrony 2.x + clients using non-MD5/SHA1 keys need to use option "version 3") +* Drop support for line editing with GNU Readline + +New in version 3.5.1 +==================== + +Security fixes +-------------- +* Create new file when writing pidfile (CVE-2020-14367) + +New in version 3.5 +================== + +Enhancements +------------ +* Add support for more accurate reading of PHC on Linux 5.0 +* Add support for hardware timestamping on interfaces with read-only + timestamping configuration +* Add support for memory locking and real-time priority on FreeBSD, + NetBSD, Solaris +* Update seccomp filter to work on more architectures +* Validate refclock driver options + +Bug fixes +--------- +* Fix bindaddress directive on FreeBSD +* Fix transposition of hardware RX timestamp on Linux 4.13 and later +* Fix building on non-glibc systems + +New in version 3.4 +================== + +Enhancements +------------ +* Add filter option to server/pool/peer directive +* Add minsamples and maxsamples options to hwtimestamp directive +* Add support for faster frequency adjustments in Linux 4.19 +* Change default pidfile to /var/run/chrony/chronyd.pid to allow + chronyd without root privileges to remove it on exit +* Disable sub-second polling intervals for distant NTP sources +* Extend range of supported sub-second polling intervals +* Get/set IPv4 destination/source address of NTP packets on FreeBSD +* Make burst options and command useful with short polling intervals +* Modify auto_offline option to activate when sending request failed +* Respond from interface that received NTP request if possible +* Add onoffline command to switch between online and offline state + according to current system network configuration +* Improve example NetworkManager dispatcher script + +Bug fixes +--------- +* Avoid waiting in Linux getrandom system call +* Fix PPS support on FreeBSD and NetBSD + +New in version 3.3 +================== + +Enhancements +------------ +* Add burst option to server/pool directive +* Add stratum and tai options to refclock directive +* Add support for Nettle crypto library +* Add workaround for missing kernel receive timestamps on Linux +* Wait for late hardware transmit timestamps +* Improve source selection with unreachable sources +* Improve protection against replay attacks on symmetric mode +* Allow PHC refclock to use socket in /var/run/chrony +* Add shutdown command to stop chronyd +* Simplify format of response to manual list command +* Improve handling of unknown responses in chronyc + +Bug fixes +--------- +* Respond to NTPv1 client requests with zero mode +* Fix -x option to not require CAP_SYS_TIME under non-root user +* Fix acquisitionport directive to work with privilege separation +* Fix handling of socket errors on Linux to avoid high CPU usage +* Fix chronyc to not get stuck in infinite loop after clock step + +New in version 3.2 +================== + +Enhancements +------------ +* Improve stability with NTP sources and reference clocks +* Improve stability with hardware timestamping +* Improve support for NTP interleaved modes +* Control frequency of system clock on macOS 10.13 and later +* Set TAI-UTC offset of system clock with leapsectz directive +* Minimise data in client requests to improve privacy +* Allow transmit-only hardware timestamping +* Add support for new timestamping options introduced in Linux 4.13 +* Add root delay, root dispersion and maximum error to tracking log +* Add mindelay and asymmetry options to server/peer/pool directive +* Add extpps option to PHC refclock to timestamp external PPS signal +* Add pps option to refclock directive to treat any refclock as PPS +* Add width option to refclock directive to filter wrong pulse edges +* Add rxfilter option to hwtimestamp directive +* Add -x option to disable control of system clock +* Add -l option to log to specified file instead of syslog +* Allow multiple command-line options to be specified together +* Allow starting without root privileges with -Q option +* Update seccomp filter for new glibc versions +* Dump history on exit by default with dumpdir directive +* Use hardening compiler options by default + +Bug fixes +--------- +* Don't drop PHC samples with low-resolution system clock +* Ignore outliers in PHC tracking, RTC tracking, manual input +* Increase polling interval when peer is not responding +* Exit with error message when include directive fails +* Don't allow slash after hostname in allow/deny directive/command +* Try to connect to all addresses in chronyc before giving up + +New in version 3.1 +================== + +Enhancements +------------ +* Add support for precise cross timestamping of PHC on Linux +* Add minpoll, precision, nocrossts options to hwtimestamp directive +* Add rawmeasurements option to log directive and modify measurements + option to log only valid measurements from synchronised sources +* Allow sub-second polling interval with NTP sources + +Bug fixes +--------- +* Fix time smoothing in interleaved mode + +New in version 3.0 +================== + +Enhancements +------------ +* Add support for software and hardware timestamping on Linux +* Add support for client/server and symmetric interleaved modes +* Add support for MS-SNTP authentication in Samba +* Add support for truncated MACs in NTPv4 packets +* Estimate and correct for asymmetric network jitter +* Increase default minsamples and polltarget to improve stability + with very low jitter +* Add maxjitter directive to limit source selection by jitter +* Add offset option to server/pool/peer directive +* Add maxlockage option to refclock directive +* Add -t option to chronyd to exit after specified time +* Add partial protection against replay attacks on symmetric mode +* Don't reset polling interval when switching sources to online state +* Allow rate limiting with very short intervals +* Improve maximum server throughput on Linux and NetBSD +* Remove dump files after start +* Add tab-completion to chronyc with libedit/readline +* Add ntpdata command to print details about NTP measurements +* Allow all source options to be set in add server/peer command +* Indicate truncated addresses/hostnames in chronyc output +* Print reference IDs as hexadecimal numbers to avoid confusion with + IPv4 addresses + +Bug fixes +--------- +* Fix crash with disabled asynchronous name resolving + +New in version 2.4.1 +==================== + +Bug fixes +--------- +* Fix processing of kernel timestamps on non-Linux systems +* Fix crash with smoothtime directive +* Fix validation of refclock sample times +* Fix parsing of refclock directive + +New in version 2.4 +================== + +Enhancements +------------ +* Add orphan option to local directive for orphan mode compatible with ntpd +* Add distance option to local directive to set activation threshold + (1 second by default) +* Add maxdrift directive to set maximum allowed drift of system clock +* Try to replace NTP sources exceeding maximum distance +* Randomise source replacement to avoid getting stuck with bad sources +* Randomise selection of sources from pools on start +* Ignore reference timestamp as ntpd doesn't always set it correctly +* Modify tracking report to use same values as seen by NTP clients +* Add -c option to chronyc to write reports in CSV format +* Provide detailed manual pages + +Bug fixes +--------- +* Fix SOCK refclock to work correctly when not specified as last refclock +* Fix initstepslew and -q/-Q options to accept time from own NTP clients +* Fix authentication with keys using 512-bit hash functions +* Fix crash on exit when multiple signals are received +* Fix conversion of very small floating-point numbers in command packets + +Removed features +---------------- +* Drop documentation in Texinfo format + +New in version 2.3 +================== + +Enhancements +------------ +* Add support for NTP and command response rate limiting +* Add support for dropping root privileges on Mac OS X, FreeBSD, Solaris +* Add require and trust options for source selection +* Enable logchange by default (1 second threshold) +* Set RTC on Mac OS X with rtcsync directive +* Allow binding to NTP port after dropping root privileges on NetBSD +* Drop CAP_NET_BIND_SERVICE capability on Linux when NTP port is disabled +* Resolve names in separate process when seccomp filter is enabled +* Replace old records in client log when memory limit is reached +* Don't reveal local time and synchronisation state in client packets +* Don't keep client sockets open for longer than necessary +* Ignore poll in KoD RATE packets as ntpd doesn't always set it correctly +* Warn when using keys shorter than 80 bits +* Add keygen command to generate random keys easily +* Add serverstats command to report NTP and command packet statistics + +Bug fixes +--------- +* Fix clock correction after making step on Mac OS X +* Fix building on Solaris + +New in version 2.2.1 +==================== + +Security fixes +-------------- +* Restrict authentication of NTP server/peer to specified key (CVE-2016-1567) + +New in version 2.2 +================== + +Enhancements +------------ +* Add support for configuration and monitoring over Unix domain socket + (accessible by root or chrony user when root privileges are dropped) +* Add support for system call filtering with seccomp on Linux (experimental) +* Add support for dropping root privileges on NetBSD +* Control frequency of system clock on FreeBSD, NetBSD, Solaris +* Add system leap second handling mode on FreeBSD, NetBSD, Solaris +* Add dynamic drift removal on Mac OS X +* Add support for setting real-time priority on Mac OS X +* Add maxdistance directive to limit source selection by root distance + (3 seconds by default) +* Add refresh command to get new addresses of NTP sources +* Allow wildcard patterns in include directive +* Restore time from driftfile with -s option if later than RTC time +* Add configure option to set default hwclockfile +* Add -d option to chronyc to enable debug messages +* Allow multiple addresses to be specified for chronyc with -h option + and reconnect when no valid reply is received +* Make check interval in waitsync command configurable + +Bug fixes +--------- +* Fix building on NetBSD, Solaris +* Restore time from driftfile with -s option if reading RTC failed + +Removed features +---------------- +* Drop support for authentication with command key (run-time configuration + is now allowed only for local users that can access the Unix domain socket) + +New in version 2.1.1 +==================== + +Bug fixes +--------- +* Fix clock stepping by integer number of seconds on Linux + +New in version 2.1 +================== + +Enhancements +------------ +* Add support for Mac OS X +* Try to replace unreachable and falseticker servers/peers specified + by name like pool sources +* Add leaponly option to smoothtime directive to allow synchronised + leap smear between multiple servers +* Use specific reference ID when smoothing served time +* Add smoothing command to report time smoothing status +* Add smoothtime command to activate or reset time smoothing + +Bug fixes +--------- +* Fix crash in source selection with preferred sources +* Fix resetting of time smoothing +* Include packet precision in peer dispersion +* Fix crash in chronyc on invalid command syntax + +New in version 2.0 +================== + +Enhancements +------------ +* Update to NTP version 4 (RFC 5905) +* Add pool directive to specify pool of NTP servers +* Add leapsecmode directive to select how to correct clock for leap second +* Add smoothtime directive to smooth served time and enable leap smear +* Add minsources directive to set required number of selectable sources +* Add minsamples and maxsamples options for all sources +* Add tempcomp configuration with list of points +* Allow unlimited number of NTP sources, refclocks and keys +* Allow unreachable sources to remain selected +* Improve source selection +* Handle offline sources as unreachable +* Open NTP server port only when necessary (client access is allowed by + allow directive/command or peer/broadcast is configured) +* Change default bindcmdaddress to loopback address +* Change default maxdelay to 3 seconds +* Change default stratumweight to 0.001 +* Update adjtimex synchronisation status +* Use system headers for adjtimex +* Check for memory allocation errors +* Reduce memory usage +* Add configure options to compile without NTP, cmdmon, refclock support +* Extend makestep command to set automatic clock stepping + +Bug fixes +--------- +* Add sanity checks for time and frequency offset +* Don't report synchronised status during leap second +* Don't combine reference clocks with close NTP sources +* Fix accepting requests from configured sources +* Fix initial fallback drift setting + +New in version 1.31.1 +===================== + +Security fixes +-------------- +* Protect authenticated symmetric NTP associations against DoS attacks + (CVE-2015-1853) +* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821) +* Fix initialization of reply slots for authenticated commands (CVE-2015-1822) + +New in version 1.31 +=================== + +Enhancements +------------ +* Support operation in other NTP eras (next era begins in 2036), + NTP time is mapped to [-50, +86] years around build date by default +* Restore time from driftfile with -s when RTC is missing/unsupported +* Close connected client sockets when not waiting for reply +* Use one client socket with random port when acquisitionport is 0 +* Use NTP packets instead of UDP echo for presend +* Don't adjust polling interval when sending fails +* Allow binding to addresses that don't exist yet +* Ignore measurements around leap second +* Improve detection of unexpected time jumps +* Include example of logrotate configuration, systemd services and + NetworkManager dispatcher script + +Bug fixes +--------- +* Reconnect client sockets for each request to follow changes + in network configuration automatically +* Restart timer when polling interval is changed on reset + +New in version 1.30 +=================== + +Enhancements +------------ +* Add asynchronous name resolving with POSIX threads +* Add PTP hardware clock (PHC) refclock driver +* Add new generic clock driver to slew by adjusting frequency only + (without kernel PLL or adjtime) and use it on Linux +* Add rtcautotrim directive to trim RTC automatically +* Add hwclockfile directive to share RTC LOCAL/UTC setting with hwclock +* Add maxslewrate directive to set maximum allowed slew rate +* Add maxdispersion option for refclocks +* Add -q/-Q options to set clock/print offset once and exit +* Allow directives to be specified on chronyd command line +* Replace frequency scaling in Linux driver with retaining of tick +* Try to detect unexpected forward time jumps and reset state +* Exit with non-zero code when maxchange limit is reached +* Improve makestep to not start and stop slew unnecessarily +* Change default corrtimeratio to 3.0 to improve frequency accuracy +* Announce leap second only on last day of June and December +* Use separate connected client sockets for each NTP server +* Remove separate NTP implementation used for initstepslew +* Limit maximum minpoll set by KoD RATE to default maxpoll +* Don't send NTP requests with unknown key +* Print warning when source is added with unknown key +* Take leap second in PPS refclock from locked source +* Make reading of RTC for initial trim more reliable +* Don't create cmdmon sockets when cmdport is 0 +* Add configure option to set default user to drop root privileges +* Add configure option to compile with debug messages +* Print debug messages when -d is used more than once +* Change format of messages written to terminal with -d +* Write fatal messages also to stderr with -n +* Use IP_RECVERR socket option in chronyc to not wait unnecessarily +* Shorten default chronyc timeout for localhost +* Change default hostname in chronyc from localhost to 127.0.0.1 +* Print error message on invalid syntax with all chronyc commands +* Include simulation test suite using clknetsim + +Bug fixes +--------- +* Fix crash when selecting with multiple preferred sources +* Fix frequency calculation with large frequency offsets +* Fix code writing drift and RTC files to compile correctly +* Fix -4/-6 options in chronyc to not reset hostname set by -h +* Fix refclock sample validation with sub-second polling interval +* Set stratum correctly with non-PPS SOCK refclock and local stratum +* Modify dispersion accounting in refclocks to prevent PPS getting + stuck with large dispersion and not accepting new samples + +New in version 1.29.1 +===================== + +Security fixes +-------------- +* Modify chronyc protocol to prevent amplification attacks (CVE-2014-0021) + (incompatible with previous protocol version, chronyc supports both) + +New in version 1.29 +=================== + +Security fixes +-------------- +* Fix crash when processing crafted commands (CVE-2012-4502) + (possible with IP addresses allowed by cmdallow and localhost) +* Don't send uninitialized data in SUBNETS_ACCESSED and CLIENT_ACCESSES + replies (CVE-2012-4503) (not used by chronyc) + +Other changes +------------- +* Drop support for SUBNETS_ACCESSED and CLIENT_ACCESSES commands + +New in version 1.28 +=================== + +* Combine sources to improve accuracy +* Make config and command parser strict +* Add -a option to chronyc to authenticate automatically +* Add -R option to ignore initstepslew and makestep directives +* Add generatecommandkey, minsamples, maxsamples and user directives +* Improve compatibility with NTPv1 and NTPv2 clients +* Create sockets only in selected family with -4/-6 option +* Treat address bind errors as non-fatal +* Extend tracking log +* Accept float values as initstepslew threshold +* Allow hostnames in offline, online and burst commands +* Fix and improve peer polling +* Fix crash in config parsing with too many servers +* Fix crash with duplicated initstepslew address +* Fix delta calculation with extreme frequency offsets +* Set local stratum correctly +* Remove unnecessary adjtimex calls +* Set paths in documentation by configure +* Update chrony.spec + +New in version 1.27 +=================== + +* Support for stronger keys via NSS or libtomcrypt library +* Support reading leap second data from tz database +* Support for precise clock stepping on Linux +* Support for nanoseconds in SHM refclock +* Make offset corrections smoother on Linux +* Make transmit timestamps random below clock precision +* Add corrtimeratio and maxchange directives +* Extend tracking, sources and activity reports +* Wait in foreground process until daemon is fully initialized +* Fix crash with slow name resolving +* Fix iburst with jittery sources +* Fix offset stored in rtc data right after trimrtc +* Fix crash and hang with RTC or manual samples +* Don't use readonly adjtime on Linux kernels before 2.6.28 +* Changed chronyc protocol, incompatible with older versions + +New in version 1.26 +=================== + +* Add compatibility with Linux 3.0 and later +* Use proper source address in NTP replies on multihomed IPv6 hosts +* Accept NTP packets with versions 4, 3 and 2 +* Cope with unexpected backward time jumps +* Don't reset kernel frequency on start without drift file +* Retry on permanent DNS error by default +* Add waitsync command + +New in version 1.25 +=================== + +* Improve accuracy with NTP sources +* Improve accuracy with reference clocks +* Improve polling interval adjustment +* Improve stability with temporary asymmetric delays +* Improve source selection +* Improve initial synchronisation +* Add delayed server name resolving +* Add temperature compensation +* Add nanosecond slewing to Linux driver +* Add fallback drifts +* Add iburst, minstratum, maxdelaydevratio, polltarget, + prefer, noselect options +* Add rtcsync directive to enable Linux 11-minute mode +* Add reselectdist, stratumweight, logbanner, maxclockerror, + include directives +* Add -n option to not detach daemon from terminal +* Fix pidfile directive +* Fix name resolving with disabled IPv6 support +* Fix reloading sample histories with reference clocks +* Fix crash with auto_offline option +* Fix online command on auto_offline sources +* Fix file descriptor leaks +* Increase burst polling interval and stop on KoD RATE +* Set maxupdateskew to 1000 ppm by default +* Require password for clients command +* Update drift file at most once per hour +* Use system headers for Linux RTC support +* Reduce default chronyc timeout and make it configurable +* Avoid large values in chronyc sources and sourcestats output +* Add reselect command to force reselecting best source +* Add -m option to allow multiple commands on command line + +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) +* IPv6 support +* Linux capabilities support (to drop root privileges) +* Memory locking support on Linux +* Real-time scheduler support on Linux +* Leap second support on Linux +* Support for editline library +* Support for new Linux readonly adjtime +* NTP client support for KoD RATE +* Read kernel timestamps for received NTP packets +* Reply to NTP requests with correct address on multihomed hosts +* 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 +* Support for Linux on S/390 and PowerPC +* Fix various bugs on 64-bit systems +* Fix valgrind errors and compiler warnings +* Improve configure to support common options and variables +* Improve status checking and printing in chronyc +* Return non-zero exit code on errors in chronyc +* Reduce request timeout in chronyc +* Print estimated offset in sourcestats +* Changed chronyc protocol, incompatible with older versions + +New in version 1.23 +=================== + +* Support for MIPS, x86_64, sparc, alpha, arm, FreeBSD +* Fix serious sign-extension error in handling IP addresses +* RTC support can be excluded at compile time +* Make sources gcc-4 compatible +* Fix various compiler warnings +* Handle fluctuations in peer distance better. +* Fixed handling of stratum zero. +* Fix various problems for 64-bit systems +* Flush chronyc output streams after each command, to allow it to be driven + through pipes +* Manpage improvements + +Version 1.22 +============ + +This release number was claimed by a release that Mandriva made to patch +important bugs in 1.21. The official numbering has jumped to 1.23 as a +consequence. + +New in version 1.21 +=================== + +* Don't include Linux kernel header files any longer : allows chrony to compile + on recent distros. +* Stop trying to use RTC if continuous streams of error messages would occur + (Linux with HPET). + +New in version 1.20 +=================== + +* Many small tidy-ups and security improvements +* Improve documentation (RTC support in post 2.0 kernels) +* Remove trailing \n from syslog messages +* Syslog messages now include IP and port number when packet cannot be sent. +* Added the "acquisitionport" directive. (Kalle Olavi Niemitalo) +* Use uname(2) instead of /proc/version to get kernel version. +* Merge support for Linux on Alpha +* Merge support for 64bit architectures +* Don't link -lm if it's not needed +* Fix Solaris build (broken by 64bit change) +* Add detection of Linux 2.5 +* Allow arbitrary value of HZ in Linux kernel +* Fix for chrony.spec on SuSE (Paul Elliot) +* Fix handling of initstepslew if no servers are listed (John Hasler) +* Fix install rule in Makefile if chronyd is in use (Juliusz Chroboczek) +* Replace sprintf by snprintf to remove risk of buffer overrun (John Hasler) +* Add --help to configure script + +New in version 1.19 +=================== + +* Auto-detect kernel's timer interrupt rate (so-called 'HZ') when chronyd + starts instead of relying on compiled-in value. +* Fix 2 bugs in function that creates the directory for the log and dump files. +* Amended webpage URL and contact details. +* Generate more informative syslog messages before exiting on failed + assertions. +* Fix bugs in clamping code for the tick value used when slewing a large + offset. +* Don't chown files to root during install (should be pointless, and makes RPM + building awkward as ordinary user.) +* Include chrony.spec file for building RPMs + +New in version 1.18 +=================== +* Amend homepage and mailing list information to chrony.sunsite.dk +* Delete pidfile on exit from chronyd. +* Improvements to readline interface to chronyc +* Only generate syslog message when synchronisation is initially lost (instead + of on every failed synchronisation attempt) +* Use double fork approach when initialising daemon. +* More things in contrib directory. +* New options to help package builders: --infodir/--mandir for configure, and + DESTDIR=xxx for make. (See section 2.2 of chrony.txt for details). +* Changed the wording of the messages generated by mailonchange and logchange + directives. + +New in version 1.17 +=================== +* Port to NetBSD +* Configuration supports Linux on PPC +* Fix compilation warnings +* Several documentation improvements +* Bundled manpages (taken from the 'missing manpages project') +* Cope with lack of bzero function for Solaris 2.3 systems +* Store chronyd's pid in a file (default /var/run/chronyd.pid) and check if + chronyd may already be running when starting up. New pidfile directive in + configuration file. +* Any size subnet is now allowed in allow and deny commands. (Example: + 6.7.8/20 or 6.7.8.x/20 (any x) mean a 20 bit subnet). +* The environment variables CC and CFLAGS passed to configure can now be used + to select the compiler and optimisation/debug options to use +* Write syslog messages when chronyd loses synchronisation. +* Print GPL text when chronyc is run. +* Add NTP broadcast server capability (new broadcast directive). +* Add 'auto_offline' option to server/peer (conf file) or add server/peer (via + chronyc). +* Add 'activity' command to chronyc, to report how many servers/peers are + currently online/offline. +* Fix long-standing bug with how the system time quantum was calculated. +* Include support for systems with HZ!=100 (HZ is the timer interrupt + frequency). +* Include example chrony.conf and chrony.keys files (examples subdirectory). +* Include support for readline in chronyc. + +New in version 1.16.1 +===================== +* Fix compilation problem on Linux 2.4.13 (spinlock.h / spinlock_t) + +New in version 1.16 +=================== +* More informative captions for 'sources' and 'sourcestats' commands in chronyc + (use 'sources -v' and 'sourcestats -v' to get them). +* Correct behaviour for Solaris versions>=2.6 (dosynctodr not required on these + versions.) +* Remove some compiler warnings (Solaris) +* If last line of keys file doesn't have end-of-line, don't truncate final + character of that key. +* Change timestamp format used in logfiles to make it fully numeric (to aid + importing data into spreadsheets etc) +* Minor documentation updates and improvements. + +New in version 1.15 +=================== +* Add contributed change to 'configure' to support Solaris 2.8 on x86 +* Workaround for assertion failure that arises if two received packets occur + close together. (Still need to find out why this happens at all.) +* Hopefully fix problem where fast slewing was incompatible with machines + that have a large background drift rate (=> tick value went out of range + for adjtimex() on Linux.) +* Fix rtc_linux.c compile problems with 2.4.x kernel include files. +* Include support for RTC device not being at /dev/rtc (new rtcdevice directive + in configuration file). +* Include support for restricting network interfaces for commands (new + bindcmdaddress directive in configuration file) +* Fix potential linking fault in pktlength.c (use of CROAK macro replaced by + normal assert). +* Add some material on bug reporting + contributing to the chrony.texi file +* Made the chrony.texi file "Vim6-friendly" (removed xrefs on @node lines, + added folding markers to chapters + sections.) +* Switched over to GPL for the licence + +New in version 1.14 +=================== +* Fix compilation for certain other Linux distributions (including Mandrake + 7.1) + +New in version 1.13 +=================== +* Fixed compilation problems on Redhat/SuSE installations with recent 2.2.x + kernels. +* Minor tidy-ups and documentation enhancements. +* Add support for Linux 2.4 kernels + +New in version 1.12 +=================== + +* Trial fix for long-standing bug in Linux RTC estimator when system time is + slewed. +* Fix bug in chronyc if -h is specified without a hostname +* Fixes to logging various error conditions when operating in daemon mode. +* More stuff under contrib/ +* Changes to README file (e.g. about the new chrony-users mailing list) + +New in version 1.11a +==================== + +* Minor changes to contact details +* Minor changes to installation details (chrony subdirectory under doc/) + +New in version 1.11 +=================== + +* Improve robustness of installation procedure +* Tidy up documenation and contact details +* Distribute manual as .txt rather than as .ps +* Add -n option to chronyc to work with numeric IP addresses rather than + names. +* Add material in contrib subdirectory +* Improve robustness of handling drift file and RTC coefficients file +* Improve robustness of regression algorithm + +New in version 1.1 +================== + +Bug fixes +--------- + +* Made linear regression more resistant to rounding errors (old one + occasionally generated negative variances which made everything go + haywire). Trap infinite or 'not-a-number' values being used to + alter system clock to increase robustness further. + +Other changes/Enhancements +-------------------------- + +* Support for Linux 2.1 and 2.2 kernels + +* New command 'makestep' in chronyc to immediately jump the system + time to match the NTP estimated time (Linux only) - a response to + systems booting an hour wrong after summertime/wintertime changes, + due to RTCs running on local time. Needs extending to Sun driver + files too. + +* New directives 'logchange' and 'mailonchange' to log to syslog or + email to a specific address respectively if chronyd detects a clock + offset exceeding a defined threshold. + +* Added capability to log all client/peer NTP accesses and command + accesses (can be turned off with conf file directive 'noclientlog'). + Added 'clients' command to chronyc to display this data. + +* Improved manual mode to use robust regression rather than 2 point + fit. + +* Added 'manual list' and 'manual delete' commands to chronyc to + allow display of entered timestamps and discretionary deletion of + outliers. + +* If host goes unsynchronised the dummy IP address 0.0.0.0 is detected + to avoid attempting a reverse name lookup (to stop dial on demand IP + links from being started) + +* Changed chronyc/chronyd protocol so messages are now all variable + length. Saves on network bandwidth particularly for large replies + from chronyd to chronyc (to support the clients command). + +* Added bindaddress directive to configuration file, to give + additional control over limiting which hosts can access the local + server. + +* Groundwork done for a port to Windows NT to compile with Cygwin + toolkit. chronyc works (to monitor another host). sys_winnt.c + needs finishing to use NT clock control API. Program structure + needs adapting to use Windows NT service functions, so it can be + started at boot time. Hopefully a Windows NT / Cygwin guru with + some spare time can take this port over :-) + +New in version 1.02 +=================== + +Bug fixes +--------- + +* Fix error messages in chronyc if daemon is not reachable. + +* Fix config file problem for 'allow all' and 'deny all' without a + trailing machine address. + +* Remove fatal failed assertion if command socket cannot be read from + in daemon. + +* Rewrote timezone handling for Linux real time clock, following + various reported problems related to daylight saving. + +Other changes/Enhancements +-------------------------- + +* Configure script recognizes BSD/386 and uses SunOS 4.1 driver for + it. + +* Log files now print date as day-month-year rather than as a day + number. Milliseconds removed from timestamps of logged data. + Banners included in file to give meanings of columns. + +* Only do 1 initial step (followed by a trimming slew) when + initialising from RTC on Linux (previously did 2 steps). + +New in version 1.01 +=================== + +Bug fixes +--------- + +* Handle timezone of RTC correctly with respect to daylight saving + time + +* Syntax check the chronyc 'local' command properly + +* Fixed assertion failed fault in median finder (used by RTC + regression fitting) + +Other changes/Enhancements +-------------------------- + +* Log selection of new NTP reference source to syslog. + +* Don't zero-pad IP address fields + +* Add new command to chronyc to allow logfiles to be cycled. + +* Extend allow/deny directive syntax in configuration file to so + directive can apply to all hosts on the Internet. + +* Tidy up printout of timestamps to make it clear they are in UTC + +* Make 'configure' check the processor type as well as the operating + system. diff --git a/README b/README new file mode 100644 index 0000000..79b515b --- /dev/null +++ b/README @@ -0,0 +1,145 @@ +This is the README for chrony. + +What is chrony? +=============== + +chrony is a versatile implementation of the Network Time Protocol (NTP). +It can synchronise the system clock with NTP servers, reference clocks +(e.g. GPS receiver), and manual input using wristwatch and keyboard. +It can also operate as an NTPv4 (RFC 5905) server and peer to provide +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 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 +microseconds. With hardware timestamping, or a hardware reference clock, +sub-microsecond accuracy may be possible. + +Two programs are included in chrony, chronyd is a daemon that can be +started at boot time and chronyc is a command-line interface program +which can be used to monitor chronyd's performance and to change various +operating parameters whilst it is running. + +What will chrony run on? +======================== + +The software is known to work on Linux, FreeBSD, NetBSD, macOS and +illumos. Closely related systems may work too. Any other system will +likely require a porting exercise. + +How do I set it up? +=================== + +The file INSTALL gives instructions. On supported systems the +compilation process should be automatic. You will need a C compiler, +e.g. gcc or clang. + +What documentation is there? +============================ + +The distribution includes manual pages and a document containing +Frequently Asked Questions (FAQ). + +The documentation is also available on the chrony web pages, accessible +through the URL + + https://chrony-project.org/ + +License +======= + +chrony is distributed under the GNU General Public License version 2. + +Authors +======= + +Richard P. Curnow +Miroslav Lichvar + +Acknowledgements +================ + +In writing the chronyd program, extensive use has been made of the NTPv3 (RFC +1305) and NTPv4 (RFC 5905) specification. The source code of the xntpd/ntpd +implementation written by Dennis Fergusson, Lars Mathiesen, David Mills, and +others has been used to check the details of the protocol. + +The following people have provided patches and other major contributions +to chrony: + +Lonnie Abelbeck +Benny Lyne Amorsen +Andrew Bishop +Vincent Blut +Luca Boccassi +Stephan I. Boettcher +David Bohman +Goswin Brederlow +Leigh Brown +Erik Bryer +Jonathan Cameron +Bryan Christianson +Juliusz Chroboczek +Dan Drown +Kamil Dudka +Christian Ehrhardt +Paul Elliott +Robert Fairley +Stefan R. Filipek +Andy Fiddaman +Mike Fleetwood +Rob Gill +Alexander Gretencord +Andrew Griffiths +Walter Haidinger +Juergen Hannken-Illjes +John Hasler +Tjalling Hattink +Liam Hatton +Holger Hoffstätte +Jachym Holecek +Håkan Johansson +Jim Knoble +Antti Jrvinen +Uwe Kleine-König +Eric Lammerts +Stefan Lucke +Victor Lum +Kevin Lyda +Paul Menzel +Vladimir Michl +Victor Moroz +Kalle Olavi Niemitalo +Patrick Oppenlander +Frank Otto +Denny Page +Rupesh Patel +Chris Perl +Gautier PHILIPPON +Andreas Piesk +Mike Ryan +Baruch Siach +Josef 'Jeff' Sipek +Foster Snowhill +Andreas Steinmetz +NAKAMURA Takumi +Timo Teras +Bill Unruh +Luke Valenta +Stephen Wadeley +Bernhard Weiss +Wolfgang Weisselberg +Bernhard M. Wiedemann +Joachim Wiedorn +Ralf Wildenhues +Ulrich Windl +Michael Witten +Doug Woodward +Thomas Zajic + +Many other people have contributed bug reports and suggestions. We are sorry +we cannot identify all of you individually. diff --git a/addressing.h b/addressing.h new file mode 100644 index 0000000..3e311fa --- /dev/null +++ b/addressing.h @@ -0,0 +1,67 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 1997-2002 + * + * 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. + * + ********************************************************************** + + ======================================================================= + + Types used for addressing sources etc + */ + +#ifndef GOT_ADDRESSING_H +#define GOT_ADDRESSING_H + +#include "sysincl.h" + +/* This type is used to represent an IPv4 address or IPv6 address. + Addresses which are not resolved yet can be represented with an ID. + All parts are in HOST order, NOT network order. */ + +#define IPADDR_UNSPEC 0 +#define IPADDR_INET4 1 +#define IPADDR_INET6 2 +#define IPADDR_ID 3 + +typedef struct { + union { + uint32_t in4; + uint8_t in6[16]; + uint32_t id; + } addr; + uint16_t family; + uint16_t _pad; +} IPAddr; + +typedef struct { + IPAddr ip_addr; + uint16_t port; +} IPSockAddr; + +typedef IPSockAddr NTP_Remote_Address; + +#define INVALID_IF_INDEX -1 + +typedef struct { + IPAddr ip_addr; + int if_index; + int sock_fd; +} NTP_Local_Address; + +#endif /* GOT_ADDRESSING_H */ + diff --git a/addrfilt.c b/addrfilt.c new file mode 100644 index 0000000..6208b46 --- /dev/null +++ b/addrfilt.c @@ -0,0 +1,405 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005 + * Copyright (C) Miroslav Lichvar 2009, 2015 + * + * 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 a set of routines for checking IP addresses + against a set of rules and deciding whether they are allowed or + disallowed. + + */ + +#include "config.h" + +#include "sysincl.h" + +#include "addrfilt.h" +#include "memory.h" + +/* Define the number of bits which are stripped off per level of + indirection in the tables */ +#define NBITS 4 + +/* Define the table size */ +#define TABLE_SIZE (1UL<addr.in6[i * 4 + 0] << 24 | + ip->addr.in6[i * 4 + 1] << 16 | + ip->addr.in6[i * 4 + 2] << 8 | + ip->addr.in6[i * 4 + 3]; +} + +/* ================================================== */ + +inline static uint32_t +get_subnet(uint32_t *addr, unsigned int where) +{ + int off; + + off = where / 32; + where %= 32; + + return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1); +} + +/* ================================================== */ + +ADF_AuthTable +ADF_CreateTable(void) +{ + ADF_AuthTable result; + result = MallocNew(struct ADF_AuthTableInst); + + /* Default is that nothing is allowed */ + result->base4.state = DENY; + result->base4.extended = NULL; + result->base6.state = DENY; + result->base6.extended = NULL; + + return result; +} + +/* ================================================== */ +/* This function deletes all definitions of child nodes, in effect + pruning a whole subnet definition back to a single parent + record. */ +static void +close_node(TableNode *node) +{ + int i; + TableNode *child_node; + + if (node->extended != NULL) { + for (i=0; iextended[i]); + close_node(child_node); + } + Free(node->extended); + node->extended = NULL; + } +} + + +/* ================================================== */ +/* Allocate the extension field in a node, and set all the children's + states to default to that of the node being extended */ + +static void +open_node(TableNode *node) +{ + int i; + TableNode *child_node; + + if (node->extended == NULL) { + + node->extended = MallocArray(struct _TableNode, TABLE_SIZE); + + for (i=0; iextended[i]); + child_node->state = AS_PARENT; + child_node->extended = NULL; + } + } +} + +/* ================================================== */ + +static ADF_Status +set_subnet(TableNode *start_node, + uint32_t *ip, + int ip_len, + int subnet_bits, + State new_state, + int delete_children) +{ + int bits_to_go, bits_consumed; + uint32_t subnet; + TableNode *node; + + bits_consumed = 0; + bits_to_go = subnet_bits; + node = start_node; + + if ((subnet_bits < 0) || + (subnet_bits > 32 * ip_len)) { + + return ADF_BADSUBNET; + + } else { + + if ((bits_to_go & (NBITS-1)) == 0) { + + while (bits_to_go > 0) { + subnet = get_subnet(ip, bits_consumed); + if (!(node->extended)) { + open_node(node); + } + node = &(node->extended[subnet]); + bits_to_go -= NBITS; + bits_consumed += NBITS; + } + + if (delete_children) { + close_node(node); + } + node->state = new_state; + + } else { /* Have to set multiple entries */ + int N, i, j; + TableNode *this_node; + + while (bits_to_go >= NBITS) { + subnet = get_subnet(ip, bits_consumed); + if (!(node->extended)) { + open_node(node); + } + node = &(node->extended[subnet]); + bits_to_go -= NBITS; + bits_consumed += NBITS; + } + + /* How many subnet entries to set : 1->8, 2->4, 3->2 */ + N = 1 << (NBITS-bits_to_go); + + subnet = get_subnet(ip, bits_consumed) & ~(N - 1); + assert(subnet + N <= TABLE_SIZE); + + if (!(node->extended)) { + open_node(node); + } + + for (i=subnet, j=0; jextended[i]); + if (delete_children) { + close_node(this_node); + } + this_node->state = new_state; + } + } + + return ADF_SUCCESS; + } + +} + +/* ================================================== */ + +static ADF_Status +set_subnet_(ADF_AuthTable table, + IPAddr *ip_addr, + int subnet_bits, + State new_state, + int delete_children) +{ + uint32_t ip6[4]; + + switch (ip_addr->family) { + case IPADDR_INET4: + return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children); + case IPADDR_INET6: + split_ip6(ip_addr, ip6); + return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children); + case IPADDR_UNSPEC: + /* Apply to both, subnet_bits has to be 0 */ + if (subnet_bits != 0) + return ADF_BADSUBNET; + memset(ip6, 0, sizeof (ip6)); + if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS && + set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS) + return ADF_SUCCESS; + break; + default: + break; + } + + return ADF_BADSUBNET; +} + +ADF_Status +ADF_Allow(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits) +{ + return set_subnet_(table, ip, subnet_bits, ALLOW, 0); +} + +/* ================================================== */ + + +ADF_Status +ADF_AllowAll(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits) +{ + return set_subnet_(table, ip, subnet_bits, ALLOW, 1); +} + +/* ================================================== */ + +ADF_Status +ADF_Deny(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits) +{ + return set_subnet_(table, ip, subnet_bits, DENY, 0); +} + +/* ================================================== */ + +ADF_Status +ADF_DenyAll(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits) +{ + return set_subnet_(table, ip, subnet_bits, DENY, 1); +} + +/* ================================================== */ + +void +ADF_DestroyTable(ADF_AuthTable table) +{ + close_node(&table->base4); + close_node(&table->base6); + Free(table); +} + +/* ================================================== */ + +static int +check_ip_in_node(TableNode *start_node, uint32_t *ip) +{ + uint32_t subnet; + int bits_consumed = 0; + int result = 0; + int finished = 0; + TableNode *node; + State state=DENY; + + node = start_node; + + do { + if (node->state != AS_PARENT) { + state = node->state; + } + if (node->extended) { + subnet = get_subnet(ip, bits_consumed); + node = &(node->extended[subnet]); + bits_consumed += NBITS; + } else { + /* Make decision on this node */ + finished = 1; + } + } while (!finished); + + switch (state) { + case ALLOW: + result = 1; + break; + case DENY: + result = 0; + break; + case AS_PARENT: + assert(0); + break; + } + + return result; +} + + +/* ================================================== */ + +int +ADF_IsAllowed(ADF_AuthTable table, + IPAddr *ip_addr) +{ + uint32_t ip6[4]; + + switch (ip_addr->family) { + case IPADDR_INET4: + return check_ip_in_node(&table->base4, &ip_addr->addr.in4); + case IPADDR_INET6: + split_ip6(ip_addr, ip6); + return check_ip_in_node(&table->base6, ip6); + default: + return 0; + } +} + +/* ================================================== */ + +static int +is_any_allowed(TableNode *node, State parent) +{ + State state; + int i; + + state = node->state != AS_PARENT ? node->state : parent; + assert(state != AS_PARENT); + + if (node->extended) { + for (i = 0; i < TABLE_SIZE; i++) { + if (is_any_allowed(&node->extended[i], state)) + return 1; + } + } else if (state == ALLOW) { + return 1; + } + + return 0; +} + +/* ================================================== */ + +int +ADF_IsAnyAllowed(ADF_AuthTable table, int family) +{ + switch (family) { + case IPADDR_INET4: + return is_any_allowed(&table->base4, AS_PARENT); + case IPADDR_INET6: + return is_any_allowed(&table->base6, AS_PARENT); + default: + return 0; + } +} diff --git a/addrfilt.h b/addrfilt.h new file mode 100644 index 0000000..b8c131f --- /dev/null +++ b/addrfilt.h @@ -0,0 +1,80 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 1997-2002 + * + * 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. + * + ********************************************************************** + + ======================================================================= + + Module for providing an authorisation filter on IP addresses + */ + +#ifndef GOT_ADDRFILT_H +#define GOT_ADDRFILT_H + +#include "addressing.h" + +typedef struct ADF_AuthTableInst *ADF_AuthTable; + +typedef enum { + ADF_SUCCESS, + ADF_BADSUBNET +} ADF_Status; + + +/* Create a new table. The default rule is deny for everything */ +extern ADF_AuthTable ADF_CreateTable(void); + +/* Allow anything in the supplied subnet, EXCEPT for any more specific + subnets that are already defined */ +extern ADF_Status ADF_Allow(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits); + +/* Allow anything in the supplied subnet, overwriting existing + definitions for any more specific subnets */ +extern ADF_Status ADF_AllowAll(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits); + +/* Deny anything in the supplied subnet, EXCEPT for any more specific + subnets that are already defined */ +extern ADF_Status ADF_Deny(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits); + +/* Deny anything in the supplied subnet, overwriting existing + definitions for any more specific subnets */ +extern ADF_Status ADF_DenyAll(ADF_AuthTable table, + IPAddr *ip, + int subnet_bits); + +/* Clear up the table */ +extern void ADF_DestroyTable(ADF_AuthTable table); + +/* Check whether a given IP address is allowed by the rules in + the table */ +extern int ADF_IsAllowed(ADF_AuthTable table, + IPAddr *ip); + +/* Check if at least one address from a given family is allowed by + the rules in the table */ +extern int ADF_IsAnyAllowed(ADF_AuthTable table, + int family); + +#endif /* GOT_ADDRFILT_H */ diff --git a/array.c b/array.c new file mode 100644 index 0000000..b31ba56 --- /dev/null +++ b/array.c @@ -0,0 +1,145 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2014 + * + * 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. + * + ********************************************************************** + + ======================================================================= + + Functions implementing an array with automatic memory allocation. + + */ + +#include "config.h" + +#include "sysincl.h" + +#include "array.h" +#include "memory.h" + +struct ARR_Instance_Record { + void *data; + unsigned int elem_size; + unsigned int used; + unsigned int allocated; +}; + +ARR_Instance +ARR_CreateInstance(unsigned int elem_size) +{ + ARR_Instance array; + + assert(elem_size > 0); + + array = MallocNew(struct ARR_Instance_Record); + + array->data = NULL; + array->elem_size = elem_size; + array->used = 0; + array->allocated = 0; + + return array; +} + +void +ARR_DestroyInstance(ARR_Instance array) +{ + Free(array->data); + Free(array); +} + +static void +realloc_array(ARR_Instance array, unsigned int min_size) +{ + assert(min_size <= 2 * min_size); + if (array->allocated >= min_size && array->allocated <= 2 * min_size) + return; + + if (array->allocated < min_size) { + while (array->allocated < min_size) + array->allocated = array->allocated ? 2 * array->allocated : 1; + } else { + array->allocated = min_size; + } + + array->data = Realloc2(array->data, array->allocated, array->elem_size); +} + +void * +ARR_GetNewElement(ARR_Instance array) +{ + array->used++; + realloc_array(array, array->used); + return ARR_GetElement(array, array->used - 1); +} + +void * +ARR_GetElement(ARR_Instance array, unsigned int index) +{ + assert(index < array->used); + return (void *)((char *)array->data + (size_t)index * array->elem_size); +} + +void * +ARR_GetElements(ARR_Instance array) +{ + /* Return a non-NULL pointer when the array has zero size */ + if (!array->data) { + assert(!array->used); + return array; + } + + return array->data; +} + +void +ARR_AppendElement(ARR_Instance array, void *element) +{ + void *e; + + e = ARR_GetNewElement(array); + memcpy(e, element, array->elem_size); +} + +void +ARR_RemoveElement(ARR_Instance array, unsigned int index) +{ + void *e, *l; + + e = ARR_GetElement(array, index); + l = ARR_GetElement(array, array->used - 1); + + if (e < l) + memmove(e, (char *)e + array->elem_size, (char *)l - (char *)e); + array->used--; + + realloc_array(array, array->used); +} + +void +ARR_SetSize(ARR_Instance array, unsigned int size) +{ + realloc_array(array, size); + array->used = size; +} + +unsigned int +ARR_GetSize(ARR_Instance array) +{ + return array->used; +} diff --git a/array.h b/array.h new file mode 100644 index 0000000..f4fbddb --- /dev/null +++ b/array.h @@ -0,0 +1,59 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2014 + * + * 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. + * + ********************************************************************** + + ======================================================================= + + Header file for array functions. + */ + +#ifndef GOT_ARRAY_H +#define GOT_ARRAY_H + +typedef struct ARR_Instance_Record *ARR_Instance; + +/* Create a new array with given element size */ +extern ARR_Instance ARR_CreateInstance(unsigned int elem_size); + +/* Destroy the array */ +extern void ARR_DestroyInstance(ARR_Instance array); + +/* Return pointer to a new element added to the end of the array */ +extern void *ARR_GetNewElement(ARR_Instance array); + +/* Return element with given index */ +extern void *ARR_GetElement(ARR_Instance array, unsigned int index); + +/* Return pointer to the internal array of elements */ +extern void *ARR_GetElements(ARR_Instance array); + +/* Add a new element to the end of the array */ +extern void ARR_AppendElement(ARR_Instance array, void *element); + +/* Remove element with given index */ +extern void ARR_RemoveElement(ARR_Instance array, unsigned int index); + +/* Set the size of the array */ +extern void ARR_SetSize(ARR_Instance array, unsigned int size); + +/* Return current size of the array */ +extern unsigned int ARR_GetSize(ARR_Instance array); + +#endif diff --git a/candm.h b/candm.h new file mode 100644 index 0000000..401c015 --- /dev/null +++ b/candm.h @@ -0,0 +1,869 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 1997-2003 + * + * 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. + * + ********************************************************************** + + ======================================================================= + + Definitions for the network protocol used for command and monitoring + of the timeserver. + + */ + +#ifndef GOT_CANDM_H +#define GOT_CANDM_H + +#include "sysincl.h" +#include "addressing.h" + +/* This is the default port to use for CANDM, if no alternative is + defined */ +#define DEFAULT_CANDM_PORT 323 + +/* Request codes */ +#define REQ_NULL 0 +#define REQ_ONLINE 1 +#define REQ_OFFLINE 2 +#define REQ_BURST 3 +#define REQ_MODIFY_MINPOLL 4 +#define REQ_MODIFY_MAXPOLL 5 +#define REQ_DUMP 6 +#define REQ_MODIFY_MAXDELAY 7 +#define REQ_MODIFY_MAXDELAYRATIO 8 +#define REQ_MODIFY_MAXUPDATESKEW 9 +#define REQ_LOGON 10 +#define REQ_SETTIME 11 +#define REQ_LOCAL 12 +#define REQ_MANUAL 13 +#define REQ_N_SOURCES 14 +#define REQ_SOURCE_DATA 15 +#define REQ_REKEY 16 +#define REQ_ALLOW 17 +#define REQ_ALLOWALL 18 +#define REQ_DENY 19 +#define REQ_DENYALL 20 +#define REQ_CMDALLOW 21 +#define REQ_CMDALLOWALL 22 +#define REQ_CMDDENY 23 +#define REQ_CMDDENYALL 24 +#define REQ_ACCHECK 25 +#define REQ_CMDACCHECK 26 +#define REQ_ADD_SERVER 27 +#define REQ_ADD_PEER 28 +#define REQ_DEL_SOURCE 29 +#define REQ_WRITERTC 30 +#define REQ_DFREQ 31 +#define REQ_DOFFSET 32 +#define REQ_TRACKING 33 +#define REQ_SOURCESTATS 34 +#define REQ_RTCREPORT 35 +#define REQ_TRIMRTC 36 +#define REQ_CYCLELOGS 37 +#define REQ_SUBNETS_ACCESSED 38 +#define REQ_CLIENT_ACCESSES 39 +#define REQ_CLIENT_ACCESSES_BY_INDEX 40 +#define REQ_MANUAL_LIST 41 +#define REQ_MANUAL_DELETE 42 +#define REQ_MAKESTEP 43 +#define REQ_ACTIVITY 44 +#define REQ_MODIFY_MINSTRATUM 45 +#define REQ_MODIFY_POLLTARGET 46 +#define REQ_MODIFY_MAXDELAYDEVRATIO 47 +#define REQ_RESELECT 48 +#define REQ_RESELECTDISTANCE 49 +#define REQ_MODIFY_MAKESTEP 50 +#define REQ_SMOOTHING 51 +#define REQ_SMOOTHTIME 52 +#define REQ_REFRESH 53 +#define REQ_SERVER_STATS 54 +#define REQ_CLIENT_ACCESSES_BY_INDEX2 55 +#define REQ_LOCAL2 56 +#define REQ_NTP_DATA 57 +#define REQ_ADD_SERVER2 58 +#define REQ_ADD_PEER2 59 +#define REQ_ADD_SERVER3 60 +#define REQ_ADD_PEER3 61 +#define REQ_SHUTDOWN 62 +#define REQ_ONOFFLINE 63 +#define REQ_ADD_SOURCE 64 +#define REQ_NTP_SOURCE_NAME 65 +#define REQ_RESET_SOURCES 66 +#define REQ_AUTH_DATA 67 +#define REQ_CLIENT_ACCESSES_BY_INDEX3 68 +#define REQ_SELECT_DATA 69 +#define REQ_RELOAD_SOURCES 70 +#define REQ_DOFFSET2 71 +#define REQ_MODIFY_SELECTOPTS 72 +#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 { + uint32_t tv_sec_high; + uint32_t tv_sec_low; + uint32_t tv_nsec; +} Timespec; + +/* This is used in tv_sec_high for 32-bit timestamps */ +#define TV_NOHIGHSEC 0x7fffffff + +/* Structure for 64-bit integers (not requiring 64-bit alignment) */ +typedef struct { + uint32_t high; + uint32_t low; +} Integer64; + +/* 32-bit floating-point format consisting of 7-bit signed exponent + and 25-bit signed coefficient without hidden bit. + The result is calculated as: 2^(exp - 25) * coef */ +typedef struct { + int32_t f; +} Float; + +/* The EOR (end of record) fields are used by the offsetof operator in + pktlength.c, to get the number of bytes that ought to be + transmitted for each packet type. */ + +typedef struct { + int32_t EOR; +} REQ_Null; + +typedef struct { + IPAddr mask; + IPAddr address; + int32_t EOR; +} REQ_Online; + +typedef struct { + IPAddr mask; + IPAddr address; + int32_t EOR; +} REQ_Offline; + +typedef struct { + IPAddr mask; + IPAddr address; + int32_t n_good_samples; + int32_t n_total_samples; + int32_t EOR; +} REQ_Burst; + +typedef struct { + IPAddr address; + int32_t new_minpoll; + int32_t EOR; +} REQ_Modify_Minpoll; + +typedef struct { + IPAddr address; + int32_t new_maxpoll; + int32_t EOR; +} REQ_Modify_Maxpoll; + +typedef struct { + int32_t pad; + int32_t EOR; +} REQ_Dump; + +typedef struct { + IPAddr address; + Float new_max_delay; + int32_t EOR; +} REQ_Modify_Maxdelay; + +typedef struct { + IPAddr address; + Float new_max_delay_ratio; + int32_t EOR; +} REQ_Modify_Maxdelayratio; + +typedef struct { + IPAddr address; + Float new_max_delay_dev_ratio; + int32_t EOR; +} REQ_Modify_Maxdelaydevratio; + +typedef struct { + IPAddr address; + int32_t new_min_stratum; + int32_t EOR; +} REQ_Modify_Minstratum; + +typedef struct { + IPAddr address; + int32_t new_poll_target; + int32_t EOR; +} REQ_Modify_Polltarget; + +typedef struct { + Float new_max_update_skew; + int32_t EOR; +} REQ_Modify_Maxupdateskew; + +typedef struct { + int32_t limit; + Float threshold; + int32_t EOR; +} REQ_Modify_Makestep; + +typedef struct { + Timespec ts; + int32_t EOR; +} REQ_Logon; + +typedef struct { + Timespec ts; + int32_t EOR; +} REQ_Settime; + +typedef struct { + int32_t on_off; + int32_t stratum; + Float distance; + int32_t orphan; + Float activate; + uint32_t reserved[2]; + int32_t EOR; +} REQ_Local; + +typedef struct { + int32_t option; + int32_t EOR; +} REQ_Manual; + +typedef struct { + int32_t index; + int32_t EOR; +} REQ_Source_Data; + +typedef struct { + IPAddr ip; + int32_t subnet_bits; + int32_t EOR; +} REQ_Allow_Deny; + +typedef struct { + IPAddr ip; + int32_t EOR; +} REQ_Ac_Check; + +/* Source types in NTP source requests */ +#define REQ_ADDSRC_SERVER 1 +#define REQ_ADDSRC_PEER 2 +#define REQ_ADDSRC_POOL 3 + +/* Flags used in NTP source requests */ +#define REQ_ADDSRC_ONLINE 0x1 +#define REQ_ADDSRC_AUTOOFFLINE 0x2 +#define REQ_ADDSRC_IBURST 0x4 +#define REQ_ADDSRC_PREFER 0x8 +#define REQ_ADDSRC_NOSELECT 0x10 +#define REQ_ADDSRC_TRUST 0x20 +#define REQ_ADDSRC_REQUIRE 0x40 +#define REQ_ADDSRC_INTERLEAVED 0x80 +#define REQ_ADDSRC_BURST 0x100 +#define REQ_ADDSRC_NTS 0x200 +#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; + uint8_t name[256]; + uint32_t port; + int32_t minpoll; + int32_t maxpoll; + int32_t presend_minpoll; + uint32_t min_stratum; + uint32_t poll_target; + uint32_t version; + uint32_t max_sources; + int32_t min_samples; + int32_t max_samples; + uint32_t authkey; + uint32_t nts_port; + Float max_delay; + Float max_delay_ratio; + Float max_delay_dev_ratio; + Float min_delay; + Float asymmetry; + Float offset; + uint32_t flags; + int32_t filter_length; + uint32_t cert_set; + Float max_delay_quant; + uint32_t reserved[1]; + int32_t EOR; +} REQ_NTP_Source; + +typedef struct { + IPAddr ip_addr; + int32_t EOR; +} REQ_Del_Source; + +typedef struct { + Float dfreq; + int32_t EOR; +} REQ_Dfreq; + +typedef struct { + Float doffset; + int32_t EOR; +} REQ_Doffset; + +typedef struct { + uint32_t index; + int32_t EOR; +} REQ_Sourcestats; + +/* This is based on the response size rather than the + request size */ +#define MAX_CLIENT_ACCESSES 8 + +typedef struct { + uint32_t first_index; + uint32_t n_clients; + uint32_t min_hits; + uint32_t reset; + int32_t EOR; +} REQ_ClientAccessesByIndex; + +typedef struct { + int32_t index; + int32_t EOR; +} REQ_ManualDelete; + +typedef struct { + Float distance; + int32_t EOR; +} REQ_ReselectDistance; + +#define REQ_SMOOTHTIME_RESET 0 +#define REQ_SMOOTHTIME_ACTIVATE 1 + +typedef struct { + int32_t option; + int32_t EOR; +} REQ_SmoothTime; + +typedef struct { + IPAddr ip_addr; + int32_t EOR; +} REQ_NTPData; + +typedef struct { + IPAddr ip_addr; + int32_t EOR; +} REQ_NTPSourceName; + +typedef struct { + IPAddr ip_addr; + int32_t EOR; +} REQ_AuthData; + +typedef struct { + uint32_t index; + int32_t EOR; +} REQ_SelectData; + +/* Mask and options reuse the REQ_ADDSRC flags */ +typedef struct { + IPAddr address; + uint32_t ref_id; + uint32_t mask; + uint32_t options; + 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 +#define PKT_TYPE_CMD_REPLY 2 + +/* This version number needs to be incremented whenever the packet + size and/or the format of any of the existing messages is changed. + Other changes, e.g. new command types, should be handled cleanly by + client.c and cmdmon.c anyway, so the version can stay the same. + + Version 1 : original version with fixed size packets + + Version 2 : both command and reply packet sizes made capable of + being variable length. + + Version 3 : NTP_Source message lengthened (auto_offline) + + Version 4 : IPv6 addressing added, 64-bit time values, sourcestats + and tracking reports extended, added flags to NTP source request, + trimmed source report, replaced fixed-point format with floating-point + and used also instead of integer microseconds, new commands: modify stratum, + modify polltarget, modify maxdelaydevratio, reselect, reselectdistance + + Version 5 : auth data moved to the end of the packet to allow hashes with + different sizes, extended sources, tracking and activity reports, dropped + subnets accessed and client accesses + + Version 6 : added padding to requests to prevent amplification attack, + changed maximum number of samples in manual list to 16, new commands: modify + makestep, smoothing, smoothtime + + Support for authentication was removed later in version 6 of the protocol + and commands that required authentication are allowed only locally over Unix + domain socket. + + Version 6 (no authentication) : changed format of client accesses by index + (two times), delta offset, and manual timestamp, added new fields and + flags to NTP source request and report, made length of manual list constant, + added new commands: authdata, ntpdata, onoffline, refresh, reset, + selectdata, serverstats, shutdown, sourcename + */ + +#define PROTO_VERSION_NUMBER 6 + +/* The oldest protocol versions that are compatible enough with the current + version to report a version mismatch for the server and the client */ +#define PROTO_VERSION_MISMATCH_COMPAT_SERVER 5 +#define PROTO_VERSION_MISMATCH_COMPAT_CLIENT 4 + +/* The first protocol version using padding in requests */ +#define PROTO_VERSION_PADDING 6 + +/* The maximum length of padding in request packet, currently + defined by CLIENT_ACCESSES_BY_INDEX3 */ +#define MAX_PADDING_LENGTH 484 + +/* ================================================== */ + +typedef struct { + uint8_t version; /* Protocol version */ + uint8_t pkt_type; /* What sort of packet this is */ + uint8_t res1; + uint8_t res2; + uint16_t command; /* Which command is being issued */ + uint16_t attempt; /* How many resends the client has done + (count up from zero for same sequence + number) */ + uint32_t sequence; /* Client's sequence number */ + uint32_t pad1; + uint32_t pad2; + + union { + REQ_Null null; + REQ_Online online; + REQ_Offline offline; + REQ_Burst burst; + REQ_Modify_Minpoll modify_minpoll; + REQ_Modify_Maxpoll modify_maxpoll; + REQ_Dump dump; + REQ_Modify_Maxdelay modify_maxdelay; + REQ_Modify_Maxdelayratio modify_maxdelayratio; + REQ_Modify_Maxdelaydevratio modify_maxdelaydevratio; + REQ_Modify_Minstratum modify_minstratum; + REQ_Modify_Polltarget modify_polltarget; + REQ_Modify_Maxupdateskew modify_maxupdateskew; + REQ_Modify_Makestep modify_makestep; + REQ_Logon logon; + REQ_Settime settime; + REQ_Local local; + REQ_Manual manual; + REQ_Source_Data source_data; + REQ_Allow_Deny allow_deny; + REQ_Ac_Check ac_check; + REQ_NTP_Source ntp_source; + REQ_Del_Source del_source; + REQ_Dfreq dfreq; + REQ_Doffset doffset; + REQ_Sourcestats sourcestats; + REQ_ClientAccessesByIndex client_accesses_by_index; + REQ_ManualDelete manual_delete; + REQ_ReselectDistance reselect_distance; + REQ_SmoothTime smoothtime; + REQ_NTPData ntp_data; + REQ_NTPSourceName ntp_source_name; + 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 + maximum size of the packet, there is no hole after the data field. */ + uint8_t padding[MAX_PADDING_LENGTH]; + +} CMD_Request; + +/* ================================================== */ +/* Authority codes for command types */ + +#define PERMIT_OPEN 0 +#define PERMIT_LOCAL 1 +#define PERMIT_AUTH 2 + +/* ================================================== */ + +/* Reply codes */ +#define RPY_NULL 1 +#define RPY_N_SOURCES 2 +#define RPY_SOURCE_DATA 3 +#define RPY_MANUAL_TIMESTAMP 4 +#define RPY_TRACKING 5 +#define RPY_SOURCESTATS 6 +#define RPY_RTC 7 +#define RPY_SUBNETS_ACCESSED 8 +#define RPY_CLIENT_ACCESSES 9 +#define RPY_CLIENT_ACCESSES_BY_INDEX 10 +#define RPY_MANUAL_LIST 11 +#define RPY_ACTIVITY 12 +#define RPY_SMOOTHING 13 +#define RPY_SERVER_STATS 14 +#define RPY_CLIENT_ACCESSES_BY_INDEX2 15 +#define RPY_NTP_DATA 16 +#define RPY_MANUAL_TIMESTAMP2 17 +#define RPY_MANUAL_LIST2 18 +#define RPY_NTP_SOURCE_NAME 19 +#define RPY_AUTH_DATA 20 +#define RPY_CLIENT_ACCESSES_BY_INDEX3 21 +#define RPY_SERVER_STATS2 22 +#define RPY_SELECT_DATA 23 +#define RPY_SERVER_STATS3 24 +#define RPY_SERVER_STATS4 25 +#define RPY_NTP_DATA2 26 +#define N_REPLY_TYPES 27 + +/* Status codes */ +#define STT_SUCCESS 0 +#define STT_FAILED 1 +#define STT_UNAUTH 2 +#define STT_INVALID 3 +#define STT_NOSUCHSOURCE 4 +#define STT_INVALIDTS 5 +#define STT_NOTENABLED 6 +#define STT_BADSUBNET 7 +#define STT_ACCESSALLOWED 8 +#define STT_ACCESSDENIED 9 +#define STT_NOHOSTACCESS 10 /* Deprecated */ +#define STT_SOURCEALREADYKNOWN 11 +#define STT_TOOMANYSOURCES 12 +#define STT_NORTC 13 +#define STT_BADRTCFILE 14 +#define STT_INACTIVE 15 +#define STT_BADSAMPLE 16 +#define STT_INVALIDAF 17 +#define STT_BADPKTVERSION 18 +#define STT_BADPKTLENGTH 19 +#define STT_INVALIDNAME 21 + +typedef struct { + int32_t EOR; +} RPY_Null; + +typedef struct { + uint32_t n_sources; + int32_t EOR; +} RPY_N_Sources; + +#define RPY_SD_MD_CLIENT 0 +#define RPY_SD_MD_PEER 1 +#define RPY_SD_MD_REF 2 + +#define RPY_SD_ST_SELECTED 0 +#define RPY_SD_ST_NONSELECTABLE 1 +#define RPY_SD_ST_FALSETICKER 2 +#define RPY_SD_ST_JITTERY 3 +#define RPY_SD_ST_UNSELECTED 4 +#define RPY_SD_ST_SELECTABLE 5 + +typedef struct { + IPAddr ip_addr; + int16_t poll; + uint16_t stratum; + uint16_t state; + uint16_t mode; + uint16_t flags; + uint16_t reachability; + uint32_t since_sample; + Float orig_latest_meas; + Float latest_meas; + Float latest_meas_err; + int32_t EOR; +} RPY_Source_Data; + +typedef struct { + uint32_t ref_id; + IPAddr ip_addr; + uint16_t stratum; + uint16_t leap_status; + Timespec ref_time; + Float current_correction; + Float last_offset; + Float rms_offset; + Float freq_ppm; + Float resid_freq_ppm; + Float skew_ppm; + Float root_delay; + Float root_dispersion; + Float last_update_interval; + int32_t EOR; +} RPY_Tracking; + +typedef struct { + uint32_t ref_id; + IPAddr ip_addr; + uint32_t n_samples; + uint32_t n_runs; + uint32_t span_seconds; + Float sd; + Float resid_freq_ppm; + Float skew_ppm; + Float est_offset; + Float est_offset_err; + int32_t EOR; +} RPY_Sourcestats; + +typedef struct { + Timespec ref_time; + uint16_t n_samples; + uint16_t n_runs; + uint32_t span_seconds; + Float rtc_seconds_fast; + Float rtc_gain_rate_ppm; + int32_t EOR; +} RPY_Rtc; + +typedef struct { + Float offset; + Float dfreq_ppm; + Float new_afreq_ppm; + int32_t EOR; +} RPY_ManualTimestamp; + +typedef struct { + IPAddr ip; + uint32_t ntp_hits; + uint32_t nke_hits; + uint32_t cmd_hits; + uint32_t ntp_drops; + uint32_t nke_drops; + uint32_t cmd_drops; + int8_t ntp_interval; + int8_t nke_interval; + int8_t cmd_interval; + int8_t ntp_timeout_interval; + uint32_t last_ntp_hit_ago; + uint32_t last_nke_hit_ago; + uint32_t last_cmd_hit_ago; +} RPY_ClientAccesses_Client; + +typedef struct { + uint32_t n_indices; /* how many indices there are in the server's table */ + uint32_t next_index; /* the index 1 beyond those processed on this call */ + uint32_t n_clients; /* the number of valid entries in the following array */ + RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES]; + int32_t EOR; +} RPY_ClientAccessesByIndex; + +typedef struct { + Integer64 ntp_hits; + Integer64 nke_hits; + Integer64 cmd_hits; + Integer64 ntp_drops; + Integer64 nke_drops; + Integer64 cmd_drops; + Integer64 log_drops; + Integer64 ntp_auth_hits; + Integer64 ntp_interleaved_hits; + Integer64 ntp_timestamps; + Integer64 ntp_span_seconds; + Integer64 ntp_daemon_rx_timestamps; + Integer64 ntp_daemon_tx_timestamps; + Integer64 ntp_kernel_rx_timestamps; + Integer64 ntp_kernel_tx_timestamps; + Integer64 ntp_hw_rx_timestamps; + Integer64 ntp_hw_tx_timestamps; + Integer64 reserved[4]; + int32_t EOR; +} RPY_ServerStats; + +#define MAX_MANUAL_LIST_SAMPLES 16 + +typedef struct { + Timespec when; + Float slewed_offset; + Float orig_offset; + Float residual; +} RPY_ManualListSample; + +typedef struct { + uint32_t n_samples; + RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES]; + int32_t EOR; +} RPY_ManualList; + +typedef struct { + int32_t online; + int32_t offline; + int32_t burst_online; + int32_t burst_offline; + int32_t unresolved; + int32_t EOR; +} RPY_Activity; + +#define RPY_SMT_FLAG_ACTIVE 0x1 +#define RPY_SMT_FLAG_LEAPONLY 0x2 + +typedef struct { + uint32_t flags; + Float offset; + Float freq_ppm; + Float wander_ppm; + Float last_update_ago; + Float remaining_time; + int32_t EOR; +} RPY_Smoothing; + +#define RPY_NTP_FLAGS_TESTS 0x3ff +#define RPY_NTP_FLAG_INTERLEAVED 0x4000 +#define RPY_NTP_FLAG_AUTHENTICATED 0x8000 + +typedef struct { + IPAddr remote_addr; + IPAddr local_addr; + uint16_t remote_port; + uint8_t leap; + uint8_t version; + uint8_t mode; + uint8_t stratum; + int8_t poll; + int8_t precision; + Float root_delay; + Float root_dispersion; + uint32_t ref_id; + Timespec ref_time; + Float offset; + Float peer_delay; + Float peer_dispersion; + Float response_time; + Float jitter_asymmetry; + uint16_t flags; + uint8_t tx_tss_char; + uint8_t rx_tss_char; + uint32_t total_tx_count; + 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; + uint32_t reserved[4]; + int32_t EOR; +} RPY_NTPData; + +typedef struct { + uint8_t name[256]; + int32_t EOR; +} RPY_NTPSourceName; + +#define RPY_AD_MD_NONE 0 +#define RPY_AD_MD_SYMMETRIC 1 +#define RPY_AD_MD_NTS 2 + +typedef struct { + uint16_t mode; + uint16_t key_type; + uint32_t key_id; + uint16_t key_length; + uint16_t ke_attempts; + uint32_t last_ke_ago; + uint16_t cookies; + uint16_t cookie_length; + uint16_t nak; + uint16_t pad; + int32_t EOR; +} RPY_AuthData; + +#define RPY_SD_OPTION_NOSELECT 0x1 +#define RPY_SD_OPTION_PREFER 0x2 +#define RPY_SD_OPTION_TRUST 0x4 +#define RPY_SD_OPTION_REQUIRE 0x8 + +typedef struct { + uint32_t ref_id; + IPAddr ip_addr; + uint8_t state_char; + uint8_t authentication; + uint8_t leap; + uint8_t pad; + uint16_t conf_options; + uint16_t eff_options; + uint32_t last_sample_ago; + Float score; + Float lo_limit; + Float hi_limit; + int32_t EOR; +} RPY_SelectData; + +typedef struct { + uint8_t version; + uint8_t pkt_type; + uint8_t res1; + uint8_t res2; + uint16_t command; /* Which command is being replied to */ + uint16_t reply; /* Which format of reply this is */ + uint16_t status; /* Status of command processing */ + uint16_t pad1; /* Padding for compatibility and 4 byte alignment */ + uint16_t pad2; + uint16_t pad3; + uint32_t sequence; /* Echo of client's sequence number */ + uint32_t pad4; + uint32_t pad5; + + union { + RPY_Null null; + RPY_N_Sources n_sources; + RPY_Source_Data source_data; + RPY_ManualTimestamp manual_timestamp; + RPY_Tracking tracking; + RPY_Sourcestats sourcestats; + RPY_Rtc rtc; + RPY_ClientAccessesByIndex client_accesses_by_index; + RPY_ServerStats server_stats; + RPY_ManualList manual_list; + RPY_Activity activity; + RPY_Smoothing smoothing; + RPY_NTPData ntp_data; + RPY_NTPSourceName ntp_source_name; + RPY_AuthData auth_data; + RPY_SelectData select_data; + } data; /* Reply specific parameters */ + +} CMD_Reply; + +/* ================================================== */ + +#endif /* GOT_CANDM_H */ diff --git a/client.c b/client.c new file mode 100644 index 0000000..52906d3 --- /dev/null +++ b/client.c @@ -0,0 +1,3595 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 1997-2003 + * Copyright (C) Lonnie Abelbeck 2016, 2018 + * Copyright (C) Miroslav Lichvar 2009-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. + * + ********************************************************************** + + ======================================================================= + + Command line client for configuring the daemon and obtaining status + from it whilst running. + */ + +#include "config.h" + +#include "sysincl.h" + +#include "array.h" +#include "candm.h" +#include "cmac.h" +#include "logging.h" +#include "memory.h" +#include "nameserv.h" +#include "getdate.h" +#include "cmdparse.h" +#include "pktlength.h" +#include "socket.h" +#include "util.h" + +#ifdef FEAT_READLINE +#include +#endif + +/* ================================================== */ + +struct Address { + SCK_AddressType type; + union { + IPSockAddr ip; + char *path; + } addr; +}; + +static ARR_Instance server_addresses; + +static int sock_fd = -1; + +static volatile int quit = 0; + +static int on_terminal = 0; + +static int no_dns = 0; + +static int source_names = 0; + +static int csv_mode = 0; + +static int end_dot = 0; + +/* ================================================== */ +/* Log a message. This is a minimalistic replacement of the logging.c + implementation to avoid linking with it and other modules. */ + +LOG_Severity log_min_severity = LOGS_INFO; + +void LOG_Message(LOG_Severity severity, +#if DEBUG > 0 + int line_number, const char *filename, const char *function_name, +#endif + const char *format, ...) +{ + va_list ap; + + if (severity < log_min_severity) + return; + + va_start(ap, format); + vfprintf(stderr, format, ap); + putc('\n', stderr); + va_end(ap); +} + +/* ================================================== */ +/* Read a single line of commands from standard input */ + +#ifdef FEAT_READLINE +static char **command_name_completion(const char *text, int start, int end); +#endif + +static char * +read_line(void) +{ + static char line[2048]; + static const char *prompt = "chronyc> "; + + if (on_terminal) { +#ifdef FEAT_READLINE + char *cmd; + + rl_attempted_completion_function = command_name_completion; + rl_basic_word_break_characters = " \t\n\r"; + + /* save line only if not empty */ + cmd = readline(prompt); + if( cmd == NULL ) return( NULL ); + + /* user pressed return */ + if( *cmd != '\0' ) { + strncpy(line, cmd, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; + add_history(cmd); + /* free the buffer allocated by readline */ + Free(cmd); + } else { + /* simulate the user has entered an empty line */ + *line = '\0'; + } + return( line ); +#else + printf("%s", prompt); + fflush(stdout); +#endif + } + if (fgets(line, sizeof(line), stdin)) { + return line; + } else { + return NULL; + } + +} + +/* ================================================== */ + +static ARR_Instance +get_addresses(const char *hostnames, int port) +{ + struct Address *addr; + ARR_Instance addrs; + char *hostname, *s1, *s2; + IPAddr ip_addrs[DNS_MAX_ADDRESSES]; + int i; + + addrs = ARR_CreateInstance(sizeof (*addr)); + s1 = Strdup(hostnames); + + /* Parse the comma-separated list of hostnames */ + for (hostname = s1; hostname && *hostname; hostname = s2) { + s2 = strchr(hostname, ','); + if (s2) + *s2++ = '\0'; + + /* hostname starting with / is considered a path of Unix domain socket */ + if (hostname[0] == '/') { + addr = ARR_GetNewElement(addrs); + addr->type = SCK_ADDR_UNIX; + addr->addr.path = Strdup(hostname); + } else { + if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) { + DEBUG_LOG("Could not get IP address for %s", hostname); + continue; + } + + for (i = 0; i < DNS_MAX_ADDRESSES && ip_addrs[i].family != IPADDR_UNSPEC; i++) { + addr = ARR_GetNewElement(addrs); + addr->type = SCK_ADDR_IP; + addr->addr.ip.ip_addr = ip_addrs[i]; + addr->addr.ip.port = port; + DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i])); + } + } + } + + Free(s1); + return addrs; +} + +/* ================================================== */ + +static void +free_addresses(ARR_Instance addresses) +{ + struct Address *addr; + unsigned int i; + + for (i = 0; i < ARR_GetSize(addresses); i++) { + addr = ARR_GetElement(addresses, i); + + if (addr->type == SCK_ADDR_UNIX) + Free(addr->addr.path); + } + + ARR_DestroyInstance(addresses); +} + +/* ================================================== */ +/* Initialise the socket used to talk to the daemon */ + +static int +open_socket(struct Address *addr) +{ + char *dir, *local_addr; + size_t local_addr_len; + + switch (addr->type) { + case SCK_ADDR_IP: + sock_fd = SCK_OpenUdpSocket(&addr->addr.ip, NULL, NULL, 0); + break; + case SCK_ADDR_UNIX: + /* Construct path of our socket. Use the same directory as the server + socket and include our process ID to allow multiple chronyc instances + running at the same time. */ + + dir = UTI_PathToDir(addr->addr.path); + local_addr_len = strlen(dir) + 50; + local_addr = Malloc(local_addr_len); + + snprintf(local_addr, local_addr_len, "%s/chronyc.%d.sock", dir, (int)getpid()); + + sock_fd = SCK_OpenUnixDatagramSocket(addr->addr.path, local_addr, + SCK_FLAG_ALL_PERMISSIONS); + Free(dir); + Free(local_addr); + + break; + default: + assert(0); + } + + if (sock_fd < 0) + return 0; + + return 1; +} + +/* ================================================== */ + +static void +close_io(void) +{ + if (sock_fd < 0) + return; + + SCK_RemoveSocket(sock_fd); + SCK_CloseSocket(sock_fd); + sock_fd = -1; +} + +/* ================================================== */ + +static int +open_io(void) +{ + static unsigned int address_index = 0; + struct Address *addr; + + /* If a socket is already opened, close it and try the next address */ + if (sock_fd >= 0) { + close_io(); + address_index++; + } + + /* Find an address for which a socket can be opened and connected */ + for (; address_index < ARR_GetSize(server_addresses); address_index++) { + addr = ARR_GetElement(server_addresses, address_index); + + if (open_socket(addr)) + return 1; + + close_io(); + } + + /* Start from the first address if called again */ + address_index = 0; + + return 0; +} + +/* ================================================== */ + +static void +bits_to_mask(int bits, int family, IPAddr *mask) +{ + int i; + + mask->family = family; + switch (family) { + case IPADDR_INET4: + if (bits > 32 || bits < 0) + bits = 32; + if (bits > 0) { + mask->addr.in4 = -1; + mask->addr.in4 <<= 32 - bits; + } else { + mask->addr.in4 = 0; + } + break; + case IPADDR_INET6: + if (bits > 128 || bits < 0) + bits = 128; + for (i = 0; i < bits / 8; i++) + mask->addr.in6[i] = 0xff; + if (i < 16) + mask->addr.in6[i++] = (0xff << (8 - bits % 8)) & 0xff; + for (; i < 16; i++) + mask->addr.in6[i] = 0x0; + break; + case IPADDR_ID: + mask->family = IPADDR_UNSPEC; + break; + default: + assert(0); + } +} + +/* ================================================== */ + +static int +parse_source_address(char *word, IPAddr *address) +{ + if (UTI_StringToIdIP(word, address)) + return 1; + + if (DNS_Name2IPAddress(word, address, 1) == DNS_Success) + return 1; + + return 0; +} + +/* ================================================== */ + +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) +{ + unsigned int bits; + char *p, *q; + + p = line; + if (!*p) { + mask->family = address->family = IPADDR_UNSPEC; + return 1; + } else { + q = strchr(p, '/'); + if (q) { + *q++ = 0; + if (UTI_StringToIP(p, mask)) { + p = q; + if (UTI_StringToIP(p, address)) { + if (address->family == mask->family) + return 1; + } else if (sscanf(p, "%u", &bits) == 1) { + *address = *mask; + bits_to_mask(bits, address->family, mask); + return 1; + } + } + } else { + if (parse_source_address(p, address)) { + bits_to_mask(-1, address->family, mask); + return 1; + } else { + LOG(LOGS_ERR, "Could not get address for hostname"); + return 0; + } + } + } + + LOG(LOGS_ERR, "Invalid syntax for mask/address"); + return 0; +} + +/* ================================================== */ + +static int +process_cmd_offline(CMD_Request *msg, char *line) +{ + IPAddr mask, address; + int ok; + + if (read_mask_address(line, &mask, &address)) { + UTI_IPHostToNetwork(&mask, &msg->data.offline.mask); + UTI_IPHostToNetwork(&address, &msg->data.offline.address); + msg->command = htons(REQ_OFFLINE); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + + +static int +process_cmd_online(CMD_Request *msg, char *line) +{ + IPAddr mask, address; + int ok; + + if (read_mask_address(line, &mask, &address)) { + UTI_IPHostToNetwork(&mask, &msg->data.online.mask); + UTI_IPHostToNetwork(&address, &msg->data.online.address); + msg->command = htons(REQ_ONLINE); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static void +process_cmd_onoffline(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_ONOFFLINE); +} + +/* ================================================== */ + +static int +read_address_integer(char *line, IPAddr *address, int *value) +{ + char *hostname; + int ok = 0; + + hostname = line; + line = CPS_SplitWord(line); + + if (sscanf(line, "%d", value) != 1) { + LOG(LOGS_ERR, "Invalid syntax for address value"); + ok = 0; + } else { + if (!parse_source_address(hostname, address)) { + LOG(LOGS_ERR, "Could not get address for hostname"); + ok = 0; + } else { + ok = 1; + } + } + + return ok; + +} + + +/* ================================================== */ + +static int +read_address_double(char *line, IPAddr *address, double *value) +{ + char *hostname; + int ok = 0; + + hostname = line; + line = CPS_SplitWord(line); + + if (sscanf(line, "%lf", value) != 1) { + LOG(LOGS_ERR, "Invalid syntax for address value"); + ok = 0; + } else { + if (!parse_source_address(hostname, address)) { + LOG(LOGS_ERR, "Could not get address for hostname"); + ok = 0; + } else { + ok = 1; + } + } + + return ok; + +} + + +/* ================================================== */ + +static int +process_cmd_minpoll(CMD_Request *msg, char *line) +{ + IPAddr address; + int minpoll; + int ok; + + if (read_address_integer(line, &address, &minpoll)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_minpoll.address); + msg->data.modify_minpoll.new_minpoll = htonl(minpoll); + msg->command = htons(REQ_MODIFY_MINPOLL); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_maxpoll(CMD_Request *msg, char *line) +{ + IPAddr address; + int maxpoll; + int ok; + + if (read_address_integer(line, &address, &maxpoll)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_maxpoll.address); + msg->data.modify_maxpoll.new_maxpoll = htonl(maxpoll); + msg->command = htons(REQ_MODIFY_MAXPOLL); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_maxdelay(CMD_Request *msg, char *line) +{ + IPAddr address; + double max_delay; + int ok; + + if (read_address_double(line, &address, &max_delay)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address); + msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay); + msg->command = htons(REQ_MODIFY_MAXDELAY); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_maxdelaydevratio(CMD_Request *msg, char *line) +{ + IPAddr address; + double max_delay_dev_ratio; + int ok; + + if (read_address_double(line, &address, &max_delay_dev_ratio)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelaydevratio.address); + msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_dev_ratio); + msg->command = htons(REQ_MODIFY_MAXDELAYDEVRATIO); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_maxdelayratio(CMD_Request *msg, char *line) +{ + IPAddr address; + double max_delay_ratio; + int ok; + + if (read_address_double(line, &address, &max_delay_ratio)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address); + msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio); + msg->command = htons(REQ_MODIFY_MAXDELAYRATIO); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_minstratum(CMD_Request *msg, char *line) +{ + IPAddr address; + int min_stratum; + int ok; + + if (read_address_integer(line, &address, &min_stratum)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_minstratum.address); + msg->data.modify_minstratum.new_min_stratum = htonl(min_stratum); + msg->command = htons(REQ_MODIFY_MINSTRATUM); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_polltarget(CMD_Request *msg, char *line) +{ + IPAddr address; + int poll_target; + int ok; + + if (read_address_integer(line, &address, &poll_target)) { + UTI_IPHostToNetwork(&address, &msg->data.modify_polltarget.address); + msg->data.modify_polltarget.new_poll_target = htonl(poll_target); + msg->command = htons(REQ_MODIFY_POLLTARGET); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static int +process_cmd_maxupdateskew(CMD_Request *msg, char *line) +{ + int ok; + double new_max_update_skew; + + if (sscanf(line, "%lf", &new_max_update_skew) == 1) { + msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew); + msg->command = htons(REQ_MODIFY_MAXUPDATESKEW); + ok = 1; + } else { + ok = 0; + } + + return ok; + +} + +/* ================================================== */ + +static void +process_cmd_dump(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_DUMP); + msg->data.dump.pad = htonl(0); +} + +/* ================================================== */ + +static void +process_cmd_writertc(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_WRITERTC); +} + +/* ================================================== */ + +static void +process_cmd_trimrtc(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_TRIMRTC); +} + +/* ================================================== */ + +static void +process_cmd_cyclelogs(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_CYCLELOGS); +} + +/* ================================================== */ + +static int +process_cmd_burst(CMD_Request *msg, char *line) +{ + int n_good_samples, n_total_samples; + char *s1, *s2; + IPAddr address, mask; + + s1 = line; + s2 = CPS_SplitWord(s1); + CPS_SplitWord(s2); + + if (sscanf(s1, "%d/%d", &n_good_samples, &n_total_samples) != 2) { + LOG(LOGS_ERR, "Invalid syntax for burst command"); + return 0; + } + + mask.family = address.family = IPADDR_UNSPEC; + if (*s2 && !read_mask_address(s2, &mask, &address)) { + return 0; + } + + msg->command = htons(REQ_BURST); + msg->data.burst.n_good_samples = ntohl(n_good_samples); + msg->data.burst.n_total_samples = ntohl(n_total_samples); + + UTI_IPHostToNetwork(&mask, &msg->data.burst.mask); + UTI_IPHostToNetwork(&address, &msg->data.burst.address); + + return 1; +} + +/* ================================================== */ + +static int +process_cmd_local(CMD_Request *msg, char *line) +{ + int on_off, stratum = 0, orphan = 0; + double distance = 0.0, activate = 0.0; + + if (!strcmp(line, "off")) { + on_off = 0; + } 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_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; +} + +/* ================================================== */ + +static int +process_cmd_manual(CMD_Request *msg, const char *line) +{ + const char *p; + + p = line; + + if (!strcmp(p, "off")) { + msg->data.manual.option = htonl(0); + } else if (!strcmp(p, "on")) { + msg->data.manual.option = htonl(1); + } else if (!strcmp(p, "reset")) { + msg->data.manual.option = htonl(2); + } else { + LOG(LOGS_ERR, "Invalid syntax for manual command"); + return 0; + } + msg->command = htons(REQ_MANUAL); + + return 1; +} + +/* ================================================== */ + +static int +process_cmd_allowdeny(CMD_Request *msg, char *line, int cmd, int allcmd) +{ + int all, subnet_bits; + IPAddr ip; + + if (!CPS_ParseAllowDeny(line, &all, &ip, &subnet_bits)) { + LOG(LOGS_ERR, "Could not read address"); + return 0; + } + + msg->command = htons(all ? allcmd : cmd); + UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip); + msg->data.allow_deny.subnet_bits = htonl(subnet_bits); + + return 1; +} + +/* ================================================== */ + +static int +process_cmd_accheck(CMD_Request *msg, char *line) +{ + IPAddr ip; + msg->command = htons(REQ_ACCHECK); + if (DNS_Name2IPAddress(line, &ip, 1) == DNS_Success) { + UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip); + return 1; + } else { + LOG(LOGS_ERR, "Could not read address"); + return 0; + } +} + +/* ================================================== */ + +static int +process_cmd_cmdaccheck(CMD_Request *msg, char *line) +{ + IPAddr ip; + msg->command = htons(REQ_CMDACCHECK); + if (DNS_Name2IPAddress(line, &ip, 1) == DNS_Success) { + UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip); + return 1; + } else { + LOG(LOGS_ERR, "Could not read address"); + return 0; + } +} + +/* ================================================== */ + +static int +process_cmd_dfreq(CMD_Request *msg, char *line) +{ + double dfreq; + + msg->command = htons(REQ_DFREQ); + + if (sscanf(line, "%lf", &dfreq) != 1) { + LOG(LOGS_ERR, "Invalid value"); + return 0; + } + + msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq); + return 1; +} + +/* ================================================== */ + +static int +process_cmd_doffset(CMD_Request *msg, char *line) +{ + double doffset; + + msg->command = htons(REQ_DOFFSET2); + + if (sscanf(line, "%lf", &doffset) != 1) { + LOG(LOGS_ERR, "Invalid value"); + return 0; + } + + msg->data.doffset.doffset = UTI_FloatHostToNetwork(doffset); + return 1; +} + +/* ================================================== */ + +static int +convert_addsrc_sel_options(int options) +{ + return (options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) | + (options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) | + (options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) | + (options & SRC_SELECT_REQUIRE ? REQ_ADDSRC_REQUIRE : 0); +} + +/* ================================================== */ + +static int +process_cmd_add_source(CMD_Request *msg, char *line) +{ + CPS_NTP_Source data; + IPAddr ip_addr; + int result = 0, status, type; + const char *opt_name, *word; + + msg->command = htons(REQ_ADD_SOURCE); + + word = line; + line = CPS_SplitWord(line); + + if (!strcasecmp(word, "server")) { + type = REQ_ADDSRC_SERVER; + } else if (!strcasecmp(word, "peer")) { + type = REQ_ADDSRC_PEER; + } else if (!strcasecmp(word, "pool")) { + type = REQ_ADDSRC_POOL; + } else { + LOG(LOGS_ERR, "Invalid syntax for add command"); + return 0; + } + + status = CPS_ParseNTPSourceAdd(line, &data); + switch (status) { + case 0: + LOG(LOGS_ERR, "Invalid syntax for add command"); + break; + default: + /* Verify that the address is resolvable (chronyc and chronyd are + assumed to be running on the same host) */ + if (strlen(data.name) >= sizeof (msg->data.ntp_source.name) || + DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) { + LOG(LOGS_ERR, "Invalid host/IP address"); + break; + } + + opt_name = NULL; + if (opt_name) { + LOG(LOGS_ERR, "%s can't be set in chronyc", opt_name); + break; + } + + msg->data.ntp_source.type = htonl(type); + if (strlen(data.name) >= sizeof (msg->data.ntp_source.name)) + assert(0); + strncpy((char *)msg->data.ntp_source.name, data.name, + sizeof (msg->data.ntp_source.name)); + msg->data.ntp_source.port = htonl(data.port); + msg->data.ntp_source.minpoll = htonl(data.params.minpoll); + msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll); + msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll); + msg->data.ntp_source.min_stratum = htonl(data.params.min_stratum); + msg->data.ntp_source.poll_target = htonl(data.params.poll_target); + msg->data.ntp_source.version = htonl(data.params.version); + msg->data.ntp_source.max_sources = htonl(data.params.max_sources); + msg->data.ntp_source.min_samples = htonl(data.params.min_samples); + msg->data.ntp_source.max_samples = htonl(data.params.max_samples); + msg->data.ntp_source.authkey = htonl(data.params.authkey); + msg->data.ntp_source.nts_port = htonl(data.params.nts_port); + msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay); + msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio); + msg->data.ntp_source.max_delay_dev_ratio = + UTI_FloatHostToNetwork(data.params.max_delay_dev_ratio); + msg->data.ntp_source.min_delay = UTI_FloatHostToNetwork(data.params.min_delay); + msg->data.ntp_source.asymmetry = UTI_FloatHostToNetwork(data.params.asymmetry); + msg->data.ntp_source.offset = UTI_FloatHostToNetwork(data.params.offset); + msg->data.ntp_source.flags = htonl( + (data.params.connectivity == SRC_ONLINE ? REQ_ADDSRC_ONLINE : 0) | + (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0) | + (data.params.iburst ? REQ_ADDSRC_IBURST : 0) | + (data.params.interleaved ? REQ_ADDSRC_INTERLEAVED : 0) | + (data.params.burst ? REQ_ADDSRC_BURST : 0) | + (data.params.nts ? REQ_ADDSRC_NTS : 0) | + (data.params.copy ? REQ_ADDSRC_COPY : 0) | + (data.params.ext_fields & NTP_EF_FLAG_EXP_MONO_ROOT ? + 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); + msg->data.ntp_source.max_delay_quant = + UTI_FloatHostToNetwork(data.params.max_delay_quant); + memset(msg->data.ntp_source.reserved, 0, sizeof (msg->data.ntp_source.reserved)); + + result = 1; + + break; + } + + return result; +} + +/* ================================================== */ + +static int +process_cmd_delete(CMD_Request *msg, char *line) +{ + char *hostname; + int ok = 0; + IPAddr address; + + msg->command = htons(REQ_DEL_SOURCE); + hostname = line; + CPS_SplitWord(line); + + if (!*hostname) { + LOG(LOGS_ERR, "Invalid syntax for address"); + ok = 0; + } else { + if (!parse_source_address(hostname, &address)) { + LOG(LOGS_ERR, "Could not get address for hostname"); + ok = 0; + } else { + UTI_IPHostToNetwork(&address, &msg->data.del_source.ip_addr); + ok = 1; + } + } + + return ok; + +} + +/* ================================================== */ + +static void +give_help(void) +{ + int line, len; + const char *s, cols[] = + "System clock:\0\0" + "tracking\0Display system time information\0" + "makestep\0Correct clock by stepping immediately\0" + "makestep \0Configure automatic clock stepping\0" + "maxupdateskew \0Modify maximum valid skew to update frequency\0" + "waitsync [ [ [ []]]]\0" + "Wait until synchronised in specified limits\0" + "\0\0" + "Time sources:\0\0" + "sources [-a] [-v]\0Display information about current sources\0" + "sourcestats [-a] [-v]\0Display statistics about collected measurements\0" + "selectdata [-a] [-v]\0Display information about source selection\0" + "selectopts <+|-options>\0Modify selection options\0" + "reselect\0Force reselecting synchronisation source\0" + "reselectdist \0Modify reselection distance\0" + "offset \0Modify offset correction\0" + "\0\0" + "NTP sources:\0\0" + "activity\0Check how many NTP sources are online/offline\0" + "authdata [-a] [-v]\0Display information about authentication\0" + "ntpdata [
]\0Display information about last valid measurement\0" + "add server [options]\0Add new NTP server\0" + "add pool [options]\0Add new pool of NTP servers\0" + "add peer [options]\0Add new NTP peer\0" + "delete
\0Remove server or peer\0" + "burst / [[/]
]\0Start rapid set of measurements\0" + "maxdelay
\0Modify maximum valid sample delay\0" + "maxdelayratio
\0Modify maximum valid delay/minimum ratio\0" + "maxdelaydevratio
\0Modify maximum valid delay/deviation ratio\0" + "minpoll
\0Modify minimum polling interval\0" + "maxpoll
\0Modify maximum polling interval\0" + "minstratum
\0Modify minimum stratum\0" + "offline [[/]
]\0Set sources in subnet to offline status\0" + "online [[/]
]\0Set sources in subnet to online status\0" + "onoffline\0Set all sources to online or offline status\0" + "\0according to network configuration\0" + "polltarget
\0Modify poll target\0" + "refresh\0Refresh IP addresses\0" + "reload sources\0Re-read *.sources files\0" + "sourcename
\0Display original name\0" + "\0\0" + "Manual time input:\0\0" + "manual off|on|reset\0Disable/enable/reset settime command\0" + "manual list\0Show previous settime entries\0" + "manual delete \0Delete previous settime entry\0" + "settime