From 96c956ad1f7dca2a974e09ed45146648d8a0eac9 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 17 2020 17:55:10 +0000 Subject: chrony-3.5 base --- 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..426b134 --- /dev/null +++ b/FAQ @@ -0,0 +1,551 @@ +Frequently Asked Questions + +Table of Contents + + o 1. chrony compared to other programs + ? 1.1. How does chrony compare to ntpd? + 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 from an NTP client? + ? 2.3. I have several computers on a LAN. Should be all 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 improve the accuracy of the system clock with NTP + sources? + ? 2.7. Does chronyd have an ntpdate mode? + ? 2.8. Can chronyd be configured to control the clock like ntpd? + ? 2.9. 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 chronyd allowed to step the system clock? + ? 3.4. Using a Windows NTP server? + ? 3.5. 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. Why does chronyc tracking always print an IPv4 address as + reference ID? + ? 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. I want to use chronyd's RTC support. Must I disable hwclock? + ? 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. 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? + o 7. Operating systems + ? 7.1. Does chrony support Windows? + ? 7.2. Are there any plans to support Windows? + +1. chrony compared to other programs + +1.1. How does chrony compare to ntpd? + +chronyd was designed to work well in a wide range of conditions and it can +usually synchronise the system clock faster and with better time accuracy. It +doesn't 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's a virtual machine), or you want to use NTP +on an isolated network with no hardware reference clocks in sight, chrony will +probably work much better for you. + +For a more detailed comparison of features and performance, see the comparison +page on the chrony website. + +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 +can be used for names that resolve to multiple addresses. For good reliability +the client should have at least three servers. The iburst option speeds 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's 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 want 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 from an NTP client? + +You need to add an allow directive to the chrony.conf file in order to open the +NTP port and allow chronyd to reply to client requests. allow with no specified +subnet allows access from all IPv4 and IPv6 addresses. + +2.3. I have several computers on a LAN. Should be all clients of an external +server? + +The best configuration is usually 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. Starting from version 1.25, 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 don't need to serve time to NTP clients or peers, you can add port 0 to +the chrony.conf file to completely disable the NTP server functionality and +prevent NTP requests from reaching chronyd. Starting from version 2.0, the NTP +server port is open only when client access is allowed by the allow directive +or command, an NTP peer is configured, or the broadcast directive is used. + +If you don't need to use chronyc remotely, you can add the following directives +to the configuration file to bind the command sockets to the loopback +interface. This is done by default since version 2.0. + +bindcmdaddress 127.0.0.1 +bindcmdaddress ::1 + +If you don't need to use chronyc at all or you need to run chronyc only under +the root or chrony user (which can access chronyd through a Unix domain socket +since version 2.2), you can disable the internet command sockets completely 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's compromised. It's recommended to +enable the filter only when it's 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 may 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 improve the accuracy of the system clock with NTP sources? + +Select NTP servers that are well synchronised, stable and close to your +network. It's 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 in the chrony.conf file. It should +make local receive and transmit timestamps of NTP packets much more accurate. + +There are also useful options which can be set in the server directive, they +are minpoll, maxpoll, polltarget, maxdelay, maxdelayratio, maxdelaydevratio, +and xleave. + +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 may 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 may work better. + +An example of the directive for an NTP server on the Internet that you are +allowed to poll frequently could be + +server foo.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 unusally 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 in order to allow the +server to send the client 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 may 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. + +If it is acceptable for NTP clients in the network to send requests at an +excessive rate, a sub-second polling interval may 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 + +2.7. 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 don't want to use a configuration file, NTP servers can be specified on the +command line. For example: + +# chronyd -q 'pool pool.ntp.org iburst' + +2.8. 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. + +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 may cause the offsets in the tracking and +sourcestats reports/logs to be significantly smaller than the actual offsets +and be unsuitable for monitoring. + +2.9. 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's 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 packets +may be blocked. Try using a tool like wireshark or tcpdump to see if you're +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: + +210 Number of sources = 3 +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +^* foo.example.net 2 6 377 34 +484us[ -157us] +/- 30ms +^- bar.example.net 2 6 377 34 +33ms[ +32ms] +/- 47ms +^+ baz.example.net 3 6 377 35 -1397us[-2033us] +/- 60ms + +3.2. Are NTP servers specified with the offline option? + +Check that you're using chronyc's online and offline commands appropriately. +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 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's 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 may be +necessary to allow the step on any clock update. The example above would change +to + +makestep 1 -1 + +3.4. 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 may 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.5. 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.2 seconds 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 +foo.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 0.2 seconds, 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 isn't +necessary for localhost. + +Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, ps +-auxw) to see if it's running. Or try netstat -a and see if the ports 123/udp +and 323/udp are listening. If chronyd is not running, you may 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 port 323/ +udp. You need to amend the firewall configuration in this case. + +4.2. I keep getting the error 501 Not authorised + +Since version 2.2, the password command doesn't do anything and chronyc needs +to run locally under the root or chrony user, which are allowed to access the +chronyd's Unix domain command socket. + +With older versions, you need to authenticate with the password command first +or use the -a option to authenticate automatically on start. The configuration +file needs to specify a file which contains keys (keyfile directive) and which +key in the key file should be used for chronyc authentication (commandkey +directive). + +4.3. Why does chronyc tracking always print an IPv4 address as reference ID? + +The reference ID is a 32-bit value and in versions before 3.0 it was printed in +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). + +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 doesn't 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 won't 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's 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. I want to use chronyd's RTC support. Must I disable hwclock? + +The hwclock program is often set-up by default in the boot and shutdown scripts +with many 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's important to disable hwclock in the shutdown procedure. If you +don't, it will over-write 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 may be using the device. + +5.5. 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 the mode may be useful to 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's not supported in chronyd, 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 may be acceptable +to keep all sources online all the time. + +7. Operating systems + +7.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. + +7.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 2019-05-10 12:22:57 CEST diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..98bab69 --- /dev/null +++ b/INSTALL @@ -0,0 +1,195 @@ +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. + +The following programs and libraries with their development files are needed to +build chrony: + + o C compiler (gcc or clang recommended) + + o GNU Make + + o Nettle, NSS, or LibTomCrypt (optional) + + o Editline (optional) + + o libcap (Linux only, optional) + + o libseccomp (Linux only, optional) + + o timepps.h header (optional) + + o Asciidoctor (for HTML documentation) + + o Bash (for testing) + +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 or readline 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. + +Support for line editing libraries + +chronyc can be built with support for line editing, this allows you to use the +cursor keys to replay and edit old commands. Two libraries are supported which +provide such functionality, editline and GNU readline. + +Please note that readline since version 6.0 is licensed under GPLv3+ which is +incompatible with chrony's license GPLv2. You should use editline instead if +you don't want to use older readline versions. + +The configure script will automatically enable the line editing support if one +of the supported libraries is available. If they are both available, the +editline library will be used. + +If you don't want to use it (in which case chronyc will use a minimal command +line interface), invoke configure like this: + +./configure --disable-readline other-options... + +If you have editline, readline or ncurses installed in locations that aren't +normally searched by the compiler and linker, you need to use extra options: + +--with-readline-includes=directory_name + + This defines the name of the directory above the one where readline.h is. + readline.h is assumed to be in editline or readline subdirectory of the + named directory. + +--with-readline-library=directory_name + + This defines the directory containing the libedit.a or libedit.so file, or + libreadline.a or libreadline.so file. + +--with-ncurses-library=directory_name + + This defines the directory containing the libncurses.a or libncurses.so + file. + +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 2019-05-10 12:22:57 CEST diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..8e68ef4 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,138 @@ +################################################## +# +# 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@ + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ + +DESTDIR= + +HASH_OBJ = @HASH_OBJ@ + +OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \ + reference.o regress.o rtc.o samplefilt.o sched.o sources.o sourcestats.o stubs.o \ + smooth.o sys.o sys_null.o tempcomp.o util.o $(HASH_OBJ) + +EXTRA_OBJS=@EXTRA_OBJECTS@ + +CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \ + pktlength.o util.o $(HASH_OBJ) + +ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS) + +LDFLAGS = @LDFLAGS@ +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) $(EXTRA_OBJS) + $(CC) $(CFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) + +chronyc : $(CLI_OBJS) + $(CC) $(CFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_CLI_LIBS) + +distclean : clean + $(MAKE) -C doc distclean + $(MAKE) -C test/unit distclean + -rm -f .DS_Store + -rm -f Makefile config.h config.log + +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) $(EXTRA_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 $@ + +-include $(ALL_OBJS:%.o=.deps/%.d) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3413361 --- /dev/null +++ b/NEWS @@ -0,0 +1,855 @@ +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..a492446 --- /dev/null +++ b/README @@ -0,0 +1,164 @@ +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 continuosly, or run on a virtual machine. + +Typical accuracy between two machines synchronised over the Internet is +within a few milliseconds; on a LAN, accuracy is typically in tens of +microseconds. With hardware timestamping, or a hardware reference clock, +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 +Solaris. Closely related systems may work too. Any other system will +likely require a porting exercise. You would need to start from one +of the existing system-specific drivers and look into the quirks of +certain system calls and the kernel on your target system. + +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.tuxfamily.org/ + +Where are new versions announced? +================================= + +There is a low volume mailing list where new versions and other +important news relating to chrony is announced. You can join this list +by sending mail with the subject "subscribe" to + +chrony-announce-request@chrony.tuxfamily.org + +These messages will be copied to chrony-users (see below). + +How can I get support for chrony? +and where can I discuss new features, possible bugs etc? +======================================================== + +There are 3 mailing lists relating to chrony. chrony-announce was +mentioned above. chrony-users is a users' discussion list, e.g. for +general questions and answers about using chrony. chrony-dev is a more +technical list, e.g. for discussing how new features should be +implemented, exchange of information between developers etc. To +subscribe to either of these lists, send a message with the subject +"subscribe" to + +chrony-users-request@chrony.tuxfamily.org +or +chrony-dev-request@chrony.tuxfamily.org + +as applicable. + +When you are reporting a bug, please send us all the information you can. +Unfortunately, chrony has proven to be one of those programs where it is very +difficult to reproduce bugs in a different environment. So we may have to +interact with you quite a lot to obtain enough extra logging and tracing to +pin-point the problem in some cases. Please be patient and plan for this! + +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 RFC 1305 +and RFC 5905, written by David Mills. The source code of the NTP reference +implementation has been used to check the details of the protocol. + +The following people have provided patches and other major contributions +to the program : + +Lonnie Abelbeck +Benny Lyne Amorsen +Andrew Bishop +Vincent Blut +Stephan I. Boettcher +Goswin Brederlow +Leigh Brown +Erik Bryer +Jonathan Cameron +Bryan Christianson +Juliusz Chroboczek +Christian Ehrhardt +Paul Elliott +Stefan R. Filipek +Mike Fleetwood +Alexander Gretencord +Andrew Griffiths +Walter Haidinger +Juergen Hannken-Illjes +John Hasler +Tjalling Hattink +Liam Hatton +Jachym Holecek +HÃ¥kan Johansson +Jim Knoble +Antti Jrvinen +Eric Lammerts +Stefan Lucke +Victor Lum +Kevin Lyda +Paul Menzel +Vladimir Michl +Victor Moroz +Kalle Olavi Niemitalo +Frank Otto +Denny Page +Chris Perl +Gautier PHILIPPON +Andreas Piesk +Andreas Steinmetz +NAKAMURA Takumi +Timo Teras +Bill Unruh +Stephen Wadeley +Bernhard Weiss +Wolfgang Weisselberg +Bernhard M. Wiedemann +Joachim Wiedorn +Ralf Wildenhues +Ulrich Windl +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..9ecc18b --- /dev/null +++ b/addressing.h @@ -0,0 +1,62 @@ +/* + 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. + All parts are in HOST order, NOT network order. */ + +#define IPADDR_UNSPEC 0 +#define IPADDR_INET4 1 +#define IPADDR_INET6 2 + +typedef struct { + union { + uint32_t in4; + uint8_t in6[16]; + } addr; + uint16_t family; + uint16_t _pad; +} IPAddr; + +typedef struct { + IPAddr ip_addr; + unsigned short port; +} 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..dd16700 --- /dev/null +++ b/addrfilt.c @@ -0,0 +1,403 @@ +/* + 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; + } + + 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); + } + + 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..d70cff9 --- /dev/null +++ b/array.c @@ -0,0 +1,130 @@ +/* + 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_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..c812e84 --- /dev/null +++ b/array.h @@ -0,0 +1,56 @@ +/* + 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); + +/* 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..cb79739 --- /dev/null +++ b/candm.h @@ -0,0 +1,726 @@ +/* + 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 N_REQUEST_TYPES 64 + +/* 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 + +/* 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; + 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; + +/* 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 + +typedef struct { + IPAddr ip_addr; + 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; + 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 reserved[3]; + 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 { + int32_t sec; + int32_t usec; + 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; + 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; + +/* ================================================== */ + +#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 + (using new request/reply types) and manual timestamp, added new fields and + flags to NTP source request and report, made length of manual list constant, + added new commands: ntpdata, refresh, serverstats, shutdown + */ + +#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 MANUAL_LIST */ +#define MAX_PADDING_LENGTH 396 + +/* ================================================== */ + +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; + } 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 N_REPLY_TYPES 19 + +/* 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 +/* Deprecated */ +#define STT_NOHOSTACCESS 10 +#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 + +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_SYNC 0 +#define RPY_SD_ST_UNREACH 1 +#define RPY_SD_ST_FALSETICKER 2 +#define RPY_SD_ST_JITTERY 3 +#define RPY_SD_ST_CANDIDATE 4 +#define RPY_SD_ST_OUTLIER 5 + +#define RPY_SD_FLAG_NOSELECT 0x1 +#define RPY_SD_FLAG_PREFER 0x2 +#define RPY_SD_FLAG_TRUST 0x4 +#define RPY_SD_FLAG_REQUIRE 0x8 + +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 cmd_hits; + uint32_t ntp_drops; + uint32_t cmd_drops; + int8_t ntp_interval; + int8_t cmd_interval; + int8_t ntp_timeout_interval; + int8_t pad; + uint32_t last_ntp_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 { + uint32_t ntp_hits; + uint32_t cmd_hits; + uint32_t ntp_drops; + uint32_t cmd_drops; + uint32_t log_drops; + 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 reserved[4]; + int32_t EOR; +} RPY_NTPData; + +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; + } data; /* Reply specific parameters */ + +} CMD_Reply; + +/* ================================================== */ + +#endif /* GOT_CANDM_H */ diff --git a/client.c b/client.c new file mode 100644 index 0000000..8736504 --- /dev/null +++ b/client.c @@ -0,0 +1,3290 @@ +/* + 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-2018 + * + * 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 "logging.h" +#include "memory.h" +#include "nameserv.h" +#include "getdate.h" +#include "cmdparse.h" +#include "pktlength.h" +#include "util.h" + +#ifdef FEAT_READLINE +#ifdef USE_EDITLINE +#include +#else +#include +#include +#endif +#endif + +/* ================================================== */ + +union sockaddr_all { + struct sockaddr_in in4; +#ifdef FEAT_IPV6 + struct sockaddr_in6 in6; +#endif + struct sockaddr_un un; + struct sockaddr sa; +}; + +static ARR_Instance sockaddrs; + +static int sock_fd = -1; + +static int quit = 0; + +static int on_terminal = 0; + +static int no_dns = 0; + +static int csv_mode = 0; + +/* ================================================== */ +/* Log a message. This is a minimalistic replacement of the logging.c + implementation to avoid linking with it and other modules. */ + +int log_debug_enabled = 0; + +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; + + 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_sockaddrs(const char *hostnames, int port) +{ + ARR_Instance addrs; + char *hostname, *s1, *s2; + IPAddr ip_addrs[DNS_MAX_ADDRESSES]; + union sockaddr_all *addr; + int i; + + addrs = ARR_CreateInstance(sizeof (union sockaddr_all)); + 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 = (union sockaddr_all *)ARR_GetNewElement(addrs); + if (snprintf(addr->un.sun_path, sizeof (addr->un.sun_path), "%s", hostname) >= + sizeof (addr->un.sun_path)) + LOG_FATAL("Unix socket path too long"); + addr->un.sun_family = AF_UNIX; + } 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 = (union sockaddr_all *)ARR_GetNewElement(addrs); + UTI_IPAndPortToSockaddr(&ip_addrs[i], port, (struct sockaddr *)addr); + DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i])); + } + } + } + + Free(s1); + return addrs; +} + +/* ================================================== */ +/* Initialise the socket used to talk to the daemon */ + +static int +prepare_socket(union sockaddr_all *addr) +{ + socklen_t addr_len; + char *dir; + + switch (addr->sa.sa_family) { + case AF_UNIX: + addr_len = sizeof (addr->un); + break; + case AF_INET: + addr_len = sizeof (addr->in4); + break; +#ifdef FEAT_IPV6 + case AF_INET6: + addr_len = sizeof (addr->in6); + break; +#endif + default: + assert(0); + } + + sock_fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0); + + if (sock_fd < 0) { + DEBUG_LOG("Could not create socket : %s", strerror(errno)); + return 0; + } + + if (addr->sa.sa_family == AF_UNIX) { + struct sockaddr_un sa_un; + + /* 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->un.sun_path); + if (snprintf(sa_un.sun_path, sizeof (sa_un.sun_path), + "%s/chronyc.%d.sock", dir, (int)getpid()) >= sizeof (sa_un.sun_path)) + LOG_FATAL("Unix socket path too long"); + Free(dir); + + sa_un.sun_family = AF_UNIX; + unlink(sa_un.sun_path); + + /* Bind the socket to the path */ + if (bind(sock_fd, (struct sockaddr *)&sa_un, sizeof (sa_un)) < 0) { + DEBUG_LOG("Could not bind socket : %s", strerror(errno)); + return 0; + } + + /* Allow server without root privileges to send replies to our socket */ + if (chmod(sa_un.sun_path, 0666) < 0) { + DEBUG_LOG("Could not change socket permissions : %s", strerror(errno)); + return 0; + } + } + + if (connect(sock_fd, &addr->sa, addr_len) < 0) { + DEBUG_LOG("Could not connect socket : %s", strerror(errno)); + return 0; + } + + return 1; +} + +/* ================================================== */ + +static void +close_io(void) +{ + union sockaddr_all addr; + socklen_t addr_len = sizeof (addr); + + if (sock_fd < 0) + return; + + /* Remove our Unix domain socket */ + if (getsockname(sock_fd, &addr.sa, &addr_len) < 0) + LOG_FATAL("getsockname() failed : %s", strerror(errno)); + if (addr_len <= sizeof (addr) && addr_len > sizeof (addr.sa.sa_family) && + addr.sa.sa_family == AF_UNIX) + unlink(addr.un.sun_path); + + close(sock_fd); + sock_fd = -1; +} + +/* ================================================== */ + +static int +open_io(void) +{ + static unsigned int address_index = 0; + union sockaddr_all *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(sockaddrs); address_index++) { + addr = (union sockaddr_all *)ARR_GetElement(sockaddrs, address_index); + DEBUG_LOG("Opening connection to %s", UTI_SockaddrToString(&addr->sa)); + + if (prepare_socket(addr)) + return 1; + + close_io(); + } + + 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; + default: + assert(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 (DNS_Name2IPAddress(p, address, 1) == DNS_Success) { + 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 (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) { + 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 (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) { + 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; + + if (!strcmp(line, "off")) { + on_off = 0; + } else if (CPS_ParseLocal(line, &stratum, &orphan, &distance)) { + on_off = 1; + } else { + LOG(LOGS_ERR, "Invalid syntax for local command"); + return 0; + } + + msg->command = htons(REQ_LOCAL2); + 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); + + 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 +parse_allow_deny(CMD_Request *msg, char *line) +{ + unsigned long a, b, c, d; + int n, specified_subnet_bits; + IPAddr ip; + char *p; + + p = line; + if (!*p) { + /* blank line - applies to all addresses */ + ip.family = IPADDR_UNSPEC; + UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip); + msg->data.allow_deny.subnet_bits = htonl(0); + } else { + char *slashpos; + slashpos = strchr(p, '/'); + if (slashpos) *slashpos = 0; + + n = 0; + if (!UTI_StringToIP(p, &ip) && + (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) <= 0) { + + /* Try to parse as the name of a machine */ + if (slashpos || DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) { + LOG(LOGS_ERR, "Could not read address"); + return 0; + } else { + UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip); + if (ip.family == IPADDR_INET6) + msg->data.allow_deny.subnet_bits = htonl(128); + else + msg->data.allow_deny.subnet_bits = htonl(32); + } + } else { + + if (n == 0) { + if (ip.family == IPADDR_INET6) + msg->data.allow_deny.subnet_bits = htonl(128); + else + msg->data.allow_deny.subnet_bits = htonl(32); + } else { + ip.family = IPADDR_INET4; + + a &= 0xff; + b &= 0xff; + c &= 0xff; + d &= 0xff; + + switch (n) { + case 1: + ip.addr.in4 = htonl((a<<24)); + msg->data.allow_deny.subnet_bits = htonl(8); + break; + case 2: + ip.addr.in4 = htonl((a<<24) | (b<<16)); + msg->data.allow_deny.subnet_bits = htonl(16); + break; + case 3: + ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8)); + msg->data.allow_deny.subnet_bits = htonl(24); + break; + case 4: + ip.addr.in4 = htonl((a<<24) | (b<<16) | (c<<8) | d); + msg->data.allow_deny.subnet_bits = htonl(32); + break; + default: + assert(0); + } + } + + UTI_IPHostToNetwork(&ip, &msg->data.allow_deny.ip); + + if (slashpos) { + n = sscanf(slashpos+1, "%d", &specified_subnet_bits); + if (n == 1) { + msg->data.allow_deny.subnet_bits = htonl(specified_subnet_bits); + } else { + LOG(LOGS_WARN, "Warning: badly formatted subnet size, using %d", + (int)ntohl(msg->data.allow_deny.subnet_bits)); + } + } + } + } + return 1; +} + +/* ================================================== */ + +static int +process_cmd_allow(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_ALLOW); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_allowall(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_ALLOWALL); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_deny(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_DENY); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_denyall(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_DENYALL); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_cmdallow(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_CMDALLOW); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_cmdallowall(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_CMDALLOWALL); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_cmddeny(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_CMDDENY); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +process_cmd_cmddenyall(CMD_Request *msg, char *line) +{ + int status; + msg->command = htons(REQ_CMDDENYALL); + status = parse_allow_deny(msg, line); + return status; +} + +/* ================================================== */ + +static int +accheck_getaddr(char *line, IPAddr *addr) +{ + unsigned long a, b, c, d; + IPAddr ip; + char *p; + p = line; + if (!*p) { + return 0; + } else { + if (sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d) == 4) { + addr->family = IPADDR_INET4; + addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d; + return 1; + } else { + if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) { + return 0; + } else { + *addr = ip; + return 1; + } + } + } +} + +/* ================================================== */ + +static int +process_cmd_accheck(CMD_Request *msg, char *line) +{ + IPAddr ip; + msg->command = htons(REQ_ACCHECK); + if (accheck_getaddr(line, &ip)) { + 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 (accheck_getaddr(line, &ip)) { + UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip); + return 1; + } else { + LOG(LOGS_ERR, "Could not read address"); + return 0; + } +} + +/* ================================================== */ + +static void +process_cmd_dfreq(CMD_Request *msg, char *line) +{ + double dfreq; + msg->command = htons(REQ_DFREQ); + if (sscanf(line, "%lf", &dfreq) == 1) { + msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq); + } else { + msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0); + } +} + +/* ================================================== */ + +static void +cvt_to_sec_usec(double x, long *sec, long *usec) { + long s, us; + s = (long) x; + us = (long)(0.5 + 1.0e6 * (x - (double) s)); + while (us >= 1000000) { + us -= 1000000; + s += 1; + } + while (us < 0) { + us += 1000000; + s -= 1; + } + + *sec = s; + *usec = us; +} + +/* ================================================== */ + +static void +process_cmd_doffset(CMD_Request *msg, char *line) +{ + double doffset; + long sec, usec; + msg->command = htons(REQ_DOFFSET); + if (sscanf(line, "%lf", &doffset) == 1) { + cvt_to_sec_usec(doffset, &sec, &usec); + msg->data.doffset.sec = htonl(sec); + msg->data.doffset.usec = htonl(usec); + } else { + msg->data.doffset.sec = htonl(0); + msg->data.doffset.usec = htonl(0); + } +} + +/* ================================================== */ + +static int +process_cmd_add_server_or_peer(CMD_Request *msg, char *line) +{ + CPS_NTP_Source data; + IPAddr ip_addr; + int result = 0, status; + const char *opt_name; + + status = CPS_ParseNTPSourceAdd(line, &data); + switch (status) { + case 0: + LOG(LOGS_ERR, "Invalid syntax for add command"); + break; + default: + if (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.port = htonl((unsigned long) data.port); + UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr); + 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.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.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) | + (data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) | + (data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) | + (data.params.sel_options & SRC_SELECT_REQUIRE ? REQ_ADDSRC_REQUIRE : 0)); + msg->data.ntp_source.filter_length = htonl(data.params.filter_length); + memset(msg->data.ntp_source.reserved, 0, sizeof (msg->data.ntp_source.reserved)); + + result = 1; + + break; + } + + return result; +} + +/* ================================================== */ + +static int +process_cmd_add_server(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_ADD_SERVER3); + return process_cmd_add_server_or_peer(msg, line); +} + +/* ================================================== */ + +static int +process_cmd_add_peer(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_ADD_PEER3); + return process_cmd_add_server_or_peer(msg, line); +} + +/* ================================================== */ + +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 (DNS_Name2IPAddress(hostname, &address, 1) != DNS_Success) { + 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 [-v]\0Display information about current sources\0" + "sourcestats [-v]\0Display statistics about collected measurements\0" + "reselect\0Force reselecting synchronisation source\0" + "reselectdist \0Modify reselection distance\0" + "\0\0" + "NTP sources:\0\0" + "activity\0Check how many NTP sources are online/offline\0" + "ntpdata [
]\0Display information about last valid measurement\0" + "add server
[options]\0Add new NTP server\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" + "\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