Compare commits

...

112 Commits

Author SHA1 Message Date
Miroslav Lichvar
8a4313c32b Update NEWS 2009-12-15 16:07:34 +01:00
Miroslav Lichvar
b32432c232 Move estimated offset and error to sourcestats report
And print the estimated offset in sourcestats output.
2009-12-14 10:34:33 +01:00
Miroslav Lichvar
feb86e336a Check also for log and pow functions in configure 2009-12-13 15:00:13 +01:00
Miroslav Lichvar
7817bef866 Add FreeBSD-amd64 to configure 2009-12-13 15:00:13 +01:00
Miroslav Lichvar
2dd9f3373b Replace integer microseconds in reports with floating-point values 2009-12-13 15:00:10 +01:00
Miroslav Lichvar
5b1a8705cf Remove resid_freq and resid_skew from source report
They were not printed and they are also in sourcestats report.
2009-12-13 11:07:45 +01:00
Miroslav Lichvar
b49470117d Replace fixed-point format with floating-point in cmdmon protocol 2009-12-13 11:07:34 +01:00
Miroslav Lichvar
84f8463f2a Use nanoseconds in timevals in cmdmon protocol 2009-12-12 16:44:38 +01:00
Miroslav Lichvar
78f37e726a Use AI_ADDRCONFIG only when defined
This seems to be missing on NetBSD.
2009-12-10 18:37:58 +01:00
John G. Hasler
9d83369348 Edited faq.txt to match the version on the Website. 2009-12-10 07:55:02 -06:00
Miroslav Lichvar
365834535e Use exact address size in bind and sendto calls
Apparently this is needed on some systems, otherwise the calls
return EINVAL.
2009-12-07 12:51:56 +01:00
Miroslav Lichvar
63ae72e009 Use IP_PKTINFO and SO_TIMESTAMP only when defined 2009-12-07 12:39:16 +01:00
Miroslav Lichvar
4599e2b508 Fix sys_sunos compilation 2009-12-07 12:32:28 +01:00
Miroslav Lichvar
395c33208c Remove socket binding in chronyc
Randomly assigned port should work fine, no need for binding.
2009-12-07 12:31:35 +01:00
Miroslav Lichvar
ff423304ed Add missing commands to chronyc help 2009-12-05 13:46:17 +01:00
Miroslav Lichvar
00a77fca52 Add dns command to configure DNS resolving in chronyc 2009-12-05 13:25:56 +01:00
Miroslav Lichvar
49bd8cfab3 Fix request_reply() return code if no response received 2009-12-05 01:13:26 +01:00
Miroslav Lichvar
6031b35a7a Update documentation a bit more 2009-12-04 13:12:38 +01:00
Miroslav Lichvar
1f6e508a3d Set default chrony.conf path according to sysconfdir 2009-12-04 13:12:38 +01:00
Miroslav Lichvar
fb538c3947 Improve configure 2009-12-04 13:12:31 +01:00
Miroslav Lichvar
6af87bd8f6 Don't call ReadCookedTime after select timeout 2009-12-03 12:20:50 +01:00
Miroslav Lichvar
e248a57d00 Update documentation 2009-12-02 15:35:15 +01:00
Miroslav Lichvar
41580fe589 Add flags field to chronyc add source request
This will allow adding new flags without breaking compatibility.
2009-12-02 15:22:16 +01:00
Miroslav Lichvar
1c128b0076 Remove hyphen from git commands in make_release 2009-12-01 17:17:18 +01:00
Miroslav Lichvar
5a3d85b4ff Close socket in SOCK finalise 2009-12-01 16:01:31 +01:00
Miroslav Lichvar
0f9892fe7a Fix printing refclocks and IPv6 sources in statistics log 2009-11-30 17:18:28 +01:00
Miroslav Lichvar
19651dc767 Flush filter when PPS refclock lost sync 2009-11-30 17:03:04 +01:00
Miroslav Lichvar
e63c51c6c0 Mark SOCK driver as PPS capable 2009-11-30 16:54:04 +01:00
Miroslav Lichvar
d1c7e1bb6c Open rtc log after dropping root privileges 2009-11-30 16:54:04 +01:00
Miroslav Lichvar
1a8514a1a8 Swap leap signs in measurements log description 2009-11-30 16:54:04 +01:00
Miroslav Lichvar
7c53aca486 Add refclocks log 2009-11-30 16:54:00 +01:00
Miroslav Lichvar
e9ae3d0a0b Read local time immediately after select()
This removes a small inaccuracy caused by delay between select() and
file handler calls.
2009-11-30 13:27:34 +01:00
Miroslav Lichvar
159a9519e8 Clean up configure a bit 2009-11-27 16:47:20 +01:00
Miroslav Lichvar
5939fcb2eb Add editline, readline, linuxcaps detection to configure 2009-11-27 15:59:32 +01:00
Miroslav Lichvar
0601540d41 Use 644/755 permissions instead of 444/555 2009-11-27 13:21:57 +01:00
Miroslav Lichvar
b83861c7c2 Don't change file ownership in installation 2009-11-27 13:20:57 +01:00
Miroslav Lichvar
4d6156b549 Add bindir, sbindir, docdir options to configure 2009-11-27 13:12:58 +01:00
Miroslav Lichvar
7eae35e15e Regenerate getdate.c 2009-11-27 12:27:11 +01:00
Miroslav Lichvar
a94380673b Include getdate.y to allow regenerating getdate.c
Taken from GNU tar-1.13. Patched yylex and yyerror declarations to avoid
compiler warnings.
2009-11-27 12:25:36 +01:00
Miroslav Lichvar
dce9607d6e Add s390 and powerpc definitions to io_linux.h 2009-11-26 14:59:11 +01:00
Miroslav Lichvar
e3234465e2 Clean up system options code
Abort with error message when trying to use unsupported/disabled
system specific option.
2009-11-25 14:37:41 +01:00
Miroslav Lichvar
032838b1b0 Add new cmdmon status codes for packet version and length mismatch
With next procotol version this will allow chronyc to report that
chronyd is using a different protocol version.
2009-11-25 14:37:41 +01:00
Miroslav Lichvar
dd5405a281 Check SOCK protocol version 2009-11-25 14:37:41 +01:00
Miroslav Lichvar
6d242a33f5 Add PPS support to SOCK driver 2009-11-25 14:37:40 +01:00
Miroslav Lichvar
3bae6c3202 Make some socket error messages more descriptive 2009-11-25 14:37:40 +01:00
Miroslav Lichvar
618f372e13 Add option to limit clientlog memory 2009-11-25 14:37:36 +01:00
Miroslav Lichvar
8f72155b43 Multiply clientlog node table size when reallocating 2009-11-24 15:20:23 +01:00
Miroslav Lichvar
bbb6c5d422 Use NULLs in select call instead of empty sets 2009-11-23 17:24:44 +01:00
Miroslav Lichvar
62fe343990 Reduce adjtime calling
Don't call adjtime to determine remaining offset when there is no slewing
running.
2009-11-23 17:23:43 +01:00
Miroslav Lichvar
4097ab29c7 Don't read past buffer in find_ordered_entry_with_flags 2009-11-18 15:46:55 +01:00
Miroslav Lichvar
9c9530c688 Avoid blocking read in rtc_linux 2009-11-18 12:53:31 +01:00
Miroslav Lichvar
0a86a8dd0b Add spaces when catenating chronyc command line arguments 2009-11-12 16:48:09 +01:00
Miroslav Lichvar
e08870c63c Use non-zero exit code in chronyc to report errors 2009-11-12 16:43:34 +01:00
Miroslav Lichvar
6b38523c9c Improve status checking and printing in chronyc 2009-11-12 15:36:12 +01:00
Miroslav Lichvar
77e79e8359 Check in chronyc that command in reply is same as requested 2009-11-12 15:07:36 +01:00
Miroslav Lichvar
e88af337cd Don't set NTP source as reachable when reply doesn't have valid data
This fixes using uninitialized sourcestats values when selecting source.
2009-11-12 15:07:36 +01:00
Miroslav Lichvar
707b623ea8 Allow overriding system detection in configure 2009-11-12 15:07:35 +01:00
Miroslav Lichvar
9716a2ed7e Document -4 and -6 options 2009-11-09 14:35:39 +01:00
Miroslav Lichvar
fe2cfe1fae Support LDFLAGS and CPPFLAGS in configure 2009-11-04 15:46:58 +01:00
Jonathan Cameron
c6e2eaf7a9 Allow LDFLAGS to be used in linking 2009-11-04 15:37:32 +01:00
Miroslav Lichvar
a822bcfd67 Validate sample times received in refclock 2009-11-03 16:40:12 +01:00
Miroslav Lichvar
6640993f20 Don't forget to save last PPS sequence number 2009-11-03 16:36:02 +01:00
Miroslav Lichvar
f39dc68f84 Avoid compiler warnings in util.c on 32-bit archs 2009-10-30 11:13:08 +01:00
John G. Hasler
27cfc02468 Replaced references to sunsite with references to tuxfamily. 2009-10-29 16:14:39 -05:00
Miroslav Lichvar
8e23110aec Update COPYING and FSF address 2009-10-28 17:53:33 +01:00
Miroslav Lichvar
f7e08d0c30 Update copyrights 2009-10-28 17:53:10 +01:00
Miroslav Lichvar
f2f592fa0d Update documentation for refclock and IPv6 support 2009-10-28 16:53:03 +01:00
Miroslav Lichvar
465e580a39 Remove forgotten text in server directive description 2009-10-28 16:31:58 +01:00
Miroslav Lichvar
b4069a4c3b Add PPS API refclock driver 2009-10-28 12:40:39 +01:00
Miroslav Lichvar
352f03d487 Reselect source also according to distance
Reselect when a source with the same stratum is available and has
significantly better distance than the current source.
2009-10-27 14:28:19 +01:00
Miroslav Lichvar
8cd9e68246 Make default refclock refid from number of the source
It should avoid having two or more refclocks with the same refid.
2009-10-27 14:04:59 +01:00
Miroslav Lichvar
5b4e07d658 Add refclock option for delay
This is useful when refclocks don't agree on time, increasing the
delay will widen the interval used in the source selection algorithm.
2009-10-27 14:02:16 +01:00
Miroslav Lichvar
48b6c2aa6b Reduce size of NTP sources hash table
IPv6 addressing significantly increased size of the table,
keep only pointers to get it back.
2009-10-13 17:16:41 +02:00
Miroslav Lichvar
1570f97ee2 Include both refid and IP address in tracking and sourcestats reports
ref_id is not sufficient for IPv6 addresses and ref_id is needed for
reference clocks.
2009-10-13 16:16:57 +02:00
Miroslav Lichvar
fbd20c429e Add -4 and -6 options to set address family when resolving names 2009-10-13 16:15:49 +02:00
Miroslav Lichvar
a7892a1a15 Always send timevals in cmdmon protocol in 64-bit format
This is to avoid incompatibility between 64/32-bit client/server.
While at it, convert all time values in the protocol to timeval
to avoid Y2K38 problem.
2009-10-13 16:15:23 +02:00
Miroslav Lichvar
8265ff2890 Add IPv6 support 2009-10-13 14:44:33 +02:00
Miroslav Lichvar
183d56fd40 Don't use uninitialized values
This fixes a bunch or valgrind errors.
2009-10-13 14:43:47 +02:00
Miroslav Lichvar
d06f02be1c Don't forget to free capability object 2009-09-21 12:47:17 +02:00
Miroslav Lichvar
5a2b38378c Don't copy util functions in client.c
This requires moving croak() to logging.c and avoiding use
of log functions in util.c.
2009-09-15 18:08:58 +02:00
Miroslav Lichvar
19f3a6bca8 Fix string termination in refclock parameter parser 2009-09-09 17:12:43 +02:00
Miroslav Lichvar
dd4fb511a5 Don't lose remaining adjtime in initiate_slew
initiate_slew is called also from set_frequency which doesn't read
the remaining adjtime. This wasn't a problem before commit 8c0f3f4
as offset_register was 0.0 and initiate_slew immediately returned.
2009-08-26 17:58:57 +02:00
Miroslav Lichvar
3a9e13445f Add SOCK refclock driver
This adds a support for receiving samples over unix domain socket.
It's a better alternative to the SHM refclock, the resolution is not
limited to microseconds and it doesn't require polling.
2009-08-19 15:39:06 +02:00
Miroslav Lichvar
67c0f1c08c Switch refclock driver parameter to string 2009-08-19 15:29:52 +02:00
Miroslav Lichvar
8de55124a8 Add support for SO_TIMESTAMP control messages
SO_TIMESTAMP messages contain kernel time stamps for received packets,
this should improve accuracy and avoid the impact of CPU scheduling
latencies.
2009-08-08 12:50:04 +02:00
Timo Teras
0666d04ab2 Set reply source IP from query destination IP
Currently, on multihomed host, when chrony is not bound to a specific
IP address, a query is sent to an interface and the default source IP
hint for the back route differs, the reply will have a source IP
different than where the query was destinied to. This will cause
problems because connection tracking firewalls will drop the replies
and most likely the client program will get confused too.

This patch uses the IP_PKTINFO mechanism to get the IP address where
received packets where targetted to and use that IP address as source
hint when sending a reply.
2009-08-07 17:02:11 +02:00
Timo Teras
d87cddd6a5 Switch to recvmsg/sendmsg to get access to control messages 2009-08-07 14:27:51 +02:00
Miroslav Lichvar
84cbeeadd1 Add editline support
GNU readline recently changed license to GPLv3+ which makes it
incompatible with chrony (GPLv2). This patch adds support for editline
library (BSD license).
2009-07-17 12:48:00 +02:00
Miroslav Lichvar
eefb5c7552 Fix compiler warnings in getdate.c 2009-07-06 11:49:26 +02:00
Miroslav Lichvar
8c0f3f4042 Try to minimize adjtime error
The offset is rounded before calling adjtime and the error below
microsecond is accumulated.
2009-07-01 15:56:00 +02:00
Miroslav Lichvar
735811b2b9 Add median filter for refclocks 2009-07-01 15:55:56 +02:00
Miroslav Lichvar
923c58485f Add client support for Kiss-of-Death RATE
This adds support for RATE code which can be used in reply from NTP
server to reduce client's polling.
2009-06-30 18:01:55 +02:00
Miroslav Lichvar
032d1db883 Add support for ADJ_OFFSET_SS_READ mode
Also assume that kernels >= 2.6.27 don't need frequency scaling.
2009-05-20 17:43:09 +02:00
Miroslav Lichvar
75330fdff5 Add SHM refclock driver 2009-05-05 23:06:04 +02:00
Miroslav Lichvar
ac30bb06ef Add support for reference clocks 2009-05-05 23:05:59 +02:00
Miroslav Lichvar
ef3669fe1b Make sure skew isn't 0.0 to avoid segfaults 2009-05-05 08:52:33 +02:00
Miroslav Lichvar
9416a24f03 Don't finalise from signal handler 2009-04-29 13:53:02 +02:00
Miroslav Lichvar
8b81bfe41d Reduce request timeout in chronyc 2009-04-27 16:44:44 +02:00
Miroslav Lichvar
96759116e2 Fix memlockall patch 2009-02-11 18:01:23 +01:00
Miroslav Lichvar
4aae133c4d Fix compiler warnings in wrap_adjtimex.c 2009-02-10 18:06:25 +01:00
John Hasler
35e662d810 Add mlockall and SCHED_FIFO support
The attached patch adds support for mlockall() as well as the SCHED_FIFO
real-time scheduler. It should result in reduced (and more consistent)
latency. Usage is documented in all the documents.
2009-02-10 18:02:28 +01:00
Miroslav Lichvar
cdc22df903 Fix leap sign in measurements log 2009-01-08 13:34:54 +01:00
Miroslav Lichvar
8f9c237010 Leap second support
Leap second status is accepted and forwarded to clients if majority
of selectable sources agree. The actual insertion/deletion is supported
only on Linux now.
2009-01-08 13:33:15 +01:00
Miroslav Lichvar
0148ecaea0 Retry name resolving after temporary failure few times before giving up
This is a temporary fix to allow starting when resolv.conf is not ready yet
(e.g. when using NetworkManager). It may delay start up to 1022 seconds.
2008-11-10 15:54:06 +01:00
Miroslav Lichvar
fd2641bcb9 Fix resolving IP addresses into names on 64-bit big-endian machines 2008-11-06 18:18:41 +01:00
Miroslav Lichvar
be42b4eeea Linux capabilities support
Attached is a patch adding a linux capabilities support to chronyd. It
adds -u option which can be used to specify the user which chronyd
should switch to.
2008-11-05 23:50:48 +00:00
Miroslav Lichvar
8336f14680 Fix errors detected by valgrind
I tried running chronyd in valgrind and the result was that there are four
places where memory is not initialized. A patch fixing the errors is in the
attachment.
2008-11-05 23:48:58 +00:00
John Hasler
bc0aaa9217 Fix fault where chronyd enters an endless loop on x86_64
John writes:
Here is a patch that should prevent the endless loop.  I've changed
UTI_NormaliseTimeval() to use divide/remainder instead of a loop.  It also
replaces some similar loops with calls to UTI_NormaliseTimeval() and fixes
an unrelated bug in UTI_DiffTimevals().
2008-10-01 23:57:20 +01:00
Thomas Zajic
71aa36aa6e Fix IP addressing in chronyc
Thomas wrote:
I found a bug in the chrony client (chronyc) that affects its ability to talk
to remote hosts over the control port (323/udp).

For example, running "chronyc -h 192.168.1.3 sources -v" would just sit there
and hang, and eventually timeout. I found out with tcpdump that chronyc
actually tries to connect to 255.168.1.3 instead of 192.168.1.3.
2008-07-29 23:35:42 +01:00
Goswin Brederlow
2f2446c7dc Fix for chronyc "sources" command on 64 bit machines
(Taken from
  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=348412
)

Attached is a patchlet to make the "sources" command of chrony output properly
signed numbers. The chronyd code (see e.g. ntp.h) properly uses int32_t and
friends to get the right number of bits per datatype while client.c just uses
short, int, long. But long will be 64 bit or 32 bit depending on the cpu.
2008-03-29 20:49:59 +00:00
Richard P. Curnow
5331e1a146 Update NEWS for 1.23 2007-12-02 14:53:09 +00:00
Richard P. Curnow
eeac7b7ca0 Define io_linux.h constants for x86_64
Based on thread from chrony-users, October 2007.
2007-12-02 14:39:50 +00:00
102 changed files with 8528 additions and 3191 deletions

30
COPYING
View File

@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to the GNU Lesser General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
@@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
@@ -278,8 +278,8 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest 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 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ 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. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. 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 If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.
@@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. Public License instead of this License.

22
INSTALL
View File

@@ -32,13 +32,17 @@ for Bourne-family shells, or
for C-family shells. for C-family shells.
If the software cannot (yet) be built on your system, an error message If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, the files `options.h' and `Makefile' will will be shown. Otherwise, `Makefile' will be generated.
be generated.
By default, chronyc will be built to make use of the readline library. If you If editline or readline library is available, chronyc will be built
don't want this, specify the --disable-readline flag to configure. If you have with line editing support. If you don't want this, specify the
readline and/or ncurses installed in a non-standard location, please refer to --disable-readline flag to configure. Please refer to the chrony.txt
the chrony.txt file for information. file for more information.
If a `timepps.h' header is available, 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 CPPFLAGS variable to -I/path/to/timepps.
Now type Now type
@@ -67,11 +71,11 @@ If you want chrony to appear in the top level info directory listing, you need
to run the install-info command manually after this step. install-info takes 2 to run the install-info command manually after this step. install-info takes 2
arguments. The first is the path to the chrony.info file you have just arguments. The first is the path to the chrony.info file you have just
installed. This will be the argument you gave to --prefix when you configured installed. This will be the argument you gave to --prefix when you configured
(/usr/local by default), with /info/chrony.info on the end. The second (/usr/local by default), with /share/info/chrony.info on the end. The second
argument is the location of the file called 'dir'. This will typically be argument is the location of the file called 'dir'. This will typically be
/usr/info/dir. So the typical command line would be /usr/share/info/dir. So the typical command line would be
install-info /usr/local/info/chrony.info /usr/info/dir install-info /usr/local/share/info/chrony.info /usr/share/info/dir
Now that the software is successfully installed, the next step is to Now that the software is successfully installed, the next step is to
set up a configuration file. The contents of this depend on the set up a configuration file. The contents of this depend on the

View File

@@ -19,19 +19,23 @@
# #
# You should have received a copy of the GNU General Public License along # 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., # with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
# ======================================================================= # =======================================================================
# #
# Makefile template # Makefile template
INSTALL_PREFIX=@INSTALL_PREFIX@ SYSCONFDIR=@SYSCONFDIR@
BINDIR=@BINDIR@
SBINDIR=@SBINDIR@
MANDIR=@MANDIR@ MANDIR=@MANDIR@
INFODIR=@INFODIR@ INFODIR=@INFODIR@
DOCDIR=@DOCDIR@
CC = @CC@ CC = @CC@
CCWARNFLAGS = @CCWARNFLAGS@ CCWARNFLAGS = @CCWARNFLAGS@
OPTFLAGS = @CFLAGS@ @EXTRA_DEFS@ OPTFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@ @SYSDEFS@ @EXTRA_DEFS@
DESTDIR= DESTDIR=
@@ -41,25 +45,25 @@ OBJS = util.o sched.o regress.o local.o \
logging.o conf.o cmdmon.o md5.o keys.o \ logging.o conf.o cmdmon.o md5.o keys.o \
nameserv.o acquire.o manual.o addrfilt.o \ nameserv.o acquire.o manual.o addrfilt.o \
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \ cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
broadcast.o broadcast.o refclock.o refclock_shm.o refclock_sock.o \
refclock_pps.o
EXTRA_OBJS=@EXTRA_OBJECTS@ EXTRA_OBJS=@EXTRA_OBJECTS@
CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \ CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \
pktlength.o pktlength.o util.o
SRCS = $(patsubst %.o,%.c,$(OBJS)) SRCS = $(patsubst %.o,%.c,$(OBJS))
EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS)) EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS))
CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS)) CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS))
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
EXTRA_LIBS=@EXTRA_LIBS@ EXTRA_LIBS=@EXTRA_LIBS@
EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@ EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@
DEFS=@SYSDEFS@
CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS) CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
# Until we have a main procedure we can link, just build object files # Until we have a main procedure we can link, just build object files
@@ -68,13 +72,16 @@ CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
all : chronyd chronyc all : chronyd chronyc
chronyd : $(OBJS) $(EXTRA_OBJS) chronyd : $(OBJS) $(EXTRA_OBJS)
$(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LIBS) $(EXTRA_LIBS) $(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS)
chronyc : $(CLI_OBJS) chronyc : $(CLI_OBJS)
$(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS) $(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
conf.o : conf.c
$(CC) $(CFLAGS) $(CPPFLAGS) -DDEFAULT_CONF_DIR=\"$(SYSCONFDIR)\" -c $<
client.o : client.c client.o : client.c
$(CC) $(CFLAGS) $(DEFS) @READLINE_COMPILE@ -c $< $(CC) $(CFLAGS) $(CPPFLAGS) @READLINE_COMPILE@ -c $<
.depend : .depend :
gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend
@@ -88,45 +95,47 @@ clean :
version.h : version.txt version.h : version.txt
./mkversion ./mkversion
getdate.c : ;
getdate :
bison -o getdate.c getdate.y
# For install, don't use the install command, because its switches # For install, don't use the install command, because its switches
# seem to vary between systems. # seem to vary between systems.
install: chronyd chronyc install: chronyd chronyc
[ -d $(DESTDIR)$(INSTALL_PREFIX) ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX) [ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR)
[ -d $(DESTDIR)$(INSTALL_PREFIX)/sbin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/sbin [ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
[ -d $(DESTDIR)$(INSTALL_PREFIX)/bin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/bin [ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1 [ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5 [ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8 [ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony [ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
if [ -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ; fi if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi
if [ -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ; fi if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi
cp chronyd $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd cp chronyd $(DESTDIR)$(SBINDIR)/chronyd
chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd chmod 755 $(DESTDIR)$(SBINDIR)/chronyd
cp chronyc $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc cp chronyc $(DESTDIR)$(BINDIR)/chronyc
chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc chmod 755 $(DESTDIR)$(BINDIR)/chronyc
cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
cp COPYING $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING cp COPYING $(DESTDIR)$(DOCDIR)/COPYING
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
cp README $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README cp README $(DESTDIR)$(DOCDIR)/README
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README chmod 644 $(DESTDIR)$(DOCDIR)/README
cp chrony.1 $(DESTDIR)$(MANDIR)/man1 cp chrony.1 $(DESTDIR)$(MANDIR)/man1
chmod 444 $(DESTDIR)$(MANDIR)/man1/chrony.1 chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1 cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
chmod 444 $(DESTDIR)$(MANDIR)/man1/chronyc.1 chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8 cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
chmod 444 $(DESTDIR)$(MANDIR)/man8/chronyd.8 chmod 644 $(DESTDIR)$(MANDIR)/man8/chronyd.8
cp chrony.conf.5 $(DESTDIR)$(MANDIR)/man5 cp chrony.conf.5 $(DESTDIR)$(MANDIR)/man5
chmod 444 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5 chmod 644 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5
%.o : %.c %.o : %.c
$(CC) $(CFLAGS) $(DEFS) -c $< $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
%.s : %.c %.s : %.c
$(CC) $(CFLAGS) $(DEFS) -S $< $(CC) $(CFLAGS) $(CPPFLAGS) -S $<
main.o logging.o client.o : version.h main.o logging.o client.o : version.h
@@ -134,17 +143,14 @@ main.o logging.o client.o : version.h
MAKEINFO:=makeinfo MAKEINFO:=makeinfo
install-docs : docs install-docs : docs
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc [ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
chown root $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt cp chrony.html $(DESTDIR)$(DOCDIR)/chrony.html
cp chrony.html $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html chmod 644 $(DESTDIR)$(DOCDIR)/chrony.html
chown root $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html
[ -d $(DESTDIR)$(INFODIR) ] || mkdir -p $(DESTDIR)$(INFODIR) [ -d $(DESTDIR)$(INFODIR) ] || mkdir -p $(DESTDIR)$(INFODIR)
cp chrony.info* $(DESTDIR)$(INFODIR) cp chrony.info* $(DESTDIR)$(INFODIR)
chown root $(DESTDIR)$(INFODIR)/chrony.info* chmod 644 $(DESTDIR)$(INFODIR)/chrony.info*
chmod 444 $(DESTDIR)$(INFODIR)/chrony.info*
docs : chrony.txt chrony.html chrony.info docs : chrony.txt chrony.html chrony.info

49
NEWS
View File

@@ -1,3 +1,52 @@
New in version 1.24
===================
* 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
* Add option to limit client log memory size
* Retry name resolving after temporary failure
* 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 New in version 1.21
=================== ===================

89
README
View File

@@ -18,8 +18,8 @@ accordingly. It also works out the rate at which the system clock
gains or loses time and uses this information to keep it accurate gains or loses time and uses this information to keep it accurate
between measurements from the reference. between measurements from the reference.
The reference time can be derived from either Network Time Protocol The reference time can be derived from Network Time Protocol (NTP)
(NTP) servers (preferred), or wristwatch-and-keyboard (via chronyc). servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
http://www.eecis.udel.edu/~ntp. http://www.eecis.udel.edu/~ntp.
@@ -28,9 +28,9 @@ intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet. Of course, it will work use a dial-up account to access the Internet. Of course, it will work
on computers with permanent connections too. on computers with permanent connections too.
In addition, the Linux 2.0.x (for x >= 32), 2.2.x and 2.3.x versions In addition, on Linux it can monitor the system's real time clock
can monitor the system's real time clock performance, so the system performance, so the system can maintain accurate time even across
can maintain accurate time even across reboots. reboots.
Typical accuracies available between 2 machines are Typical accuracies available between 2 machines are
@@ -38,6 +38,8 @@ On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next) session to the next)
With a good reference clock the accuracy can reach one microsecond.
chronyd can also operate as an RFC1305-compatible NTP server and peer. chronyd can also operate as an RFC1305-compatible NTP server and peer.
@@ -46,9 +48,10 @@ What will chrony run on?
Chrony can be successfully built and run on Chrony can be successfully built and run on
1. Linux v1.2.13, v2.0.x, 2.1.x (partially), 2.2.x, 2.3.x, 2.4.x (i386). 1. Linux v1.2.13, v2.0.x, 2.1.x (partially), 2.2.x, 2.3.x, 2.4.x, 2.6.x.
Real time clock support is limited to 2.0.32 onwards and to 2.2, 2.3 and Real time clock support is limited to 2.0.32 onwards and to 2.2, 2.3,
2.4 series only. PowerPC is also known to be supported. 2.4 and 2.6 series only. i386, x86_64, PowerPC are known to be
supported.
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms) 2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
@@ -69,8 +72,7 @@ How do I set it up?
The file INSTALL gives instructions. On supported systems the The file INSTALL gives instructions. On supported systems the
compilation process should be automatic. compilation process should be automatic.
You will need an ANSI C compiler -- gcc is recommended. Versions You will need an ANSI C compiler -- gcc is recommended.
2.7.2/2.7.2.2 are known to work.
The manual (in texinfo and text formats) describes how to set the The manual (in texinfo and text formats) describes how to set the
software up for the less straightforward cases. software up for the less straightforward cases.
@@ -84,29 +86,25 @@ ready-formatted plain text (chrony.txt) in the distribution.
There is also information available on the chrony web pages, accessible There is also information available on the chrony web pages, accessible
through the URL through the URL
http://chrony.sunsite.dk/ http://chrony.tuxfamily.org/
What can chrony not do? What can chrony not do?
======================= =======================
Compared to the `reference' RFC1305 implementation xntpd, chronyd does Compared to the `reference' RFC1305 implementation xntpd, chronyd does
not support hardware reference clocks, leap seconds or broadcast not support broadcast modes.
modes.
Where are new versions announced? Where are new versions announced?
================================= =================================
There is a low volume mailing list where new versions and other There is a low volume mailing list where new versions and other
important news relating to chrony is announced. You can join this list important news relating to chrony is announced. You can join this list
by sending mail to by sending mail with the subject "subscribe" to
chrony-announce-subscribe@sunsite.dk chrony-announce-request@chrony.tuxfamily.org
These messages will be copied to chrony-users (see below). I also try These messages will be copied to chrony-users (see below). New versions
to announce new versions on Freshmeat (http://freshmeat.net/). are announced also on Freshmeat (http://freshmeat.net/).
I don't reliably announce via news any more - I don't tend to keep up
with news as I haven't enough time.
How can I get support for chrony? How can I get support for chrony?
and where can I discuss new features, possible bugs etc? and where can I discuss new features, possible bugs etc?
@@ -117,36 +115,28 @@ mentioned above. chrony-users is a users' discussion list, e.g. for
general questions and answers about using chrony. chrony-dev is a more general questions and answers about using chrony. chrony-dev is a more
technical list, e.g. for discussing how new features should be technical list, e.g. for discussing how new features should be
implemented, exchange of information between developers etc. To implemented, exchange of information between developers etc. To
subscribe to either of these lists, send an empty message to subscribe to either of these lists, send a message with the subject
"subscribe" to
chrony-users-subscribe@sunsite.dk chrony-users-request@chrony.tuxfamily.org
or or
chrony-dev-subscribe@sunsite.dk chrony-dev-request@chrony.tuxfamily.org
as applicable. as applicable.
Note that due to family commitments (a 3 year-old and a 1 year-old), I
no longer have the time to give to supporting chrony that I once had.
Therefore, the chrony-users list should be your main route for support,
rather than mailing me directly. Even if it's me that responds to your
question on the list, at least *ALL* subscribers then benefit from
seeing the discussion, rather than me taking up lots of time on
supporting people on a one-to-one basis. If you do mail me directly,
don't be surprised if I cc: the response to the mailing list.
But how can I contact the author if I need to? Author
============================================== ======
You can email me at <rc@rc0.org.uk>. If that fails, you could try to Richard P. Curnow <rc@rc0.org.uk>
find me through one of the mailing lists. It would be nice if:
- you include the word 'chrony' in the subject line (so my mail reader
can sort my mail by topic)
- you don't send complete log files, encoded binaries etc, without Maintainers
editing such material down to just the relevant bits - a few tens of ===========
lines at most. (My dial-up connection handles large messages rather
slowly ...). John Hasler <john@dhh.gt.org>
Miroslav Lichvar <mlichvar@redhat.com>
Acknowledgements Acknowledgements
================ ================
@@ -199,6 +189,8 @@ John Hasler <john@dhh.gt.org>
sizeof(unsigned long) > 4) sizeof(unsigned long) > 4)
Bug fix to initstepslew directive Bug fix to initstepslew directive
Fix to remove potential buffer overrun errors. Fix to remove potential buffer overrun errors.
Memory locking and real-time scheduler support
Fix fault where chronyd enters an endless loop
Liam Hatton <me@liamhatton.com> Liam Hatton <me@liamhatton.com>
Advice on configuring for Linux on PPC Advice on configuring for Linux on PPC
@@ -212,6 +204,13 @@ Jim Knoble <jmknoble@pobox.com>
Antti Jrvinen <costello@iki.fi> Antti Jrvinen <costello@iki.fi>
Advice on configuring for BSD/386 Advice on configuring for BSD/386
Miroslav Lichvar <mlichvar@redhat.com>
Reference clock support
IPv6 support
Linux capabilities support
Leap second support
Various bug fixes and improvements
Victor Moroz <vim@prv.adlum.ru> Victor Moroz <vim@prv.adlum.ru>
Patch to support Linux with HZ!=100 Patch to support Linux with HZ!=100
@@ -224,6 +223,9 @@ Frank Otto <sandwichmacher@web.de>
Andreas Piesk <apiesk@virbus.de> Andreas Piesk <apiesk@virbus.de>
Patch to make chronyc use the readline library if available Patch to make chronyc use the readline library if available
Timo Teras <timo.teras@iki.fi>
Patch to reply correctly on multihomed hosts
Wolfgang Weisselberg <weissel@netcologne.de> Wolfgang Weisselberg <weissel@netcologne.de>
Entries in contrib directory Entries in contrib directory
@@ -240,9 +242,4 @@ Doug Woodward <dougw@whistler.com>
Many other people have contributed bug reports and suggestions. I'm Many other people have contributed bug reports and suggestions. I'm
sorry I can't identify all of you individually. sorry I can't identify all of you individually.
Version control information
===========================
$Header: /cvs/src/chrony/README,v 1.30 2003/09/21 23:11:06 richard Exp $
vim:tw=72 vim:tw=72

174
acquire.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -65,7 +65,8 @@
#define RETRANSMISSION_TIMEOUT (1.0) #define RETRANSMISSION_TIMEOUT (1.0)
typedef struct { unsigned long ip_addr; typedef struct {
IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source int sanity; /* Flag indicating whether source
looks sane or not */ looks sane or not */
int n_dead_probes; /* Number of probes sent to the server int n_dead_probes; /* Number of probes sent to the server
@@ -93,7 +94,18 @@ static int n_completed_sources;
static int init_slew_threshold = -1; static int init_slew_threshold = -1;
static int sock_fd = -1; union sockaddr_in46 {
struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
static int sock_fd4 = -1;
#ifdef HAVE_IPV6
static int sock_fd6 = -1;
#endif
/* ================================================== */ /* ================================================== */
@@ -143,12 +155,14 @@ ACQ_Finalise(void)
/* ================================================== */ /* ================================================== */
static void static int
initialise_io(void) prepare_socket(int family)
{ {
unsigned short port_number = CNF_GetAcquisitionPort(); unsigned short port_number = CNF_GetAcquisitionPort();
int sock_fd;
socklen_t addrlen;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); sock_fd = socket(family, SOCK_DGRAM, 0);
if (sock_fd < 0) { if (sock_fd < 0) {
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno)); LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
@@ -158,18 +172,50 @@ initialise_io(void)
/* Don't bother binding this socket - we're not fussed what port /* Don't bother binding this socket - we're not fussed what port
number it gets */ number it gets */
} else { } else {
struct sockaddr_in my_addr; union sockaddr_in46 my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number); memset(&my_addr, 0, sizeof (my_addr));
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { switch (family) {
case AF_INET:
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons(port_number);
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
addrlen = sizeof (my_addr.in4);
break;
#ifdef HAVE_IPV6
case AF_INET6:
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons(port_number);
my_addr.in6.sin6_addr = in6addr_any;
addrlen = sizeof (my_addr.in6);
break;
#endif
default:
assert(0);
}
if (bind(sock_fd, &my_addr.u, addrlen) < 0) {
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno)); LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
/* but keep running */ /* but keep running */
} }
} }
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL); SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
return sock_fd;
}
/* ================================================== */
static void
initialise_io(int family)
{
if (family == IPADDR_INET4 || family == IPADDR_UNSPEC)
sock_fd4 = prepare_socket(AF_INET);
#ifdef HAVE_IPV6
if (family == IPADDR_INET6 || family == IPADDR_UNSPEC)
sock_fd6 = prepare_socket(AF_INET6);
#endif
} }
/* ================================================== */ /* ================================================== */
@@ -177,10 +223,18 @@ initialise_io(void)
static void static void
finalise_io(void) finalise_io(void)
{ {
if (sock_fd >= 0) { if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd); SCH_RemoveInputFileHandler(sock_fd4);
close(sock_fd); close(sock_fd4);
} }
sock_fd4 = -1;
#ifdef HAVE_IPV6
if (sock_fd6 >= 0) {
SCH_RemoveInputFileHandler(sock_fd6);
close(sock_fd6);
}
sock_fd6 = -1;
#endif
return; return;
} }
@@ -195,10 +249,12 @@ probe_source(SourceRecord *src)
NTP_Mode my_mode = MODE_CLIENT; NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked; struct timeval cooked;
double local_time_err; double local_time_err;
struct sockaddr_in his_addr; union sockaddr_in46 his_addr;
int sock_fd;
socklen_t addrlen;
#if 0 #if 0
printf("Sending probe to %08lx sent=%d samples=%d\n", src->ip_addr, src->n_probes_sent, src->n_samples); printf("Sending probe to %s sent=%d samples=%d\n", UTI_IPToString(&src->ip_addr), src->n_probes_sent, src->n_samples);
#endif #endif
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) | pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
@@ -219,18 +275,39 @@ probe_source(SourceRecord *src)
pkt.receive_ts.lo = 0; /* Set to 0 */ pkt.receive_ts.lo = 0; /* Set to 0 */
/* And do transmission */ /* And do transmission */
his_addr.sin_addr.s_addr = htonl(src->ip_addr);
his_addr.sin_port = htons(123); /* Fixed for now */ memset(&his_addr, 0, sizeof (his_addr));
his_addr.sin_family = AF_INET; switch (src->ip_addr.family) {
case IPADDR_INET4:
his_addr.in4.sin_addr.s_addr = htonl(src->ip_addr.addr.in4);
his_addr.in4.sin_port = htons(123); /* Fixed for now */
his_addr.in4.sin_family = AF_INET;
addrlen = sizeof (his_addr.in4);
sock_fd = sock_fd4;
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
memcpy(&his_addr.in6.sin6_addr.s6_addr, &src->ip_addr.addr.in6,
sizeof (his_addr.in6.sin6_addr.s6_addr));
his_addr.in6.sin6_port = htons(123); /* Fixed for now */
his_addr.in6.sin6_family = AF_INET6;
addrlen = sizeof (his_addr.in6);
sock_fd = sock_fd6;
break;
#endif
default:
assert(0);
}
LCL_ReadCookedTime(&cooked, &local_time_err); LCL_ReadCookedTime(&cooked, &local_time_err);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts); UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE, if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
0, 0,
(struct sockaddr *) &his_addr, sizeof(his_addr)) < 0) { &his_addr.u, addrlen) < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s", LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
UTI_IPToDottedQuad(src->ip_addr), UTI_IPToString(&src->ip_addr),
strerror(errno)); strerror(errno));
} }
@@ -253,7 +330,7 @@ transmit_timeout(void *x)
src->timer_running = 0; src->timer_running = 0;
#if 0 #if 0
printf("Timeout expired for server %08lx\n", src->ip_addr); printf("Timeout expired for server %s\n", UTI_IPToString(&src->ip_addr));
#endif #endif
if (src->n_dead_probes < MAX_DEAD_PROBES) { if (src->n_dead_probes < MAX_DEAD_PROBES) {
@@ -357,14 +434,14 @@ read_from_socket(void *anything)
{ {
int status; int status;
ReceiveBuffer msg; ReceiveBuffer msg;
struct sockaddr_in his_addr; union sockaddr_in46 his_addr;
int sock_fd;
socklen_t his_addr_len; socklen_t his_addr_len;
int flags; int flags;
int message_length; int message_length;
unsigned long remote_ip; IPAddr remote_ip;
int i, ok; int i, ok;
struct timeval now; struct timeval now;
double local_time_err;
SourceRecord *src; SourceRecord *src;
flags = 0; flags = 0;
@@ -372,26 +449,41 @@ read_from_socket(void *anything)
his_addr_len = sizeof(his_addr); his_addr_len = sizeof(his_addr);
/* Get timestamp */ /* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err); SCH_GetFileReadyTime(&now);
sock_fd = (long)anything;
status = recvfrom (sock_fd, (char *)&msg, message_length, flags, status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
(struct sockaddr *) &his_addr, &his_addr_len); &his_addr.u, &his_addr_len);
if (status < 0) { if (status < 0) {
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno)); LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
return; return;
} }
remote_ip = ntohl(his_addr.sin_addr.s_addr); switch (his_addr.u.sa_family) {
case AF_INET:
remote_ip.family = IPADDR_INET4;
remote_ip.addr.in4 = ntohl(his_addr.in4.sin_addr.s_addr);
break;
#ifdef HAVE_IPV6
case AF_INET6:
remote_ip.family = IPADDR_INET6;
memcpy(&remote_ip.addr.in6, his_addr.in6.sin6_addr.s6_addr,
sizeof (remote_ip.addr.in6));
break;
#endif
default:
assert(0);
}
#if 0 #if 0
printf("Got message from %08lx\n", remote_ip); printf("Got message from %s\n", UTI_IPToString(&remote_ip));
#endif #endif
/* Find matching host */ /* Find matching host */
ok = 0; ok = 0;
for (i=0; i<n_sources; i++) { for (i=0; i<n_sources; i++) {
if (remote_ip == sources[i].ip_addr) { if (UTI_CompareIPs(&remote_ip, &sources[i].ip_addr, NULL) == 0) {
ok = 1; ok = 1;
break; break;
} }
@@ -418,7 +510,7 @@ read_from_socket(void *anything)
(src->n_total_samples >= MAX_SAMPLES)) { (src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources; ++n_completed_sources;
#if 0 #if 0
printf("Source %08lx completed\n", src->ip_addr); printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
#endif #endif
if (n_completed_sources == n_sources) { if (n_completed_sources == n_sources) {
wind_up_acquisition(); wind_up_acquisition();
@@ -440,7 +532,7 @@ start_next_source(void)
{ {
probe_source(sources + n_started_sources); probe_source(sources + n_started_sources);
#if 0 #if 0
printf("Trying to start source %08lx\n", sources[n_started_sources].ip_addr); printf("Trying to start source %s\n", UTI_IPToString(&sources[n_started_sources].ip_addr));
#endif #endif
n_started_sources++; n_started_sources++;
@@ -552,10 +644,10 @@ process_measurements(void)
for (i=0; i<2*n_sane_sources; i++) { for (i=0; i<2*n_sane_sources; i++) {
#if 0 #if 0
fprintf(stderr, "Endpoint type %s source index %d [ip=%08lx] offset=%.6f\n", fprintf(stderr, "Endpoint type %s source index %d [ip=%s] offset=%.6f\n",
(eps[i].type == LO) ? "LO" : "HIGH", (eps[i].type == LO) ? "LO" : "HIGH",
eps[i].index, eps[i].index,
sources[eps[i].index].ip_addr, UTI_IPToString(&sources[eps[i].index].ip_addr),
eps[i].offset); eps[i].offset);
#endif #endif
@@ -655,10 +747,10 @@ start_source_timeout_handler(void *not_used)
/* ================================================== */ /* ================================================== */
void void
ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after_hook)(void *), void *anything) ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
{ {
int i; int i, ip4, ip6;
saved_after_hook = after_hook; saved_after_hook = after_hook;
saved_after_hook_anything = anything; saved_after_hook_anything = anything;
@@ -670,14 +762,18 @@ ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after
n_sources = n; n_sources = n;
sources = MallocArray(SourceRecord, n); sources = MallocArray(SourceRecord, n);
for (i=0; i<n; i++) { for (i = ip4 = ip6 = 0; i < n; i++) {
sources[i].ip_addr = ip_addrs[i]; sources[i].ip_addr = ip_addrs[i];
sources[i].n_samples = 0; sources[i].n_samples = 0;
sources[i].n_total_samples = 0; sources[i].n_total_samples = 0;
sources[i].n_dead_probes = 0; sources[i].n_dead_probes = 0;
if (ip_addrs[i].family == IPADDR_INET4)
ip4++;
else if (ip_addrs[i].family == IPADDR_INET6)
ip6++;
} }
initialise_io(); initialise_io((ip4 && ip6) ? IPADDR_UNSPEC : (ip4 ? IPADDR_INET4 : IPADDR_INET6));
/* Start sampling first source */ /* Start sampling first source */
start_next_source(); start_next_source();

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,13 +31,15 @@
#ifndef GOT_ACQUIRE_H #ifndef GOT_ACQUIRE_H
#define GOT_ACQUIRE_H #define GOT_ACQUIRE_H
#include "addressing.h"
typedef struct ACQ_SourceRecord *ACQ_Source; typedef struct ACQ_SourceRecord *ACQ_Source;
extern void ACQ_Initialise(void); extern void ACQ_Initialise(void);
extern void ACQ_Finalise(void); extern void ACQ_Finalise(void);
extern void ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int init_slew_threshold, extern void ACQ_StartAcquisition(int n, IPAddr *ip_addrs, int init_slew_threshold,
void (*after_hook)(void *), void *anything); void (*after_hook)(void *), void *anything);
extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance); extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,16 +31,28 @@
#ifndef GOT_ADDRESSING_H #ifndef GOT_ADDRESSING_H
#define GOT_ADDRESSING_H #define GOT_ADDRESSING_H
/* This type is used to represent an IPv4 address and port #include "sysincl.h"
number. Both parts are in HOST order, NOT network order. */
/* 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 { typedef struct {
unsigned long ip_addr; union {
uint32_t in4;
uint8_t in6[16];
} addr;
uint16_t family;
} IPAddr;
typedef struct {
IPAddr ip_addr;
IPAddr local_ip_addr;
unsigned short port; unsigned short port;
} NTP_Remote_Address; } NTP_Remote_Address;
#if 0
unsigned long NTP_IP_Address;
#endif
#endif /* GOT_ADDRESSING_H */ #endif /* GOT_ADDRESSING_H */

View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005 * Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -51,23 +52,35 @@ typedef struct _TableNode {
} TableNode; } TableNode;
struct ADF_AuthTableInst { struct ADF_AuthTableInst {
TableNode base; TableNode base4; /* IPv4 node */
TableNode base6; /* IPv6 node */
}; };
/* ================================================== */ /* ================================================== */
inline static unsigned long static void
get_subnet(unsigned long addr) split_ip6(IPAddr *ip, uint32_t *dst)
{ {
return (addr >> (32-NBITS)) & ((1UL<<NBITS) - 1); int i;
for (i = 0; i < 4; i++)
dst[i] = ip->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 unsigned long inline static uint32_t
get_residual(unsigned long addr) get_subnet(uint32_t *addr, unsigned int where)
{ {
return (addr << NBITS); int off;
off = where / 32;
where %= 32;
return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
} }
/* ================================================== */ /* ================================================== */
@@ -79,8 +92,10 @@ ADF_CreateTable(void)
result = MallocNew(struct ADF_AuthTableInst); result = MallocNew(struct ADF_AuthTableInst);
/* Default is that nothing is allowed */ /* Default is that nothing is allowed */
result->base.state = DENY; result->base4.state = DENY;
result->base.extended = NULL; result->base4.extended = NULL;
result->base6.state = DENY;
result->base6.extended = NULL;
return result; return result;
} }
@@ -135,22 +150,22 @@ open_node(TableNode *node)
static ADF_Status static ADF_Status
set_subnet(TableNode *start_node, set_subnet(TableNode *start_node,
unsigned long ip, uint32_t *ip,
int ip_len,
int subnet_bits, int subnet_bits,
State new_state, State new_state,
int delete_children) int delete_children)
{ {
int bits_to_go; int bits_to_go, bits_consumed;
unsigned long residual; uint32_t subnet;
unsigned long subnet;
TableNode *node; TableNode *node;
bits_consumed = 0;
bits_to_go = subnet_bits; bits_to_go = subnet_bits;
residual = ip;
node = start_node; node = start_node;
if ((subnet_bits < 0) || if ((subnet_bits < 0) ||
(subnet_bits > 32)) { (subnet_bits > 32 * ip_len)) {
return ADF_BADSUBNET; return ADF_BADSUBNET;
@@ -159,13 +174,13 @@ set_subnet(TableNode *start_node,
if ((bits_to_go & (NBITS-1)) == 0) { if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) { while (bits_to_go > 0) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
if (delete_children) { if (delete_children) {
@@ -178,18 +193,18 @@ set_subnet(TableNode *start_node,
TableNode *this_node; TableNode *this_node;
while (bits_to_go >= NBITS) { while (bits_to_go >= NBITS) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
/* How many subnet entries to set : 1->8, 2->4, 3->2 */ /* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go); N = 1 << (NBITS-bits_to_go);
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
@@ -210,12 +225,41 @@ set_subnet(TableNode *start_node,
/* ================================================== */ /* ================================================== */
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_Status
ADF_Allow(ADF_AuthTable table, ADF_Allow(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 0); return set_subnet_(table, ip, subnet_bits, ALLOW, 0);
} }
/* ================================================== */ /* ================================================== */
@@ -223,30 +267,30 @@ ADF_Allow(ADF_AuthTable table,
ADF_Status ADF_Status
ADF_AllowAll(ADF_AuthTable table, ADF_AllowAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 1); return set_subnet_(table, ip, subnet_bits, ALLOW, 1);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_Deny(ADF_AuthTable table, ADF_Deny(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, DENY, 0); return set_subnet_(table, ip, subnet_bits, DENY, 0);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_DenyAll(ADF_AuthTable table, ADF_DenyAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet(&(table->base), ip, subnet_bits, DENY, 1); return set_subnet_(table, ip, subnet_bits, DENY, 1);
} }
/* ================================================== */ /* ================================================== */
@@ -254,32 +298,33 @@ ADF_DenyAll(ADF_AuthTable table,
void void
ADF_DestroyTable(ADF_AuthTable table) ADF_DestroyTable(ADF_AuthTable table)
{ {
close_node(&(table->base)); close_node(&table->base4);
close_node(&table->base6);
Free(table); Free(table);
} }
/* ================================================== */ /* ================================================== */
static int static int
check_ip_in_node(TableNode *start_node, unsigned long ip) check_ip_in_node(TableNode *start_node, uint32_t *ip)
{ {
unsigned long residual, subnet; uint32_t subnet;
int bits_consumed = 0;
int result = 0; int result = 0;
int finished = 0; int finished = 0;
TableNode *node; TableNode *node;
State state=DENY; State state=DENY;
node = start_node; node = start_node;
residual = ip;
do { do {
if (node->state != AS_PARENT) { if (node->state != AS_PARENT) {
state = node->state; state = node->state;
} }
if (node->extended) { if (node->extended) {
subnet = get_subnet(residual); subnet = get_subnet(ip, bits_consumed);
residual = get_residual(residual);
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_consumed += NBITS;
} else { } else {
/* Make decision on this node */ /* Make decision on this node */
finished = 1; finished = 1;
@@ -306,38 +351,63 @@ check_ip_in_node(TableNode *start_node, unsigned long ip)
int int
ADF_IsAllowed(ADF_AuthTable table, ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip) IPAddr *ip_addr)
{ {
uint32_t ip6[4];
return check_ip_in_node(&(table->base), ip); 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;
} }
/* ================================================== */ /* ================================================== */
#if defined TEST #if defined TEST
static void print_node(TableNode *node, unsigned long addr, int shift, int subnet_bits) static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
{ {
unsigned long new_addr; uint32_t new_addr[4];
int i; int i;
TableNode *sub_node; TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' '); for (i=0; i<subnet_bits; i++) putchar(' ');
printf("%d.%d.%d.%d/%d : %s\n", if (ip_len == 1)
((addr >> 24) & 255), printf("%d.%d.%d.%d",
((addr >> 16) & 255), ((addr[0] >> 24) & 255),
((addr >> 8) & 255), ((addr[0] >> 16) & 255),
((addr ) & 255), ((addr[0] >> 8) & 255),
((addr[0] ) & 255));
else {
for (i=0; i<4; i++) {
if (addr[i])
printf("%d.%d.%d.%d",
((addr[i] >> 24) & 255),
((addr[i] >> 16) & 255),
((addr[i] >> 8) & 255),
((addr[i] ) & 255));
putchar(i < 3 ? ':' : '\0');
}
}
printf("/%d : %s\n",
subnet_bits, subnet_bits,
(node->state == ALLOW) ? "allow" : (node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent"); (node->state == DENY) ? "deny" : "as parent");
if (node->extended) { if (node->extended) {
for (i=0; i<16; i++) { for (i=0; i<16; i++) {
sub_node = &((*(node->extended))[i]); sub_node = &(node->extended[i]);
new_addr = addr | ((unsigned long) i << shift); new_addr[0] = addr[0];
print_node(sub_node, new_addr, shift - 4, subnet_bits + 4); new_addr[1] = addr[1];
new_addr[2] = addr[2];
new_addr[3] = addr[3];
new_addr[ip_len - 1 - shift / 32] |= ((uint32_t)i << (shift % 32));
print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
} }
} }
return; return;
@@ -346,11 +416,15 @@ static void print_node(TableNode *node, unsigned long addr, int shift, int subne
static void print_table(ADF_AuthTable table) static void print_table(ADF_AuthTable table)
{ {
unsigned long addr = 0; uint32_t addr[4];
int shift = 28;
int subnet_bits = 0;
print_node(&table->base, addr, shift, subnet_bits); memset(addr, 0, sizeof (addr));
printf("IPv4 table:\n");
print_node(&table->base4, addr, 1, 28, 0);
memset(addr, 0, sizeof (addr));
printf("IPv6 table:\n");
print_node(&table->base6, addr, 4, 124, 0);
return; return;
} }
@@ -358,13 +432,41 @@ static void print_table(ADF_AuthTable table)
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
IPAddr ip;
ADF_AuthTable table; ADF_AuthTable table;
table = ADF_CreateTable(); table = ADF_CreateTable();
ADF_Allow(table, 0x7e800000, 9); ip.family = IPADDR_INET4;
ADF_Deny(table, 0x7ecc0000, 14);
/* ADF_Deny(table, 0x7f000001, 32); */ ip.addr.in4 = 0x7e800000;
/* ADF_Allow(table, 0x7f000000, 8); */ ADF_Allow(table, &ip, 9);
ip.addr.in4 = 0x7ecc0000;
ADF_Deny(table, &ip, 14);
#if 0
ip.addr.in4 = 0x7f000001;
ADF_Deny(table, &ip, 32);
ip.addr.in4 = 0x7f000000;
ADF_Allow(table, &ip, 8);
#endif
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.family = IPADDR_INET6;
memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
ADF_Deny(table, &ip, 66);
ADF_Allow(table, &ip, 59);
memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
ADF_Deny(table, &ip, 128);
ip.addr.in6[15] ^= 3;
ADF_Allow(table, &ip, 127);
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
print_table(table); print_table(table);

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,6 +31,8 @@
#ifndef GOT_ADDRFILT_H #ifndef GOT_ADDRFILT_H
#define GOT_ADDRFILT_H #define GOT_ADDRFILT_H
#include "addressing.h"
typedef struct ADF_AuthTableInst *ADF_AuthTable; typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum { typedef enum {
@@ -45,25 +47,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
/* Allow anything in the supplied subnet, EXCEPT for any more specific /* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table, extern ADF_Status ADF_Allow(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing /* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table, extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific /* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table, extern ADF_Status ADF_Deny(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing /* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table, extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
unsigned long ip, IPAddr *ip,
int subnet_bits); int subnet_bits);
/* Clear up the table */ /* Clear up the table */
@@ -72,6 +74,6 @@ extern void ADF_DestroyTable(ADF_AuthTable table);
/* Check whether a given IP address is allowed by the rules in /* Check whether a given IP address is allowed by the rules in
the table */ the table */
extern int ADF_IsAllowed(ADF_AuthTable table, extern int ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip); IPAddr *ip);
#endif /* GOT_ADDRFILT_H */ #endif /* GOT_ADDRFILT_H */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -132,7 +132,7 @@ timeout_handler(void *arbitrary)
/* ================================================== */ /* ================================================== */
void void
BRD_AddDestination(unsigned long addr, unsigned short port, int interval) BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
{ {
if (max_destinations == n_destinations) { if (max_destinations == n_destinations) {
/* Expand array */ /* Expand array */
@@ -144,7 +144,8 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
} }
} }
destinations[n_destinations].addr.ip_addr = addr; destinations[n_destinations].addr.ip_addr = *addr;
destinations[n_destinations].addr.local_ip_addr.family = IPADDR_UNSPEC;
destinations[n_destinations].addr.port = port; destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval; destinations[n_destinations].interval = interval;

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,9 +31,11 @@
#ifndef GOT_BROADCAST_H #ifndef GOT_BROADCAST_H
#define GOT_BROADCAST_H #define GOT_BROADCAST_H
#include "addressing.h"
extern void BRD_Initialise(void); extern void BRD_Initialise(void);
extern void BRD_Finalise(void); extern void BRD_Finalise(void);
extern void BRD_AddDestination(unsigned long addr, unsigned short port, int interval); extern void BRD_AddDestination(IPAddr *addr, unsigned short port, int interval);
#endif /* GOT_BROADCAST_H */ #endif /* GOT_BROADCAST_H */

160
candm.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -34,6 +34,7 @@
#define GOT_CANDM_H #define GOT_CANDM_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
/* This is the default port to use for CANDM, if no alternative is /* This is the default port to use for CANDM, if no alternative is
defined */ defined */
@@ -91,38 +92,55 @@
password. (This time value has long since gone by) */ password. (This time value has long since gone by) */
#define SPECIAL_UTOKEN 0x10101010 #define SPECIAL_UTOKEN 0x10101010
/* Structure used to exchange timevals independent on size of time_t */
typedef struct {
uint32_t tv_sec_high;
uint32_t tv_sec_low;
uint32_t tv_nsec;
} Timeval;
/* 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 /* 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 pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */ transmitted for each packet type. */
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t EOR; int32_t EOR;
} REQ_Online; } REQ_Online;
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t EOR; int32_t EOR;
} REQ_Offline; } REQ_Offline;
typedef struct { typedef struct {
uint32_t mask; IPAddr mask;
uint32_t address; IPAddr address;
int32_t n_good_samples; int32_t n_good_samples;
int32_t n_total_samples; int32_t n_total_samples;
int32_t EOR; int32_t EOR;
} REQ_Burst; } REQ_Burst;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_minpoll; int32_t new_minpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Minpoll; } REQ_Modify_Minpoll;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_maxpoll; int32_t new_maxpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxpoll; } REQ_Modify_Maxpoll;
@@ -133,29 +151,29 @@ typedef struct {
} REQ_Dump; } REQ_Dump;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_max_delay; Float new_max_delay;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelay; } REQ_Modify_Maxdelay;
typedef struct { typedef struct {
uint32_t address; IPAddr address;
int32_t new_max_delay_ratio; Float new_max_delay_ratio;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelayratio; } REQ_Modify_Maxdelayratio;
typedef struct { typedef struct {
int32_t new_max_update_skew; Float new_max_update_skew;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxupdateskew; } REQ_Modify_Maxupdateskew;
typedef struct { typedef struct {
struct timeval ts; Timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Logon; } REQ_Logon;
typedef struct { typedef struct {
struct timeval ts; Timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Settime; } REQ_Settime;
@@ -184,32 +202,35 @@ typedef struct {
} REQ_Rekey; } REQ_Rekey;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
int32_t subnet_bits; int32_t subnet_bits;
int32_t EOR; int32_t EOR;
} REQ_Allow_Deny; } REQ_Allow_Deny;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
int32_t EOR; int32_t EOR;
} REQ_Ac_Check; } REQ_Ac_Check;
/* Flags used in NTP source requests */
#define REQ_ADDSRC_ONLINE 0x1
#define REQ_ADDSRC_AUTOOFFLINE 0x2
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
uint32_t port; uint32_t port;
int32_t minpoll; int32_t minpoll;
int32_t maxpoll; int32_t maxpoll;
int32_t presend_minpoll; int32_t presend_minpoll;
int32_t online;
int32_t auto_offline;
uint32_t authkey; uint32_t authkey;
int32_t max_delay; Float max_delay;
int32_t max_delay_ratio; Float max_delay_ratio;
uint32_t flags;
int32_t EOR; int32_t EOR;
} REQ_NTP_Source; } REQ_NTP_Source;
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
int32_t EOR; int32_t EOR;
} REQ_Del_Source; } REQ_Del_Source;
@@ -218,7 +239,7 @@ typedef struct {
} REQ_WriteRtc; } REQ_WriteRtc;
typedef struct { typedef struct {
int32_t dfreq; Float dfreq;
int32_t EOR; int32_t EOR;
} REQ_Dfreq; } REQ_Dfreq;
@@ -250,7 +271,7 @@ typedef struct {
} REQ_CycleLogs; } REQ_CycleLogs;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t bits_specd; uint32_t bits_specd;
} REQ_SubnetsAccessed_Subnet; } REQ_SubnetsAccessed_Subnet;
@@ -263,11 +284,11 @@ typedef struct {
/* This is based on the response size rather than the /* This is based on the response size rather than the
request size */ request size */
#define MAX_CLIENT_ACCESSES 16 #define MAX_CLIENT_ACCESSES 8
typedef struct { typedef struct {
uint32_t n_clients; uint32_t n_clients;
uint32_t client_ips[MAX_CLIENT_ACCESSES]; IPAddr client_ips[MAX_CLIENT_ACCESSES];
} REQ_ClientAccesses; } REQ_ClientAccesses;
typedef struct { typedef struct {
@@ -310,9 +331,18 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline) 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
*/ */
#define PROTO_VERSION_NUMBER 3 #define PROTO_VERSION_NUMBER 4
/* The oldest protocol version that is compatible enough with
the current version to report a version mismatch */
#define PROTO_VERSION_MISMATCH_COMPAT 4
/* ================================================== */ /* ================================================== */
@@ -377,13 +407,6 @@ typedef struct {
#define PERMIT_LOCAL 1 #define PERMIT_LOCAL 1
#define PERMIT_AUTH 2 #define PERMIT_AUTH 2
/* ================================================== */
/* These conversion utilities are used to convert between the internal
and the 'wire' representation of real quantities */
#define WIRE2REAL(x) ((double) ((int32_t) ntohl(x)) / 65536.0)
#define REAL2WIRE(x) (htonl((int32_t)(0.5 + 65536.0 * (x))))
/* ================================================== */ /* ================================================== */
/* Reply codes */ /* Reply codes */
@@ -419,6 +442,9 @@ typedef struct {
#define STT_BADRTCFILE 14 #define STT_BADRTCFILE 14
#define STT_INACTIVE 15 #define STT_INACTIVE 15
#define STT_BADSAMPLE 16 #define STT_BADSAMPLE 16
#define STT_INVALIDAF 17
#define STT_BADPKTVERSION 18
#define STT_BADPKTLENGTH 19
typedef struct { typedef struct {
int32_t EOR; int32_t EOR;
@@ -440,67 +466,65 @@ typedef struct {
#define RPY_SD_ST_OTHER 4 #define RPY_SD_ST_OTHER 4
typedef struct { typedef struct {
uint32_t ip_addr; IPAddr ip_addr;
uint16_t poll; uint16_t poll;
uint16_t stratum; uint16_t stratum;
uint16_t state; uint16_t state;
uint16_t mode; uint16_t mode;
uint32_t since_sample; uint32_t since_sample;
int32_t orig_latest_meas; Float orig_latest_meas;
int32_t latest_meas; Float latest_meas;
uint32_t latest_meas_err; Float latest_meas_err;
int32_t est_offset;
uint32_t est_offset_err;
int32_t resid_freq;
uint32_t resid_skew;
int32_t EOR; int32_t EOR;
} RPY_Source_Data; } RPY_Source_Data;
typedef struct { typedef struct {
uint32_t ref_id; uint32_t ref_id;
IPAddr ip_addr;
uint32_t stratum; uint32_t stratum;
uint32_t ref_time_s; Timeval ref_time;
uint32_t ref_time_us; Float current_correction;
uint32_t current_correction_s; Float freq_ppm;
uint32_t current_correction_us; Float resid_freq_ppm;
int32_t freq_ppm; Float skew_ppm;
int32_t resid_freq_ppm; Float root_delay;
int32_t skew_ppm; Float root_dispersion;
int32_t root_delay;
int32_t root_dispersion;
int32_t EOR; int32_t EOR;
} RPY_Tracking; } RPY_Tracking;
typedef struct { typedef struct {
uint32_t ip_addr; uint32_t ref_id;
IPAddr ip_addr;
uint32_t n_samples; uint32_t n_samples;
uint32_t n_runs; uint32_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
uint32_t sd_us; Float sd;
int32_t resid_freq_ppm; Float resid_freq_ppm;
int32_t skew_ppm; Float skew_ppm;
Float est_offset;
Float est_offset_err;
int32_t EOR; int32_t EOR;
} RPY_Sourcestats; } RPY_Sourcestats;
typedef struct { typedef struct {
uint32_t ref_time; Timeval ref_time;
uint16_t n_samples; uint16_t n_samples;
uint16_t n_runs; uint16_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
int32_t rtc_seconds_fast; Float rtc_seconds_fast;
int32_t rtc_gain_rate_ppm; Float rtc_gain_rate_ppm;
int32_t EOR; int32_t EOR;
} RPY_Rtc; } RPY_Rtc;
typedef struct { typedef struct {
uint32_t centiseconds; uint32_t centiseconds;
int32_t dfreq_ppm; Float dfreq_ppm;
int32_t new_afreq_ppm; Float new_afreq_ppm;
int32_t EOR; int32_t EOR;
} RPY_ManualTimestamp; } RPY_ManualTimestamp;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t bits_specd; uint32_t bits_specd;
uint32_t bitmap[8]; uint32_t bitmap[8];
} RPY_SubnetsAccessed_Subnet; } RPY_SubnetsAccessed_Subnet;
@@ -511,7 +535,7 @@ typedef struct {
} RPY_SubnetsAccessed; } RPY_SubnetsAccessed;
typedef struct { typedef struct {
uint32_t ip; IPAddr ip;
uint32_t client_hits; uint32_t client_hits;
uint32_t peer_hits; uint32_t peer_hits;
uint32_t cmd_hits_auth; uint32_t cmd_hits_auth;
@@ -536,10 +560,10 @@ typedef struct {
#define MAX_MANUAL_LIST_SAMPLES 32 #define MAX_MANUAL_LIST_SAMPLES 32
typedef struct { typedef struct {
uint32_t when; Timeval when;
int32_t slewed_offset; Float slewed_offset;
int32_t orig_offset; Float orig_offset;
int32_t residual; Float residual;
} RPY_ManualListSample; } RPY_ManualListSample;
typedef struct { typedef struct {

View File

@@ -1,4 +1,4 @@
.TH CHRONY 1 "August 10, 2001" chrony "User's Manual" .TH CHRONY 1 "December 04, 2009" chrony "User's Manual"
.SH NAME .SH NAME
chrony \- programs for keeping computer clocks accurate chrony \- programs for keeping computer clocks accurate
@@ -30,7 +30,7 @@ gains or loses time and uses this information to keep it accurate
between measurements from the reference. between measurements from the reference.
The reference time can be derived from either Network Time Protocol The reference time can be derived from either Network Time Protocol
(NTP) servers (preferred), or wristwatch-and-keyboard (via \fIchronyc\fR). (NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
\fIhttp://www.eecis.udel.edu/~ntp\fR. \fIhttp://www.eecis.udel.edu/~ntp\fR.
@@ -49,13 +49,15 @@ On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next) session to the next)
With a good reference clock the accuracy can reach one microsecond.
\fIchronyd\fR can also operate as an RFC1305-compatible NTP server and peer. \fIchronyd\fR can also operate as an RFC1305-compatible NTP server and peer.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chronyc(1), .BR chronyc(1),
.BR chrony(1) .BR chrony(1)
.I http://chrony.sunsite.dk/ .I http://chrony.tuxfamily.org/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

View File

@@ -1,4 +1,4 @@
.TH chrony.conf 5 "August 10, 2001" chrony "Configuration Files" .TH chrony.conf 5 "December 04, 2009" chrony "Configuration Files"
.SH NAME .SH NAME
chrony.conf \- chronyd configuration file chrony.conf \- chronyd configuration file
@@ -37,9 +37,9 @@ useful configuration file would look something like
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chrony(1), .BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chronyd(1) .BR chronyd(8)
.I http://chrony.sunsite.dk/ .I http://chrony.tuxfamily.org/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

View File

@@ -17,7 +17,7 @@ Description: A pair of programs for keeping computer clocks accurate.
Keywords: time NTP RFC1305 RTC adjtime Keywords: time NTP RFC1305 RTC adjtime
Author: rc@rc0.org.uk (Richard Curnow) Author: rc@rc0.org.uk (Richard Curnow)
Maintained-by: rc@rc0.org.uk (Richard Curnow) Maintained-by: rc@rc0.org.uk (Richard Curnow)
Primary-site: sunsite.unc.edu /pub/Linux/system/admin/time Primary-site: chrony.tuxfamily.org
295k chrony-1.18.tar.gz 295k chrony-1.18.tar.gz
2k chrony.lsm 2k chrony.lsm
Platforms: Linux 2.0/2.1/2.2/2.3/2.4 (x86, powerpc) Platforms: Linux 2.0/2.1/2.2/2.3/2.4 (x86, powerpc)

View File

@@ -109,8 +109,8 @@ the RFC did not make absolutely clear. The core algorithms in
@node Getting the software @node Getting the software
@subsection Getting the software @subsection Getting the software
Links on @uref{http://chrony.sunsite.dk/download.php, the Links on @uref{http://chrony.tuxfamily.org, the chrony home page}
chrony home page} describe how to obtain the software. describe how to obtain the software.
@node Platforms @node Platforms
@@ -125,8 +125,9 @@ different quirks in its behaviour.
The software is known to work in the following environments: The software is known to work in the following environments:
@itemize @bullet @itemize @bullet
@item Linux/i386 and Linux/ppc. The software is known to work on Linux 2.0.x, @item Linux on i386, x86_64 and PowerPC architectures. The software is known
2.2.x and 2.4.x. Prior to 2.0.31, the real time clock can't be used. to work on Linux 2.0.x and newer. Prior to 2.0.31, the real time clock can't
be used.
@item NetBSD @item NetBSD
@item BSD/386 @item BSD/386
@@ -203,18 +204,10 @@ integrated into @code{chronyd}.
Things @code{xntpd} can do that @code{chronyd} can't: Things @code{xntpd} can do that @code{chronyd} can't:
@itemize @bullet @itemize @bullet
@item
@code{xntpd} supports a range of different hardware reference clocks
(GPS, atomic etc) that can be connected to a computer to provide a
`stratum-1' server. @code{chronyd} does not support any such hardware
@emph{yet}; I don't have access to any to do any development work.
However, the software architecture should allow such equipment to be
interfaced at a later date.
@item @item
@code{xntpd} supports effectively all of RFC1305, including broadcast / @code{xntpd} supports effectively all of RFC1305, including broadcast /
multicast clients, leap seconds, and extra encryption schemes for multicast clients and extra encryption schemes for authenticating
authenticating data packets. data packets.
@item @item
@code{xntpd} has been ported to more types of computer / operating @code{xntpd} has been ported to more types of computer / operating
@@ -276,29 +269,19 @@ version 2, reproduced in @xref{GPL}.
@node Bug reporting @node Bug reporting
@section Bug reporting and suggestions @section Bug reporting and suggestions
If you think you've found a bug in chrony, or have a suggestion, please let me If you think you've found a bug in chrony, or have a suggestion, please let us
know. My primary current email address is @email{rc@@rc0.org.uk}. If that know. You can join chrony users mailing list by sending a message with the
fails, you could try finding me through one of the chrony mailing lists, or by subject subscribe to @email{chrony-users-request@@chrony.tuxfamily.org}. Only
looking up my name on a search engine. subscribers can post to the list.
I can't promise a timescale to fix a bug; it depends a lot on the how complex When you are reporting a bug, please send us all the information you can.
the bug is to track down, as I have a lot of other calls on my time : 2 young
children, my job, and indeed other free/open source software projects.
However, I do intend to look into problems when time allows.
Another source of information to try is the chrony users mailing list. You can
join this by sending an empty message to
@email{chrony-users-subscribe@@sunsite.dk}. Only subscribers can post to
the list.
When you are reporting a bug, please send me all the information you can.
Unfortunately, chrony has proven to be one of those programs where it is very Unfortunately, chrony has proven to be one of those programs where it is very
difficult to reproduce bugs in a different environment. So I may have to 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 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! pin-point the problem in some cases. Please be patient and plan for this!
Of course, if you can debug the problem yourself and send me a source code Of course, if you can debug the problem yourself and send us a source code
patch to fix it, I will be very grateful! patch to fix it, we will be very grateful!
@c }}} @c }}}
@c {{{ S:Contributions @c {{{ S:Contributions
@@ -309,7 +292,7 @@ Although chrony is now a fairly mature and established project, there are still
areas that could be improved. If you can program in C and have some expertise areas that could be improved. If you can program in C and have some expertise
in these areas, you might be able to fill the gaps. in these areas, you might be able to fill the gaps.
Particular areas I know need addressing are : Particular areas that need addressing are :
@enumerate @enumerate
@item Porting to other Unices @item Porting to other Unices
@@ -331,7 +314,7 @@ setsid() etc with so that chronyd can be automatically started in the system
bootstrap. bootstrap.
@end enumerate @end enumerate
@item Hardware clock support @item More drivers for reference clock support
@item Automation of the trimrtc and writertc mechanisms @item Automation of the trimrtc and writertc mechanisms
@@ -394,13 +377,16 @@ setenv CFLAGS -O
for C-family shells. for C-family shells.
If the software cannot (yet) be built on your system, an error message If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, the files @file{options.h} and will be shown. Otherwise, @file{Makefile} will be generated.
@file{Makefile} will be generated.
By default, chronyc will be built to make use of the readline library. If you If editline or readline library is available, chronyc will be built with line
don't want this, specify the --disable-readline flag to configure. If you have editing support. If you don't want this, specify the --disable-readline flag
readline and/or ncurses installed in a non-standard location, please refer to to configure. Please refer to @pxref{line editing support} for more information.
@pxref{readline support} for information.
If a @file{timepps.h} header is available, 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 @code{CPPFLAGS} variable to @code{-I/path/to/timepps}.
Now type Now type
@@ -438,12 +424,12 @@ to run the @command{install-info} command manually after this step.
@command{install-info} takes 2 arguments. The first is the path to the @command{install-info} takes 2 arguments. The first is the path to the
@file{chrony.info} file you have just installed. This will be the argument you @file{chrony.info} file you have just installed. This will be the argument you
gave to --prefix when you configured (@file{/usr/local} by default), with gave to --prefix when you configured (@file{/usr/local} by default), with
@file{/info/chrony.info} on the end. The second argument is the location of @file{/share/info/chrony.info} on the end. The second argument is the location of
the file called @file{dir}. This will typically be @file{/usr/info/dir}. So the file called @file{dir}. This will typically be @file{/usr/share/info/dir}. So
the typical command line would be the typical command line would be
@example @example
install-info /usr/local/info/chrony.info /usr/info/dir install-info /usr/local/share/info/chrony.info /usr/share/info/dir
@end example @end example
Now that the software is successfully installed, the next step is to Now that the software is successfully installed, the next step is to
@@ -452,32 +438,43 @@ network environment in which the computer operates. Typical scenarios
are described in the following section of the document. are described in the following section of the document.
@c }}} @c }}}
@menu @menu
* readline support:: If readline or ncurses in in a non-standard place * line editing support:: If libraries are in a non-standard place
* package builders:: Extra options useful to package builders * package builders:: Extra options useful to package builders
@end menu @end menu
@c {{{ readline support @c {{{ line editing support
@node readline support @node line editing support
@section Support for the readline library @section Support for line editing libraries
By default, chronyc is built to make use of the readline library. This allows Chronyc can be built with support for line editing, this allows you to use the
you to use the cursor keys to replay and edit old commands. If you don't want cursor keys to replay and edit old commands. Two libraries are supported which
to use readline (in which case chronyc will use a minimal command line provide such functionality, editline and GNU readline.
interface), invoke configure like this:
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:
@example @example
./configure --disable-readline other-options... ./configure --disable-readline other-options...
@end example @end example
If you have readline and/or ncurses installed in locations that aren't normally searched by the compiler and linker, you need extra options if you want readline to be used: 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:
@table @samp @table @samp
@item --with-readline-includes=directory_name @item --with-readline-includes=directory_name
This defines the name of the directory above the one where @file{readline.h} This defines the name of the directory above the one where @file{readline.h}
is. @file{readline.h} is assumed to be in a @file{readline} subdirectory of is. @file{readline.h} is assumed to be in @file{editline} or @file{readline}
the named directory. subdirectory of the named directory.
@item --with-readline-library=directory_name @item --with-readline-library=directory_name
This defines the directory containing the @file{libreadline.a} or This defines the directory containing the @file{libedit.a} or @file{libedit.so}
@file{libreadline.so} file. file, or @file{libreadline.a} or @file{libreadline.so} file.
@item --with-ncurses-library=directory_name @item --with-ncurses-library=directory_name
This defines the directory containing the @file{libncurses.a} or This defines the directory containing the @file{libncurses.a} or
@@ -491,7 +488,7 @@ This defines the directory containing the @file{libncurses.a} or
The configure and make procedures have some extra options that may be useful if The configure and make procedures have some extra options that may be useful if
you are building a distribution package for chrony. you are building a distribution package for chrony.
The --infodir=DIR option to configure specifies a different install directory The --infodir=DIR option to configure specifies an install directory
for the info files. This overrides the @file{info} subdirectory of the for the info files. This overrides the @file{info} subdirectory of the
argument to the --prefix option. For example, you might use argument to the --prefix option. For example, you might use
@@ -499,7 +496,7 @@ argument to the --prefix option. For example, you might use
./configure --prefix=/usr --infodir=/usr/share/info ./configure --prefix=/usr --infodir=/usr/share/info
@end example @end example
The --mandir=DIR option to configure specifies a different install directory The --mandir=DIR option to configure specifies an install directory
for the man pages. This overrides the @file{man} subdirectory of the for the man pages. This overrides the @file{man} subdirectory of the
argument to the --prefix option. argument to the --prefix option.
@@ -1088,10 +1085,23 @@ useful for dial-up systems that are shut down when not in use. For this
to work well, it relies on @code{chronyd} having been able to determine to work well, it relies on @code{chronyd} having been able to determine
accurate statistics for the difference between the real time clock and accurate statistics for the difference between the real time clock and
system clock last time the computer was on. system clock last time the computer was on.
@item -u <user>
When this option is used, chronyd will drop root privileges to the specified
user. So far, it works only on Linux when compiled with capabilities support.
@item -v @item -v
This option displays @code{chronyd's} version number to the terminal and This option displays @code{chronyd's} version number to the terminal and
exits. exits.
@item -P <priority>
This option will select the SCHED_FIFO real-time scheduler at the
specified priority (which must be between 0 and 100). This mode is
supported only on Linux.
@item -m
This option will lock chronyd into RAM so that it will never be paged
out. This mode is only supported on Linux.
@item -4
With this option hostnames will be resolved only to IPv4 addresses.
@item -6
With this option hostnames will be resolved only to IPv6 addresses.
@end table @end table
On systems that support an @file{/etc/rc.local} file for starting On systems that support an @file{/etc/rc.local} file for starting
@@ -1177,13 +1187,18 @@ directives can occur in any order in the file.
* manual directive:: Allow manual entry using chronyc's settime cmd. * manual directive:: Allow manual entry using chronyc's settime cmd.
* maxupdateskew directive:: Stop bad estimates upsetting machine clock * maxupdateskew directive:: Stop bad estimates upsetting machine clock
* noclientlog directive:: Prevent chronyd from gathering data about clients * noclientlog directive:: Prevent chronyd from gathering data about clients
* clientloglimit directive:: Set client log memory limit
* peer directive:: Specify an NTP peer * peer directive:: Specify an NTP peer
* pidfile directive:: Specify the file where chronyd's pid is written * pidfile directive:: Specify the file where chronyd's pid is written
* port directive:: Set port to use for NTP packets * port directive:: Set port to use for NTP packets
* refclock directive:: Specify a reference clock
* rtcdevice directive:: Specify name of enhanced RTC device (if not /dev/rtc) * rtcdevice directive:: Specify name of enhanced RTC device (if not /dev/rtc)
* rtcfile directive:: Specify the file where real-time clock data is stored * rtcfile directive:: Specify the file where real-time clock data is stored
* rtconutc directive:: Specify that the real time clock keeps UTC not local time * rtconutc directive:: Specify that the real time clock keeps UTC not local time
* server directive:: Specify an NTP server * server directive:: Specify an NTP server
* sched_priority directive:: Require real-time scheduling and specify a priority for it.
* lock_all directive:: Require that chronyd be locked into RAM.
@end menu @end menu
@c }}} @c }}}
@c {{{ comments in config file @c {{{ comments in config file
@@ -1241,18 +1256,22 @@ allow 1.2
allow 3.4.5 allow 3.4.5
allow 6.7.8/22 allow 6.7.8/22
allow 6.7.8.9/22 allow 6.7.8.9/22
allow 2001:db8::/32
allow 0/0
allow ::/0
allow allow
@end example @end example
The first command allows the named node to be an NTP client of this computer. The first command allows the named node to be an NTP client of this computer.
The second command allows any node with an IP address of the form 1.2.x.y (with The second command allows any node with an IPv4 address of the form 1.2.x.y (with
x and y arbitrary) to be an NTP client of this computer. Likewise, the third x and y arbitrary) to be an NTP client of this computer. Likewise, the third
command allows any node with an IP address of the form 3.4.5.x to have client command allows any node with an IPv4 address of the form 3.4.5.x to have client
NTP access. The fourth and fifth forms allow access from any node with an IP NTP access. The fourth and fifth forms allow access from any node with an IPv4
address of the form 6.7.8.x, 6.7.9.x, 6.7.10.x or 6.7.11.x (with x arbitrary), address of the form 6.7.8.x, 6.7.9.x, 6.7.10.x or 6.7.11.x (with x arbitrary),
i.e. the value 22 is the number of bits defining the specified subnet. (In the i.e. the value 22 is the number of bits defining the specified subnet. (In the
fifth form, the final byte is ignored). The sixth form allows access by any fifth form, the final byte is ignored). The sixth form is used for IPv6
node on the entire Internet. addresses. The seventh and eighth forms allow access by any IPv4 and IPv6 node
respectively. The ninth forms allows access by any node (IPv4 or IPv6).
A second form of the directive, @code{allow all}, has a greater effect, A second form of the directive, @code{allow all}, has a greater effect,
depending on the ordering of directives in the configuration file. To depending on the ordering of directives in the configuration file. To
@@ -1318,6 +1337,9 @@ firewalls). It is, therefore, not particularly useful. Use of the
@code{allow} and @code{deny} directives together with a network firewall is @code{allow} and @code{deny} directives together with a network firewall is
more likely to be successful. more likely to be successful.
For each of IPv4 and IPv6 protocols, only one @code{bindaddress}
directive can be specified.
@c }}} @c }}}
@c {{{ bindcmdaddress @c {{{ bindcmdaddress
@node bindcmdaddress directive @node bindcmdaddress directive
@@ -1342,6 +1364,9 @@ interfaces. It is, therefore, not particularly useful. Use of the
@code{cmdallow} and @code{cmddeny} directives together with a network firewall @code{cmdallow} and @code{cmddeny} directives together with a network firewall
is more likely to be successful. is more likely to be successful.
For each of IPv4 and IPv6 protocols, only one @code{bindcmdaddress}
directive can be specified.
@c }}} @c }}}
@c {{{ broadcast directive @c {{{ broadcast directive
@node broadcast directive @node broadcast directive
@@ -1356,6 +1381,7 @@ The syntax is as follows
@example @example
broadcast 30 192.168.1.255 broadcast 30 192.168.1.255
broadcast 60 192.168.2.255 12123 broadcast 60 192.168.2.255 12123
broadcast 60 ff02::101
@end example @end example
In the first example, the destination port defaults to 123/udp (the normal NTP In the first example, the destination port defaults to 123/udp (the normal NTP
@@ -1525,8 +1551,9 @@ An example of the command is
dumpdir /var/log/chrony dumpdir /var/log/chrony
@end example @end example
A source whose IP address is 1.2.3.4 would have its measurement A source whose reference id (the IP address for IPv4 sources) is
history saved in the file @file{/var/log/chrony/1.2.3.4.dat}. 1.2.3.4 would have its measurement history saved in the file
@file{/var/log/chrony/1.2.3.4.dat}.
@c }}} @c }}}
@c {{{ dumponexit @c {{{ dumponexit
@node dumponexit directive @node dumponexit directive
@@ -1729,6 +1756,10 @@ rate, and any slews made, to a file called tracking.log.
@item rtc @item rtc
This option logs information about the system's real-time clock. This option logs information about the system's real-time clock.
@item refclocks
This option logs the raw reference clock measurements to a file
called refclocks.log.
@end table @end table
The files are written to the directory specified by the logdir The files are written to the directory specified by the logdir
@@ -1745,6 +1776,7 @@ log measurements statistics tracking
* statistics log:: The format of the statistics log * statistics log:: The format of the statistics log
* tracking log:: The format of the tracking log * tracking log:: The format of the tracking log
* RTC log:: The format of the RTC log * RTC log:: The format of the RTC log
* refclocks log:: The format of the refclocks log
@end menu @end menu
@c }}} @c }}}
@c {{{ measurements.log @c {{{ measurements.log
@@ -1771,8 +1803,8 @@ expressed in UTC, not the local time zone.
@item @item
IP address of server/peer from which measurement comes [158.152.1.76] IP address of server/peer from which measurement comes [158.152.1.76]
@item @item
Leap status (@code{N} means normal, @code{-} means that the last minute Leap status (@code{N} means normal, @code{+} means that the last minute
of today has 61 seconds, @code{+} means that the last minute of the day of today has 61 seconds, @code{-} means that the last minute of the day
has 59 seconds, @code{?} means the remote computer is not currently has 59 seconds, @code{?} means the remote computer is not currently
synchronised.) [N] synchronised.) [N]
@item @item
@@ -1958,6 +1990,47 @@ The measurement interval used prior to the measurement being made (in
seconds). [120] seconds). [120]
@end enumerate @end enumerate
A banner is periodically written to the log file to indicate the
meanings of the columns.
@c }}}
@c {{{ refclocks.log
@node refclocks log
@subsubsection Refclocks log file format
An example line (which actually appears as a single line in the file)
from the refclocks log file is shown below.
@example
2009-11-30 14:33:27.000000 PPS2 7 N 1 4.900000e-07 -6.741777e-07
@end example
The columns are as follows (the quantities in square brackets are the
values from the example line above) :
@enumerate 1
@item
Date [2009-11-30]
@item
Hour:Minute:Second.Microsecond [14:33:27.000000]. Note that the
date/time pair is expressed in UTC, not the local time zone.
@item
Reference ID of refclock from which measurement comes. [PPS2]
@item
Sequence number of driver poll within one polling interval. [7]
@item
Leap status (@code{N} means normal, @code{+} means that the last minute
of today has 61 seconds, @code{-} means that the last minute of the day
has 59 seconds). [N]
@item
Flag indicating whether the sample comes from PPS source. (1 for yes,
0 for no). [1]
@item
Local clock error measured by refclock driver. [4.900000e-07]
@item
Local clock error with applied corrections. Positive indicates
that the local clock is slow. [-6.741777e-07]
@end enumerate
A banner is periodically written to the log file to indicate the A banner is periodically written to the log file to indicate the
meanings of the columns. meanings of the columns.
@c }}} @c }}}
@@ -2066,6 +2139,21 @@ This directive, which takes no arguments, specifies that client accesses
are not to be logged. Normally they are logged, allowing statistics to are not to be logged. Normally they are logged, allowing statistics to
be reported using the @code{clients} command in @code{chronyc}. be reported using the @code{clients} command in @code{chronyc}.
@c }}} @c }}}
@c {{{ clientloglimit
@node clientloglimit directive
@subsection clientloglimit
This directive specifies the maximum size of the memory allocated to
log client accesses. When the limit is reached, only information for
clients that have already been logged will be updated. If 0 is
specified, the memory size will be unlimited. The default is 524288
bytes.
An example of the use of this directive is
@example
clientloglimit 1048576
@end example
@c }}}
@c {{{ peer @c {{{ peer
@node peer directive @node peer directive
@subsection peer @subsection peer
@@ -2101,6 +2189,91 @@ port 11123
This would change the NTP port served by chronyd on the computer to This would change the NTP port served by chronyd on the computer to
udp/11123. udp/11123.
@c }}}
@c {{{ refclock
@node refclock directive
@subsection refclock
The @code{refclock} directive allows reference clocks to be specified.
The directive is immediately followed by a refclock driver name and
its parameter.
There are currently three drivers implemented:
@table @code
@item PPS
Pulse per second (PPS) API driver. The parameter is a path to the PPS
device. Assert events are used by default. The path can have
:1 appended to use clear events instead.
PPS refclock needs another source (NTP or non-PPS refclock) or local
directive (@pxref{local directive}) enabled to function. For example:
@example
refclock SHM 0 offset 0.5 delay 0.1
refclock PPS /dev/pps0
@end example
@item SHM
NTP shared memory driver. The parameter is the number of the
shared memory segment that should be used to read timestamps, usually
0, 1, 2 or 3. For example:
@example
refclock SHM 1 poll 3 refid GPS1
@end example
Software that can be used as a source of timestamps includes
@code{gpsd} and @code{shmpps}.
@item SOCK
Unix domain socket driver. The parameter is a path to the socket
which is used as the source of timestamps. This is as a better
alternative to SHM, it does not require polling, the offset
resolution is not limited to microsecond and it supports PPS.
The format for messages sent over the socket is declared in file
@code{refclock_sock.c}.
@end table
The @code{refclock} command also supports a number of subfields (which
may be defined in any order):
@table @code
@item poll
Timestamps produced by refclock drivers are not used immediately, but
they are stored and processed by a median filter in intervals
specified by this option. This is defined as a power of 2. The
default is 4 (16 seconds). A shorter interval allows @code{chronyd}
to react faster to frequency changes, but it may increase noise.
@item dpoll
Some drivers are not controlled by external events and thus require
polling. Again this is defined as a power of 2 and can be negative
for sub-second intervals. The default is 0 (1 second).
@item refid
This option is used to specify a reference id of the refclock, as up
to four ASCII characters. By default, first three characters from
driver name and the number of the refclock are used as refid. Each
refclock has to use an unique refid.
@item filter
This option sets the length of the median filter which is used to
reduce noise. With each poll about half of the stored samples are
discarded and one final sample is calculated as average of the
remaining samples. The default is 15.
@item rate
PPS signal frequency (in Hz). This option only controls how the
received pulses are aligned. To actually receive more than one
pulse per second, a negative @code{dpoll} has to be specified (-3 for
5Hz signal). The default is 1.
@item offset
This option can be used to compensate a constant error. The specified
offset (in seconds) is applied to all samples produced by the
refclock. The default is 0.0.
@item delay
This option is used to specify how the refclock is assumed
to be inaccurate (in seconds). Increasing the value is useful to
avoid having no majority in the source selection algorithm or to make
the algorithm prefer other refclocks. The default is 1e-9 (1
nanosecond).
@end table
@c }}} @c }}}
@c {{{ rtcdevice @c {{{ rtcdevice
@node rtcdevice directive @node rtcdevice directive
@@ -2174,6 +2347,37 @@ If the @code{rtconutc} directive appears, it means the RTC is required
to keep UTC. The directive takes no arguments. It is equivalent to to keep UTC. The directive takes no arguments. It is equivalent to
specifying the @code{-u} switch to the Linux @file{/sbin/clock} program. specifying the @code{-u} switch to the Linux @file{/sbin/clock} program.
@c }}} @c }}}
@c {{{ sched_priority
@node sched_priority directive
@subsection sched_priority
The @code{sched_priority} directive will select the SCHED_FIFO real-time
scheduler at the specified priority (which must be between 0 and 100).
This mode is supported only on Linux.
This directive uses the Linux sched_setscheduler() system call to
instruct the kernel to use the SCHED_FIFO first-in, first-out
real-time scheduling policy for Chronyd with the specified priority.
This means that whenever Chronyd is ready to run it will run,
interrupting whatever else is running unless it is a higher priority
real-time process. This should not impact performance as Chronyd's
resource requirements are modest, but it should result in lower and
more consistent latency since Chronyd will not need to wait for the
scheduler to get around to running it. You should not use this unless
you really need it. The sched_setscheduler man page has more details.
@c }}}
@c {{{ lock_all
@node lock_all directive
@subsection lock_all
The @code{lock_all} directive will lock chronyd into RAM so that it
will never be paged out. This mode is only supported on Linux. This
directive uses the Linux mlockall() system call to prevent Chronyd
from ever being swapped out. This should result in lower and more
consistent latency. It should not have significant impact on
performance as Chronyd's memory usage is modest. The mlockall man
page has more details.
@c }}}
@c {{{ server @c {{{ server
@node server directive @node server directive
@subsection server @subsection server
@@ -2183,9 +2387,8 @@ synchronise its system time to that of the server, but the server's
system time will never be influenced by that of a client. system time will never be influenced by that of a client.
The @code{server} directive is immediately followed by either the name The @code{server} directive is immediately followed by either the name
of the server, or its IP address in dotted-quad notation. The server of the server, or its IP address. The server command also supports a
command also supports a number of subfields (which may be defined in any number of subfields (which may be defined in any order):
order):
@table @code @table @code
@item port @item port
@@ -2341,6 +2544,12 @@ This option allows the user to specify the UDP port number which the
target @code{chronyd} is using for its command & monitoring connections. target @code{chronyd} is using for its command & monitoring connections.
This defaults to the compiled-in default; there would rarely be a need This defaults to the compiled-in default; there would rarely be a need
to change this. to change this.
@item -n
This option disables resolving IP addresses to hostnames.
@item -4
With this option hostnames will be resolved only to IPv4 addresses.
@item -6
With this option hostnames will be resolved only to IPv6 addresses.
@end table @end table
@c }}} @c }}}
@c {{{ SS:Security with chronyc @c {{{ SS:Security with chronyc
@@ -2377,6 +2586,7 @@ Only the following commands can be used @emph{without} providing a
password: password:
@itemize @bullet @itemize @bullet
@item @code{dns}
@item @code{exit} @item @code{exit}
@item @code{help} @item @code{help}
@item @code{password} @item @code{password}
@@ -2416,6 +2626,7 @@ interface.
* delete command:: Remove an NTP server or peer * delete command:: Remove an NTP server or peer
* deny command :: Denying NTP client access * deny command :: Denying NTP client access
* deny all command:: Denying NTP client access * deny all command:: Denying NTP client access
* dns command:: Configure how are hostnames and IP addresses resolved
* dump command:: Dump measurement histories to files * dump command:: Dump measurement histories to files
* exit command:: Exit from chronyc * exit command:: Exit from chronyc
* help command:: Generate help summary * help command:: Generate help summary
@@ -2452,6 +2663,7 @@ follows:
@example @example
accheck a.b.c accheck a.b.c
accheck 1.2.3.4 accheck 1.2.3.4
accheck 2001:db8::1
@end example @end example
This command can be used to examine the effect of a series of This command can be used to examine the effect of a series of
@@ -2526,6 +2738,9 @@ allow 1.2
allow 3.4.5 allow 3.4.5
allow 6.7.8/22 allow 6.7.8/22
allow 6.7.8.9/22 allow 6.7.8.9/22
allow 2001:db8:789a::/48
allow 0/0
allow ::/0
allow allow
@end example @end example
@@ -2542,7 +2757,7 @@ directive in the configuration file (@pxref{allow directive}).
@node burst command @node burst command
@subsubsection burst @subsubsection burst
The @code{burst} command tells @code{chronyd} to make a set of measurements to The @code{burst} command tells @code{chronyd} to make a set of measurements to
each of its sources over a short duration (rather than the usual each of its NTP sources over a short duration (rather than the usual
periodic measurements that it makes). After such a burst, @code{chronyd} will periodic measurements that it makes). After such a burst, @code{chronyd} will
revert to the previous state for each source. This might be either revert to the previous state for each source. This might be either
online, if the source was being periodically measured in the normal way, online, if the source was being periodically measured in the normal way,
@@ -2554,6 +2769,7 @@ The syntax of the burst command is as follows
@example @example
burst <n-good-measurements>/<max-measurements> [<mask>/<masked-address>] burst <n-good-measurements>/<max-measurements> [<mask>/<masked-address>]
burst <n-good-measurements>/<max-measurements> [<masked-address>/<masked-bits>]
@end example @end example
The mask and masked-address arguments are optional, in which case The mask and masked-address arguments are optional, in which case
@@ -2575,18 +2791,21 @@ attempt to make, even if the required number of good measurements has
not been obtained. not been obtained.
@item mask @item mask
This is a dotted quad argument (e.g. @code{255.255.255.0}) with which This is an IP address with which the IP address of each of @code{chronyd}'s
the IP address of each of @code{chronyd}'s sources is to be masked. sources is to be masked.
@item masked-address @item masked-address
This is a dotted quad argument (e.g. @code{1.2.3.0}). If the masked IP This is an IP address. If the masked IP address of a source matches this value
address of a source matches this value then the burst command is applied then the burst command is applied to that source.
to that source.
@item masked-bits
This can be used with @code{masked-address} for CIDR notation, which is a
shorter alternative to the form with mask.
@end table @end table
If no mask or masked address arguments are provided, the default is If no mask or masked address arguments are provided, every source will
@code{0.0.0.0} and @code{0.0.0.0} respectively, which will match every be matched.
source.
An example of the two-argument form of the command is An example of the two-argument form of the command is
@@ -2598,15 +2817,17 @@ This will cause @code{chronyd} to attempt to get two good measurements from
each source, stopping after two have been obtained, but in no event will each source, stopping after two have been obtained, but in no event will
it try more than ten probes to the source. it try more than ten probes to the source.
An example of the four-argument form of the command is Examples of the four-argument form of the command are
@example @example
burst 2/10 255.255.0.0/1.2.0.0 burst 2/10 255.255.0.0/1.2.0.0
burst 2/10 2001:db8:789a::/48
@end example @end example
In this case, the two out of ten sampling will only be applied to In the first case, the two out of ten sampling will only be applied to
sources whose IP addresses are of the form @code{1.2.x.y}, where x and y sources whose IPv4 addresses are of the form @code{1.2.x.y}, where x and y
are arbitrary. are arbitrary. In the second case, the sampling will be applied to sources
whose IPv6 addresses have first 48 bits equal to @code{2001:db8:789a}.
@c }}} @c }}}
@c {{{ clients @c {{{ clients
@node clients command @node clients command
@@ -2671,6 +2892,7 @@ Examples of use are as follows:
@example @example
cmdaccheck a.b.c cmdaccheck a.b.c
cmdaccheck 1.2.3.4 cmdaccheck 1.2.3.4
cmdaccheck 2001:db8::1
@end example @end example
@c }}} @c }}}
@c {{{ cmdallow @c {{{ cmdallow
@@ -2733,6 +2955,7 @@ The syntax is illustrated in the examples below.
@example @example
delete foo.bar.com delete foo.bar.com
delete 1.2.3.4 delete 1.2.3.4
delete 2001:db8::1
@end example @end example
There is one parameter, the name or IP address of the server or peer to There is one parameter, the name or IP address of the server or peer to
@@ -2752,6 +2975,9 @@ deny 1.2
deny 3.4.5 deny 3.4.5
deny 6.7.8/22 deny 6.7.8/22
deny 6.7.8.9/22 deny 6.7.8.9/22
deny 2001:db8:789a::/48
deny 0/0
deny ::/0
deny deny
@end example @end example
@c }}} @c }}}
@@ -2761,6 +2987,32 @@ deny
The effect of the allow command is identical to the @code{deny all} The effect of the allow command is identical to the @code{deny all}
directive in the configuration file (@pxref{deny directive}). directive in the configuration file (@pxref{deny directive}).
@c }}} @c }}}
@c {{{ dns
@node dns command
@subsubsection dns
The @code{dns} command configures how are hostnames and IP addresses resolved in
@code{chronyc}. IP addresses can be resolved to hostnames when printing results
of @code{sources}, @code{sourcestats}, @code{tracking} and @code{clients}
commands. Hostnames are resolved in commands that take an address as argument.
There are five forms of the command:
@table @code
@item dns -n
Disables resolving IP addresses to hostnames. Raw IP addresses will be
displayed.
@item dns +n
Enables resolving IP addresses to hostnames. This is the default unless
@code{chronyc} was started with @code{-n} option.
@item dns -4
Resolves hostnames only to IPv4 addresses.
@item dns -6
Resolves hostnames only to IPv6 addresses.
@item dns -46
Resolves hostnames to both address families. This is the default unless
@code{chronyc} was started with @code{-4} or @code{-6} option.
@end table
@c }}}
@c {{{ dump @c {{{ dump
@node dump command @node dump command
@subsubsection dump @subsubsection dump
@@ -2904,12 +3156,14 @@ The following examples illustrate the syntax
@example @example
maxdelay foo.bar.com 0.3 maxdelay foo.bar.com 0.3
maxdelay 1.2.3.4 0.0015 maxdelay 1.2.3.4 0.0015
maxdelay 2001:db8::1 0.0015
@end example @end example
The first example sets the maximum network delay allowed for a The first example sets the maximum network delay allowed for a
measurement to the host @code{foo.bar.com} to 0.3 seconds. The second measurement to the host @code{foo.bar.com} to 0.3 seconds. The second
example sets the maximum network delay for a measurement to the host and third examples set the maximum network delay for a measurement to
with IP address @code{1.2.3.4} to 1.5 milliseconds. the host with IPv4 address @code{1.2.3.4} and the host with IPv6 address
@code{2001:db8::1} to 1.5 milliseconds.
(Any measurement whose network delay exceeds the specified value is (Any measurement whose network delay exceeds the specified value is
discarded.) discarded.)
@@ -2927,13 +3181,15 @@ The following examples illustrate the syntax
@example @example
maxdelayratio foo.bar.com 1.5 maxdelayratio foo.bar.com 1.5
maxdelayratio 1.2.3.4 2.0 maxdelayratio 1.2.3.4 2.0
maxdelayratio 2001:db8::1 2.0
@end example @end example
The first example sets the maximum network delay for a measurement to The first example sets the maximum network delay for a measurement to
the host @code{foo.bar.com} to be 1.5 times the minimum delay found the host @code{foo.bar.com} to be 1.5 times the minimum delay found
amongst the previous measurements that have been retained. The second amongst the previous measurements that have been retained. The second
example sets the maximum network delay for a measurement to the host and third examples set the maximum network delay for a measurement to
with IP address @code{1.2.3.4} to be double the retained minimum. the host with IPv4 address @code{1.2.3.4} and the host with IPv6
address @code{2001:db8::1} to be double the retained minimum.
As for @code{maxdelay}, any measurement whose network delay is too large As for @code{maxdelay}, any measurement whose network delay is too large
will be discarded. will be discarded.
@@ -2952,7 +3208,7 @@ The syntax is as follows
maxpoll <host> <new-maxpoll> maxpoll <host> <new-maxpoll>
@end example @end example
where the host can be specified as either a machine name or dotted-quad where the host can be specified as either a machine name or
IP address. The new minimum poll is specified as a base-2 logarithm of IP address. The new minimum poll is specified as a base-2 logarithm of
the number of seconds between polls (e.g. specify 6 for 64 second the number of seconds between polls (e.g. specify 6 for 64 second
sampling). sampling).
@@ -2989,7 +3245,7 @@ The syntax is as follows
minpoll <host> <new-minpoll> minpoll <host> <new-minpoll>
@end example @end example
where the host can be specified as either a machine name or dotted-quad where the host can be specified as either a machine name or
IP address. The new minimum poll is specified as a base-2 logarithm of IP address. The new minimum poll is specified as a base-2 logarithm of
the number of seconds between polls (e.g. specify 6 for 64 second the number of seconds between polls (e.g. specify 6 for 64 second
sampling). sampling).
@@ -3056,24 +3312,29 @@ the @code{offline} command being used, @code{chronyd} would assume that the
source had failed and would attempt to pick another synchronisation source had failed and would attempt to pick another synchronisation
source. source.
There are two forms of the @code{offline} command. The first form is a There are three forms of the @code{offline} command. The first form is a
wildcard, meaning all sources. The second form allows a IP address mask wildcard, meaning all sources. The second form allows a IP address mask
and a masked address to be specified. These forms are illustrated below. and a masked address to be specified. The third form uses the CIDR
notation. These forms are illustrated below.
@example @example
offline offline
offline 255.255.255.0/1.2.3.0 offline 255.255.255.0/1.2.3.0
offline 2001:db8:789a::/48
@end example @end example
The second form means that the @code{offline} command is to be applied The second form means that the @code{offline} command is to be applied
to any source whose IP address is in the 1.2.3 subnet. (The host's to any source whose IPv4 address is in the @code{1.2.3} subnet. (The host's
address is logically and-ed with the mask, and if the result matches the address is logically and-ed with the mask, and if the result matches the
masked-address the host is processed). masked-address the host is processed). The third form means that the
command is to be applied to all sources whose IPv6 addresses have first
48 bits equal to @code{2001:db8:789a}.
The wildcard form of the address is actually equivalent to The wildcard form of the address is actually equivalent to
@example @example
offline 0.0.0.0/0.0.0.0 offline 0.0.0.0/0.0.0.0
offline ::/0
@end example @end example
@c }}} @c }}}
@c {{{ online @c {{{ online
@@ -3240,8 +3501,7 @@ The columns are as follows:
@item M @item M
This indicates the mode of the source. @code{^} means a server, This indicates the mode of the source. @code{^} means a server,
@code{=} means a peer and @code{#} indicates a locally connected @code{=} means a peer and @code{#} indicates a locally connected
reference clock@footnote{In the current version this will never be reference clock.
shown, because @code{chronyd} has no support for reference clocks yet.}.
@item S @item S
This column indicates the state of the sources. @code{*} indicates the This column indicates the state of the sources. @code{*} indicates the
@@ -3254,7 +3514,8 @@ appears to have too much variability. The @code{~} condition is also
shown at start-up, until at least 3 samples have been gathered from it. shown at start-up, until at least 3 samples have been gathered from it.
@item Name/IP address @item Name/IP address
This shows the name or the IP address of the source. This shows the name or the IP address of the source, or refid for
reference clocks.
@item Stratum @item Stratum
This shows the stratum of the source, as reported in its most recently This shows the stratum of the source, as reported in its most recently
@@ -3279,7 +3540,8 @@ source. This is normally in seconds. The letters @code{m}, @code{h},
@item Last sample @item Last sample
This column shows the offset between the local clock and the source at This column shows the offset between the local clock and the source at
the last measurement. The number in the square brackets shows the the last measurement. The number in the square brackets shows the
actual measured offset. This may be suffixed by @code{us} (indicating actual measured offset. This may be suffixed by @code{ns} (indicating
nanoseconds), @code{us} (indicating
microseconds), @code{ms} (indicating milliseconds), or @code{s} microseconds), @code{ms} (indicating milliseconds), or @code{s}
(indicating seconds). The number to the left of the square brackets (indicating seconds). The number to the left of the square brackets
shows the original measurement, adjusted to allow for any slews applied shows the original measurement, adjusted to allow for any slews applied
@@ -3307,9 +3569,9 @@ An example report is
@example @example
@group @group
210 Number of sources = 1 210 Number of sources = 1
Name/IP Address NP NR Span Frequency Freq Skew Std Dev Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
======================================================================== ===============================================================================
abc.def.ghi 11 5 46m -0.001 0.045 25us abc.def.ghi 11 5 46m -0.001 0.045 1us 25us
@end group @end group
@end example @end example
@@ -3317,8 +3579,8 @@ The columns are as follows
@table @code @table @code
@item Name/IP Address @item Name/IP Address
This is the name or dotted-quad IP address of the NTP server (or peer) This is the name or IP address of the NTP server (or peer) or refid of
to which the rest of the line relates. the refclock to which the rest of the line relates.
@item NP @item NP
This is the number of sample points currently being retained for the This is the number of sample points currently being retained for the
@@ -3347,6 +3609,9 @@ million. In this case, the computer's clock is estimated to be running
This is the estimated error bounds on @code{Freq} (again in parts per This is the estimated error bounds on @code{Freq} (again in parts per
million). million).
@item Offset
This is the estimated offset of the source.
@item Std Dev @item Std Dev
This is the estimated sample standard deviation. This is the estimated sample standard deviation.
@@ -3362,7 +3627,7 @@ performance. An example of the output is shown below.
Reference ID : 1.2.3.4 (a.b.c) Reference ID : 1.2.3.4 (a.b.c)
Stratum : 3 Stratum : 3
Ref time (UTC) : Sun May 17 06:13:11 1998 Ref time (UTC) : Sun May 17 06:13:11 1998
System time : 0.000000 seconds fast of NTP time System time : 0.000000000 seconds fast of NTP time
Frequency : 331.898 ppm fast Frequency : 331.898 ppm fast
Residual freq : 0.004 ppm Residual freq : 0.004 ppm
Skew : 0.154 ppm Skew : 0.154 ppm
@@ -3374,7 +3639,7 @@ The fields are explained as follows.
@table @code @table @code
@item Reference ID @item Reference ID
This is the IP address, and name if available, of the server to which This is the refid and name (or IP address) if available, of the server to which
the computer is currently synchronised. If this is @code{127.127.1.1} the computer is currently synchronised. If this is @code{127.127.1.1}
it means the computer is not synchronised to any external source and it means the computer is not synchronised to any external source and
that you have the `local' mode operating (via the @code{local} command that you have the `local' mode operating (via the @code{local} command
@@ -3640,8 +3905,8 @@ the system clock is periodically reset to the real-time clock.
@center GNU GENERAL PUBLIC LICENSE @center GNU GENERAL PUBLIC LICENSE
@center Version 2, June 1991 @center Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -3654,7 +3919,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to the GNU Lesser General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
@@ -3918,7 +4183,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest 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 possible use to the public, the best way to achieve this is to make it
@@ -3930,7 +4195,7 @@ 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. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -3942,16 +4207,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. 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 If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.
@@ -3974,7 +4239,7 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. Public License instead of this License.
@c }}} @c }}}
@contents @contents

View File

@@ -39,6 +39,7 @@ struct timex {
#define ADJ_STATUS 0x0010 /* clock status */ #define ADJ_STATUS 0x0010 /* clock status */
#define ADJ_TICK 0x4000 /* tick value */ #define ADJ_TICK 0x4000 /* tick value */
#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
#define SHIFT_USEC 16 /* frequency offset scale (shift) */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */

View File

@@ -1,4 +1,4 @@
.TH CHRONYC 1 "August 10, 2001" chrony "User's Manual" .TH CHRONYC 1 "December 04, 2009" chrony "User's Manual"
.SH NAME .SH NAME
chronyc \- command-line interface for chronyd chronyc \- command-line interface for chronyd
@@ -31,22 +31,29 @@ specify port-number
.TP .TP
\fB\-n\fR \fB\-n\fR
display raw IP addresses (don't attempt to look up hostnames) display raw IP addresses (don't attempt to look up hostnames)
.TP \fIcommand\fR .TP
\fB\-4\fR
resolve hostnames only to IPv4 addresses
.TP
\fB\-6\fR
resolve hostnames only to IPv6 addresses
.TP
\fIcommand\fR
specify command. If no command is given, chronyc will read commands specify command. If no command is given, chronyc will read commands
interactively. interactively.
.SH VERSION .SH VERSION
1.17 1.24
.SH BUGS .SH BUGS
To report bugs, please contact the author and/or visit \fIhttp://chrony.sunsite.dk/\fR To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chronyd(8), .BR chronyd(8),
.BR chrony(1) .BR chrony(1)
.I http://chrony.sunsite.dk/ .I http://chrony.tuxfamily.org/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

View File

@@ -1,4 +1,4 @@
.TH CHRONYD 8 "August 10, 2001" chrony "System Administration" .TH CHRONYD 8 "December 04, 2009" chrony "System Administration"
.SH NAME .SH NAME
chronyd \- chrony background daemon chronyd \- chrony background daemon
@@ -35,6 +35,15 @@ Information messages and warnings will be logged to syslog.
.SH OPTIONS .SH OPTIONS
A summary of the options supported by \fBchronyd\fR is included below. A summary of the options supported by \fBchronyd\fR is included below.
.TP
\fB\-P\fR \fIpriority\fR
This option will select the SCHED_FIFO real-time scheduler at the specified
priority (which must be between 0 and 100). This mode is supported only on
Linux.
.TP
.B \-m
This option will lock chronyd into RAM so that it will never be paged out.
This mode is only supported on Linux.
.TP .TP
.B \-d .B \-d
When run in this mode, the program will not detach itself from the When run in this mode, the program will not detach itself from the
@@ -79,17 +88,27 @@ been able to determine accurate statistics for the difference
between the real time clock and system clock last time the between the real time clock and system clock last time the
computer was on. computer was on.
.TP .TP
\fB\-u\fR \fIuser\fR
When this option is used, chronyd will drop root privileges to the specified
user. So far, it works only on Linux when compiled with capabilities support.
.TP
.B \-v .B \-v
This option displays \fBchronyd\fR's version number to the terminal and exits This option displays \fBchronyd\fR's version number to the terminal and exits
.TP
.B \-4
Resolve hostnames only to IPv4 addresses.
.TP
.B \-6
Resolve hostnames only to IPv6 addresses.
.SH FILES .SH FILES
\fI/etc/chrony.conf\fR \fI/etc/chrony.conf\fR
.SH VERSION .SH VERSION
Version 1.17 Version 1.24
.SH BUGS .SH BUGS
To report bugs, please contact the author and/or visit \fIhttp://chrony.sunsite.dk/\fR To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR
.SH "SEE ALSO" .SH "SEE ALSO"
\fBchronyd\fR is documented in detail in the documentation supplied with the \fBchronyd\fR is documented in detail in the documentation supplied with the

1224
client.c

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -40,6 +41,7 @@
#include "memory.h" #include "memory.h"
#include "reports.h" #include "reports.h"
#include "util.h" #include "util.h"
#include "logging.h"
/* Number of bits of address per layer of the table. This value has /* Number of bits of address per layer of the table. This value has
been chosen on the basis that a server will predominantly be serving been chosen on the basis that a server will predominantly be serving
@@ -52,7 +54,7 @@
#define TABLE_SIZE (1UL<<NBITS) #define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node { typedef struct _Node {
unsigned long ip_addr; IPAddr ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_bad; unsigned long cmd_hits_bad;
@@ -68,8 +70,10 @@ typedef struct _Subnet {
/* ================================================== */ /* ================================================== */
/* Table for the class A subnet */ /* Table for the IPv4 class A subnet */
static Subnet top_subnet; static Subnet top_subnet4;
/* Table for IPv6 */
static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been /* Table containing pointers directly to all nodes that have been
allocated. */ allocated. */
@@ -81,13 +85,46 @@ static int n_nodes = 0;
/* Number of entries for which the table has been sized. */ /* Number of entries for which the table has been sized. */
static int max_nodes = 0; static int max_nodes = 0;
#define NODE_TABLE_INCREMENT 4
/* Flag indicating whether facility is turned on or not */ /* Flag indicating whether facility is turned on or not */
static int active = 0; static int active = 0;
/* Flag indicating whether memory allocation limit has been reached
and no new nodes or subnets should be allocated */
static int alloc_limit_reached;
static unsigned long alloc_limit;
static unsigned long alloced;
/* ================================================== */ /* ================================================== */
static void
split_ip6(IPAddr *ip, uint32_t *dst)
{
int i;
for (i = 0; i < 4; i++)
dst[i] = ip->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);
}
/* ================================================== */
static void static void
clear_subnet(Subnet *subnet) clear_subnet(Subnet *subnet)
{ {
@@ -117,7 +154,8 @@ clear_node(Node *node)
void void
CLG_Initialise(void) CLG_Initialise(void)
{ {
clear_subnet(&top_subnet); clear_subnet(&top_subnet4);
clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) { if (CNF_GetNoClientLog()) {
active = 0; active = 0;
} else { } else {
@@ -128,6 +166,9 @@ CLG_Initialise(void)
max_nodes = 0; max_nodes = 0;
n_nodes = 0; n_nodes = 0;
alloced = 0;
alloc_limit = CNF_GetClientLogLimit();
alloc_limit_reached = 0;
} }
/* ================================================== */ /* ================================================== */
@@ -140,11 +181,25 @@ CLG_Finalise(void)
/* ================================================== */ /* ================================================== */
static void check_alloc_limit() {
if (alloc_limit_reached)
return;
if (alloced >= alloc_limit) {
LOG(LOGS_WARN, LOGF_ClientLog, "Client log memory limit reached");
alloc_limit_reached = 1;
}
}
/* ================================================== */
static void static void
create_subnet(Subnet *parent_subnet, int the_entry) create_subnet(Subnet *parent_subnet, int the_entry)
{ {
parent_subnet->entry[the_entry] = (void *) MallocNew(Subnet); parent_subnet->entry[the_entry] = (void *) MallocNew(Subnet);
clear_subnet((Subnet *) parent_subnet->entry[the_entry]); clear_subnet((Subnet *) parent_subnet->entry[the_entry]);
alloced += sizeof (Subnet);
check_alloc_limit();
} }
/* ================================================== */ /* ================================================== */
@@ -157,19 +212,22 @@ create_node(Subnet *parent_subnet, int the_entry)
parent_subnet->entry[the_entry] = (void *) new_node; parent_subnet->entry[the_entry] = (void *) new_node;
clear_node(new_node); clear_node(new_node);
alloced += sizeof (Node);
if (n_nodes == max_nodes) { if (n_nodes == max_nodes) {
if (nodes) { if (nodes) {
max_nodes += NODE_TABLE_INCREMENT; assert(max_nodes > 0);
max_nodes *= 2;
nodes = ReallocArray(Node *, max_nodes, nodes); nodes = ReallocArray(Node *, max_nodes, nodes);
} else { } else {
if (max_nodes != 0) { assert(max_nodes == 0);
CROAK("max_nodes should be 0"); max_nodes = 16;
}
max_nodes = NODE_TABLE_INCREMENT;
nodes = MallocArray(Node *, max_nodes); nodes = MallocArray(Node *, max_nodes);
} }
alloced += sizeof (Node *) * (max_nodes - n_nodes);
} }
nodes[n_nodes++] = (Node *) new_node; nodes[n_nodes++] = (Node *) new_node;
check_alloc_limit();
} }
/* ================================================== */ /* ================================================== */
@@ -177,29 +235,24 @@ create_node(Subnet *parent_subnet, int the_entry)
expanding subnet tables and node entries as we go if necessary. */ expanding subnet tables and node entries as we go if necessary. */
static void * static void *
find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left) find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{ {
unsigned long this_subnet, new_subnet, mask, shift; uint32_t this_subnet;
unsigned long new_bits_left;
shift = 32 - NBITS; this_subnet = get_subnet(addr, bits_consumed);
mask = (1UL<<shift) - 1; bits_consumed += NBITS;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
#if 0 if (bits_consumed < 32 * addr_len) {
fprintf(stderr, "fs addr=%08lx bl=%d ma=%08lx this=%08lx newsn=%08lx nbl=%d\n",
addr, bits_left, mask, this_subnet, new_subnet, new_bits_left);
#endif
if (new_bits_left > 0) {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached)
return NULL;
create_subnet(subnet, this_subnet); create_subnet(subnet, this_subnet);
} }
return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left); return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
} else { } else {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached)
return NULL;
create_node(subnet, this_subnet); create_node(subnet, this_subnet);
} }
return subnet->entry[this_subnet]; return subnet->entry[this_subnet];
@@ -212,30 +265,21 @@ find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
one of the parents does not exist - never open a node out */ one of the parents does not exist - never open a node out */
static void * static void *
find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left) find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
{ {
unsigned long this_subnet, new_subnet, mask, shift; uint32_t this_subnet;
unsigned long new_bits_left;
if (bits_left == 0) { if (bits_consumed >= 32 * addr_len) {
return subnet; return subnet;
} else { } else {
shift = 32 - NBITS; this_subnet = get_subnet(addr, bits_consumed);
mask = (1UL<<shift) - 1; bits_consumed += NBITS;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
#if 0
fprintf(stderr, "fsdo addr=%08lx bl=%d this=%08lx newsn=%08lx nbl=%d\n",
addr, bits_left, this_subnet, new_subnet, new_bits_left);
#endif
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
return NULL; return NULL;
} else { } else {
return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left); return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed);
} }
} }
} }
@@ -243,12 +287,28 @@ find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now) CLG_LogNTPClientAccess (IPAddr *client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
if (node == NULL)
return;
node->ip_addr = *client;
++node->client_hits; ++node->client_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@@ -257,12 +317,28 @@ CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now) CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
if (node == NULL)
return;
node->ip_addr = *client;
++node->peer_hits; ++node->peer_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@@ -271,12 +347,28 @@ CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now) CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32); switch (client->family) {
node->ip_addr = client; case IPADDR_INET4:
node = (Node *) find_subnet(&top_subnet4, &client->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(client, ip6);
node = (Node *) find_subnet(&top_subnet6, ip6, 4, 0);
break;
default:
assert(0);
}
if (node == NULL)
return;
node->ip_addr = *client;
node->last_cmd_hit = now; node->last_cmd_hit = now;
switch (type) { switch (type) {
case CLG_CMD_AUTH: case CLG_CMD_AUTH:
@@ -289,7 +381,7 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
++node->cmd_hits_bad; ++node->cmd_hits_bad;
break; break;
default: default:
CROAK("Impossible"); assert(0);
break; break;
} }
} }
@@ -298,16 +390,32 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result) CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
{ {
Subnet *s; Subnet *s;
uint32_t ip6[4];
unsigned long i; unsigned long i;
unsigned long word, bit, mask; unsigned long word, bit, mask;
if ((bits == 0) || (bits == 8) || (bits == 16) || (bits == 24)) { if (bits >= 0 && bits % 8 == 0) {
memset (result, 0, TABLE_SIZE/8); memset (result, 0, TABLE_SIZE/8);
if (active) { if (active) {
s = find_subnet_dont_open(&top_subnet, subnet, bits); switch (subnet->family) {
case IPADDR_INET4:
if (bits >= 32)
return CLG_BADSUBNET;
s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
break;
case IPADDR_INET6:
if (bits >= 128)
return CLG_BADSUBNET;
split_ip6(subnet, ip6);
s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
break;
default:
return CLG_BADSUBNET;
}
if (s) { if (s) {
for (i=0; i<256; i++) { for (i=0; i<256; i++) {
if (s->entry[i]) { if (s->entry[i]) {
@@ -332,14 +440,25 @@ CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now) CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (!active) { if (!active) {
return CLG_INACTIVE; return CLG_INACTIVE;
} else { } else {
node = (Node *) find_subnet_dont_open(&top_subnet, ip, 32); switch (ip->family) {
case IPADDR_INET4:
node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(ip, ip6);
node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
break;
default:
return CLG_EMPTYSUBNET;
}
if (!node) { if (!node) {
return CLG_EMPTYSUBNET; return CLG_EMPTYSUBNET;

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -35,15 +35,13 @@
#include "sysincl.h" #include "sysincl.h"
#include "reports.h" #include "reports.h"
typedef unsigned long CLG_IP_Addr;
/* Enough to hold flags for 256 hosts in a class C */ /* Enough to hold flags for 256 hosts in a class C */
typedef uint32_t CLG_Bitmap[8]; typedef uint32_t CLG_Bitmap[8];
extern void CLG_Initialise(void); extern void CLG_Initialise(void);
extern void CLG_Finalise(void); extern void CLG_Finalise(void);
extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now); extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now); extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
/* When logging command packets, there are several subtypes */ /* When logging command packets, there are several subtypes */
@@ -53,7 +51,7 @@ typedef enum {
CLG_CMD_BAD_PKT /* bad version or packet length */ CLG_CMD_BAD_PKT /* bad version or packet length */
} CLG_Command_Type; } CLG_Command_Type;
extern void CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now); extern void CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now);
/* And some reporting functions, for use by chronyc. */ /* And some reporting functions, for use by chronyc. */
/* TBD */ /* TBD */
@@ -70,10 +68,10 @@ typedef enum {
known. For bits=24, flag which hosts in that subnet are known. known. For bits=24, flag which hosts in that subnet are known.
Other values, return 0 (failed) */ Other values, return 0 (failed) */
extern CLG_Status CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result); extern CLG_Status CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result);
extern CLG_Status extern CLG_Status
CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now); CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now);
CLG_Status CLG_Status
CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
@@ -83,7 +81,7 @@ CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *repo
that has accessed us since 'since'. */ that has accessed us since 'since'. */
extern void CLG_IterateNTPClients extern void CLG_IterateNTPClients
(void (*fn)(CLG_IP_Addr client, void *arb), (void (*fn)(IPAddr *client, void *arb),
void *arb, void *arb,
time_t since); time_t since);

563
cmdmon.c

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,11 +31,13 @@
#ifndef GOT_CMDMON_H #ifndef GOT_CMDMON_H
#define GOT_CMDMON_H #define GOT_CMDMON_H
#include "addressing.h"
extern void CAM_Initialise(void); extern void CAM_Initialise(void);
extern void CAM_Finalise(void); extern void CAM_Finalise(void);
extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all); extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int CAM_CheckAccessRestriction(unsigned long ip_addr); extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
#endif /* GOT_CMDMON_H */ #endif /* GOT_CMDMON_H */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -61,8 +61,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
ok = 0; ok = 0;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) { if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
src->ip_addr = DNS_Name2IPAddress(hostname); if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
if (src->ip_addr != DNS_Failed_Address) {
ok = 1; ok = 1;
} }
} }

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -32,6 +32,7 @@
#define GOT_CMDPARSE_H #define GOT_CMDPARSE_H
#include "srcparams.h" #include "srcparams.h"
#include "addressing.h"
typedef enum { typedef enum {
CPS_Success, CPS_Success,
@@ -47,7 +48,7 @@ typedef enum {
} CPS_Status; } CPS_Status;
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
unsigned short port; unsigned short port;
SourceParameters params; SourceParameters params;
} CPS_NTP_Source; } CPS_NTP_Source;

347
conf.c
View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -44,6 +45,7 @@
#include "conf.h" #include "conf.h"
#include "ntp_sources.h" #include "ntp_sources.h"
#include "ntp_core.h" #include "ntp_core.h"
#include "refclock.h"
#include "cmdmon.h" #include "cmdmon.h"
#include "srcparams.h" #include "srcparams.h"
#include "logging.h" #include "logging.h"
@@ -52,10 +54,15 @@
#include "acquire.h" #include "acquire.h"
#include "cmdparse.h" #include "cmdparse.h"
#include "broadcast.h" #include "broadcast.h"
#include "util.h"
/* ================================================== */ /* ================================================== */
#define DEFAULT_CONF_FILE "/etc/chrony.conf" #ifndef DEFAULT_CONF_DIR
#define DEFAULT_CONF_DIR "/etc"
#endif
#define DEFAULT_CONF_FILE DEFAULT_CONF_DIR"/chrony.conf"
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
@@ -73,6 +80,7 @@ static void parse_peer(const char *);
static void parse_acquisitionport(const char *); static void parse_acquisitionport(const char *);
static void parse_port(const char *); static void parse_port(const char *);
static void parse_server(const char *); static void parse_server(const char *);
static void parse_refclock(const char *);
static void parse_local(const char *); static void parse_local(const char *);
static void parse_manual(const char *); static void parse_manual(const char *);
static void parse_initstepslew(const char *); static void parse_initstepslew(const char *);
@@ -83,6 +91,7 @@ static void parse_cmddeny(const char *);
static void parse_cmdport(const char *); static void parse_cmdport(const char *);
static void parse_rtconutc(const char *); static void parse_rtconutc(const char *);
static void parse_noclientlog(const char *); static void parse_noclientlog(const char *);
static void parse_clientloglimit(const char *);
static void parse_logchange(const char *); static void parse_logchange(const char *);
static void parse_mailonchange(const char *); static void parse_mailonchange(const char *);
static void parse_bindaddress(const char *); static void parse_bindaddress(const char *);
@@ -92,6 +101,8 @@ static void parse_pidfile(const char *);
static void parse_broadcast(const char *); static void parse_broadcast(const char *);
static void parse_linux_hz(const char *); static void parse_linux_hz(const char *);
static void parse_linux_freq_scale(const char *); static void parse_linux_freq_scale(const char *);
static void parse_sched_priority(const char *);
static void parse_lockall(const char *);
/* ================================================== */ /* ================================================== */
/* Configuration variables */ /* Configuration variables */
@@ -111,6 +122,7 @@ static int do_log_measurements = 0;
static int do_log_statistics = 0; static int do_log_statistics = 0;
static int do_log_tracking = 0; static int do_log_tracking = 0;
static int do_log_rtc = 0; static int do_log_rtc = 0;
static int do_log_refclocks = 0;
static int do_dump_on_exit = 0; static int do_dump_on_exit = 0;
static char *logdir = "."; static char *logdir = ".";
static char *dumpdir = "."; static char *dumpdir = ".";
@@ -126,7 +138,7 @@ static int n_init_srcs;
than this, slew instead of stepping */ than this, slew instead of stepping */
static int init_slew_threshold = -1; static int init_slew_threshold = -1;
#define MAX_INIT_SRCS 8 #define MAX_INIT_SRCS 8
static unsigned long init_srcs_ip[MAX_INIT_SRCS]; static IPAddr init_srcs_ip[MAX_INIT_SRCS];
static int enable_manual=0; static int enable_manual=0;
@@ -146,13 +158,16 @@ static double mail_change_threshold = 0.0;
memory */ memory */
static int no_client_log = 0; static int no_client_log = 0;
/* IP address (host order) for binding the NTP socket to. 0 means INADDR_ANY /* Limit memory allocated for the clients log */
will be used */ static unsigned long client_log_limit = 524288;
static unsigned long bind_address = 0UL;
/* IP address (host order) for binding the command socket to. 0 means /* IP addresses for binding the NTP socket to. UNSPEC family means INADDR_ANY
will be used */
static IPAddr bind_address4, bind_address6;
/* IP addresses for binding the command socket to. UNSPEC family means
use the value of bind_address */ use the value of bind_address */
static unsigned long bind_cmd_address = 0UL; static IPAddr bind_cmd_address4, bind_cmd_address6;
/* Filename to use for storing pid of running chronyd, to prevent multiple /* Filename to use for storing pid of running chronyd, to prevent multiple
* chronyds being started. */ * chronyds being started. */
@@ -168,6 +183,9 @@ static int linux_hz;
static int set_linux_freq_scale = 0; static int set_linux_freq_scale = 0;
static double linux_freq_scale; static double linux_freq_scale;
static int sched_priority = 0;
static int lock_memory = 0;
/* ================================================== */ /* ================================================== */
typedef struct { typedef struct {
@@ -179,6 +197,7 @@ typedef struct {
static const Command commands[] = { static const Command commands[] = {
{"server", 6, parse_server}, {"server", 6, parse_server},
{"peer", 4, parse_peer}, {"peer", 4, parse_peer},
{"refclock", 8, parse_refclock},
{"acquisitionport", 15, parse_acquisitionport}, {"acquisitionport", 15, parse_acquisitionport},
{"port", 4, parse_port}, {"port", 4, parse_port},
{"driftfile", 9, parse_driftfile}, {"driftfile", 9, parse_driftfile},
@@ -200,6 +219,7 @@ static const Command commands[] = {
{"cmdport", 7, parse_cmdport}, {"cmdport", 7, parse_cmdport},
{"rtconutc", 8, parse_rtconutc}, {"rtconutc", 8, parse_rtconutc},
{"noclientlog", 11, parse_noclientlog}, {"noclientlog", 11, parse_noclientlog},
{"clientloglimit", 14, parse_clientloglimit},
{"logchange", 9, parse_logchange}, {"logchange", 9, parse_logchange},
{"mailonchange", 12, parse_mailonchange}, {"mailonchange", 12, parse_mailonchange},
{"bindaddress", 11, parse_bindaddress}, {"bindaddress", 11, parse_bindaddress},
@@ -208,7 +228,9 @@ static const Command commands[] = {
{"pidfile", 7, parse_pidfile}, {"pidfile", 7, parse_pidfile},
{"broadcast", 9, parse_broadcast}, {"broadcast", 9, parse_broadcast},
{"linux_hz", 8, parse_linux_hz}, {"linux_hz", 8, parse_linux_hz},
{"linux_freq_scale", 16, parse_linux_freq_scale} {"linux_freq_scale", 16, parse_linux_freq_scale},
{"sched_priority", 14, parse_sched_priority},
{"lock_all", 8, parse_lockall}
}; };
static int n_commands = (sizeof(commands) / sizeof(commands[0])); static int n_commands = (sizeof(commands) / sizeof(commands[0]));
@@ -224,7 +246,7 @@ typedef enum {
typedef struct { typedef struct {
NTP_Source_Type type; NTP_Source_Type type;
unsigned long ip_addr; IPAddr ip_addr;
unsigned short port; unsigned short port;
SourceParameters params; SourceParameters params;
} NTP_Source; } NTP_Source;
@@ -234,12 +256,17 @@ typedef struct {
static NTP_Source ntp_sources[MAX_NTP_SOURCES]; static NTP_Source ntp_sources[MAX_NTP_SOURCES];
static int n_ntp_sources = 0; static int n_ntp_sources = 0;
#define MAX_RCL_SOURCES 8
static RefclockParameters refclock_sources[MAX_RCL_SOURCES];
static int n_refclock_sources = 0;
/* ================================================== */ /* ================================================== */
typedef struct _AllowDeny { typedef struct _AllowDeny {
struct _AllowDeny *next; struct _AllowDeny *next;
struct _AllowDeny *prev; struct _AllowDeny *prev;
unsigned long ip; IPAddr ip;
int subnet_bits; int subnet_bits;
int all; /* 1 to override existing more specific defns */ int all; /* 1 to override existing more specific defns */
int allow; /* 0 for deny, 1 for allow */ int allow; /* 0 for deny, 1 for allow */
@@ -365,6 +392,24 @@ parse_source(const char *line, NTP_Source_Type type)
/* ================================================== */ /* ================================================== */
static void
parse_sched_priority(const char *line)
{
if (sscanf(line, "%d", &sched_priority) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read scheduling priority at line %d", line_number);
}
}
/* ================================================== */
static void
parse_lockall(const char *line)
{
lock_memory = 1;
}
/* ================================================== */
static void static void
parse_server(const char *line) parse_server(const char *line)
{ {
@@ -381,6 +426,98 @@ parse_peer(const char *line)
/* ================================================== */ /* ================================================== */
static void
parse_refclock(const char *line)
{
int i, n, poll, dpoll, filter_length, pps_rate;
unsigned long ref_id;
double offset, delay;
const char *tmp;
char name[5], cmd[10 + 1], *param;
unsigned char ref[5];
i = n_refclock_sources;
if (i >= MAX_RCL_SOURCES)
return;
poll = 4;
dpoll = 0;
filter_length = 15;
pps_rate = 0;
offset = 0.0;
delay = 1e-9;
ref_id = 0;
if (sscanf(line, "%4s%n", name, &n) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name at line %d", line_number);
return;
}
line += n;
while (isspace(line[0]))
line++;
tmp = line;
while (line[0] != '\0' && !isspace(line[0]))
line++;
if (line == tmp) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock parameter at line %d", line_number);
return;
}
param = MallocArray(char, 1 + line - tmp);
strncpy(param, tmp, line - tmp);
param[line - tmp] = '\0';
while (sscanf(line, "%10s%n", cmd, &n) == 1) {
line += n;
if (!strncasecmp(cmd, "refid", 5)) {
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
break;
ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
} else if (!strncasecmp(cmd, "poll", 4)) {
if (sscanf(line, "%d%n", &poll, &n) != 1) {
break;
}
} else if (!strncasecmp(cmd, "dpoll", 5)) {
if (sscanf(line, "%d%n", &dpoll, &n) != 1) {
break;
}
} else if (!strncasecmp(cmd, "filter", 6)) {
if (sscanf(line, "%d%n", &filter_length, &n) != 1) {
break;
}
} else if (!strncasecmp(cmd, "rate", 4)) {
if (sscanf(line, "%d%n", &pps_rate, &n) != 1)
break;
} else if (!strncasecmp(cmd, "offset", 6)) {
if (sscanf(line, "%lf%n", &offset, &n) != 1)
break;
} else if (!strncasecmp(cmd, "delay", 5)) {
if (sscanf(line, "%lf%n", &delay, &n) != 1)
break;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Unknown refclock parameter %s at line %d", cmd, line_number);
break;
}
line += n;
}
strncpy(refclock_sources[i].driver_name, name, 4);
refclock_sources[i].driver_parameter = param;
refclock_sources[i].driver_poll = dpoll;
refclock_sources[i].poll = poll;
refclock_sources[i].filter_length = filter_length;
refclock_sources[i].pps_rate = pps_rate;
refclock_sources[i].offset = offset;
refclock_sources[i].delay = delay;
refclock_sources[i].ref_id = ref_id;
n_refclock_sources++;
}
/* ================================================== */
static void static void
parse_some_port(const char *line, int *portvar) parse_some_port(const char *line, int *portvar)
{ {
@@ -516,6 +653,9 @@ parse_log(const char *line)
} else if (!strncmp(line, "rtc", 3)) { } else if (!strncmp(line, "rtc", 3)) {
do_log_rtc = 1; do_log_rtc = 1;
line += 3; line += 3;
} else if (!strncmp(line, "refclocks", 9)) {
do_log_refclocks = 1;
line += 9;
} else { } else {
break; break;
} }
@@ -571,7 +711,7 @@ parse_initstepslew(const char *line)
char hostname[HOSTNAME_LEN+1]; char hostname[HOSTNAME_LEN+1];
int n; int n;
int threshold; int threshold;
unsigned long ip_addr; IPAddr ip_addr;
n_init_srcs = 0; n_init_srcs = 0;
p = line; p = line;
@@ -584,8 +724,7 @@ parse_initstepslew(const char *line)
} }
while (*p) { while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) { if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
ip_addr = DNS_Name2IPAddress(hostname); if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
if (ip_addr != DNS_Failed_Address) {
init_srcs_ip[n_init_srcs] = ip_addr; init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs; ++n_init_srcs;
} }
@@ -634,6 +773,21 @@ parse_noclientlog(const char *line)
/* ================================================== */ /* ================================================== */
static void
parse_clientloglimit(const char *line)
{
if (sscanf(line, "%lu", &client_log_limit) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read clientlog memory limit at line %d", line_number);
}
if (client_log_limit == 0) {
/* unlimited */
client_log_limit = (unsigned long)-1;
}
}
/* ================================================== */
static void static void
parse_logchange(const char *line) parse_logchange(const char *line)
{ {
@@ -677,7 +831,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
unsigned long a, b, c, d, n; unsigned long a, b, c, d, n;
int all = 0; int all = 0;
AllowDeny *new_node = NULL; AllowDeny *new_node = NULL;
unsigned long ip_addr; IPAddr ip_addr;
p = line; p = line;
@@ -694,20 +848,29 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
new_node->ip = 0UL; new_node->ip.family = IPADDR_UNSPEC;
new_node->subnet_bits = 0; new_node->subnet_bits = 0;
} else { } else {
char *slashpos; char *slashpos;
slashpos = strchr(p, '/'); slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0; if (slashpos) *slashpos = 0;
n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d); n = 0;
if (UTI_StringToIP(p, &ip_addr) ||
if (n >= 1) { (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
if (n == 0) {
new_node->ip = ip_addr;
if (ip_addr.family == IPADDR_INET6)
new_node->subnet_bits = 128;
else
new_node->subnet_bits = 32;
} else {
new_node->ip.family = IPADDR_INET4;
a &= 0xff; a &= 0xff;
b &= 0xff; b &= 0xff;
c &= 0xff; c &= 0xff;
@@ -715,24 +878,24 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
switch (n) { switch (n) {
case 1: case 1:
new_node->ip = (a<<24); new_node->ip.addr.in4 = (a<<24);
new_node->subnet_bits = 8; new_node->subnet_bits = 8;
break; break;
case 2: case 2:
new_node->ip = (a<<24) | (b<<16); new_node->ip.addr.in4 = (a<<24) | (b<<16);
new_node->subnet_bits = 16; new_node->subnet_bits = 16;
break; break;
case 3: case 3:
new_node->ip = (a<<24) | (b<<16) | (c<<8); new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
new_node->subnet_bits = 24; new_node->subnet_bits = 24;
break; break;
case 4: case 4:
new_node->ip = (a<<24) | (b<<16) | (c<<8) | d; new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
new_node->subnet_bits = 32; new_node->subnet_bits = 32;
break; break;
default: default:
assert(0); assert(0);
}
} }
if (slashpos) { if (slashpos) {
@@ -746,12 +909,14 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
} }
} else { } else {
ip_addr = DNS_Name2IPAddress(p); if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
if (ip_addr != DNS_Failed_Address) {
new_node = MallocNew(AllowDeny); new_node = MallocNew(AllowDeny);
new_node->allow = allow; new_node->allow = allow;
new_node->all = all; new_node->all = all;
new_node->ip = ip_addr; new_node->ip = ip_addr;
if (ip_addr.family == IPADDR_INET6)
new_node->subnet_bits = 128;
else
new_node->subnet_bits = 32; new_node->subnet_bits = 32;
} else { } else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number);
@@ -805,27 +970,20 @@ parse_cmddeny(const char *line)
/* ================================================== */ /* ================================================== */
static unsigned long
parse_an_address(const char *line, const char *errmsg)
{
unsigned long a, b, c, d;
int n;
n = sscanf(line, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n == 4) {
return (((a&0xff)<<24) | ((b&0xff)<<16) |
((c&0xff)<<8) | (d&0xff));
} else {
LOG(LOGS_WARN, LOGF_Configure, errmsg, line_number);
return 0UL;
}
}
/* ================================================== */
static void static void
parse_bindaddress(const char *line) parse_bindaddress(const char *line)
{ {
bind_address = parse_an_address(line, "Could not read bind address at line %d\n"); IPAddr ip;
char addr[51];
if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
if (ip.family == IPADDR_INET4)
bind_address4 = ip;
else if (ip.family == IPADDR_INET6)
bind_address6 = ip;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read bind address at line %d\n", line_number);
}
} }
/* ================================================== */ /* ================================================== */
@@ -833,7 +991,17 @@ parse_bindaddress(const char *line)
static void static void
parse_bindcmdaddress(const char *line) parse_bindcmdaddress(const char *line)
{ {
bind_cmd_address = parse_an_address(line, "Could not read bind command address at line %d\n"); IPAddr ip;
char addr[51];
if (sscanf(line, "%50s", addr) == 1 && UTI_StringToIP(addr, &ip)) {
if (ip.family == IPADDR_INET4)
bind_cmd_address4 = ip;
else if (ip.family == IPADDR_INET6)
bind_cmd_address6 = ip;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read bind command address at line %d\n", line_number);
}
} }
/* ================================================== */ /* ================================================== */
@@ -850,7 +1018,7 @@ parse_pidfile(const char *line)
typedef struct { typedef struct {
/* Both in host (not necessarily network) order */ /* Both in host (not necessarily network) order */
unsigned long addr; IPAddr addr;
unsigned short port; unsigned short port;
int interval; int interval;
} NTP_Broadcast_Destination; } NTP_Broadcast_Destination;
@@ -866,27 +1034,22 @@ parse_broadcast(const char *line)
{ {
/* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */ /* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
int port; int port;
unsigned int a, b, c, d;
int n; int n;
int interval; int interval;
unsigned long addr; char addr[51];
IPAddr ip;
n = sscanf(line, "%d %u.%u.%u.%u %d", &interval, &a, &b, &c, &d, &port); n = sscanf(line, "%d %50s %d", &interval, addr, &port);
if (n < 5) { if (n < 2 || !UTI_StringToIP(addr, &ip)) {
LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
return; return;
} else if (n == 5) { } else if (n == 2) {
/* default port */ /* default port */
port = 123; port = 123;
} else if (n > 6) { } else if (n > 3) {
LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number); LOG(LOGS_WARN, LOGF_Configure, "Too many fields in broadcast directive at line %d", line_number);
} }
addr = ((unsigned long) a << 24) |
((unsigned long) b << 16) |
((unsigned long) c << 8) |
((unsigned long) d );
if (max_broadcasts == n_broadcasts) { if (max_broadcasts == n_broadcasts) {
/* Expand array */ /* Expand array */
max_broadcasts += 8; max_broadcasts += 8;
@@ -897,7 +1060,7 @@ parse_broadcast(const char *line)
} }
} }
broadcasts[n_broadcasts].addr = addr; broadcasts[n_broadcasts].addr = ip;
broadcasts[n_broadcasts].port = port; broadcasts[n_broadcasts].port = port;
broadcasts[n_broadcasts].interval = interval; broadcasts[n_broadcasts].interval = interval;
++n_broadcasts; ++n_broadcasts;
@@ -948,6 +1111,7 @@ CNF_AddSources(void) {
for (i=0; i<n_ntp_sources; i++) { for (i=0; i<n_ntp_sources; i++) {
server.ip_addr = ntp_sources[i].ip_addr; server.ip_addr = ntp_sources[i].ip_addr;
memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
server.port = ntp_sources[i].port; server.port = ntp_sources[i].port;
switch (ntp_sources[i].type) { switch (ntp_sources[i].type) {
@@ -968,12 +1132,23 @@ CNF_AddSources(void) {
/* ================================================== */ /* ================================================== */
void
CNF_AddRefclocks(void) {
int i;
for (i=0; i<n_refclock_sources; i++) {
RCL_AddRefclock(&refclock_sources[i]);
}
}
/* ================================================== */
void void
CNF_AddBroadcasts(void) CNF_AddBroadcasts(void)
{ {
int i; int i;
for (i=0; i<n_broadcasts; i++) { for (i=0; i<n_broadcasts; i++) {
BRD_AddDestination(broadcasts[i].addr, BRD_AddDestination(&broadcasts[i].addr,
broadcasts[i].port, broadcasts[i].port,
broadcasts[i].interval); broadcasts[i].interval);
} }
@@ -1051,6 +1226,13 @@ CNF_GetLogRtc(void)
return do_log_rtc; return do_log_rtc;
} }
/* ================================================== */
int
CNF_GetLogRefclocks(void)
{
return do_log_refclocks;
}
/* ================================================== */ /* ================================================== */
char * char *
@@ -1169,14 +1351,14 @@ CNF_SetupAccessRestrictions(void)
int status; int status;
for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) { for (node = ntp_auth_list.next; node != &ntp_auth_list; node = node->next) {
status = NCR_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all); status = NCR_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) { if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip); LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
} }
} }
for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) { for (node = cmd_auth_list.next; node != &cmd_auth_list; node = node->next) {
status = CAM_AddAccessRestriction(node->ip, node->subnet_bits, node->allow, node->all); status = CAM_AddAccessRestriction(&node->ip, node->subnet_bits, node->allow, node->all);
if (!status) { if (!status) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip); LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
} }
@@ -1195,18 +1377,36 @@ CNF_GetNoClientLog(void)
/* ================================================== */ /* ================================================== */
void unsigned long
CNF_GetBindAddress(unsigned long *addr) CNF_GetClientLogLimit(void)
{ {
*addr = bind_address; return client_log_limit;
} }
/* ================================================== */ /* ================================================== */
void void
CNF_GetBindCommandAddress(unsigned long *addr) CNF_GetBindAddress(int family, IPAddr *addr)
{ {
*addr = bind_cmd_address ? bind_cmd_address : bind_address; if (family == IPADDR_INET4)
*addr = bind_address4;
else if (family == IPADDR_INET6)
*addr = bind_address6;
else
addr->family = IPADDR_UNSPEC;
}
/* ================================================== */
void
CNF_GetBindCommandAddress(int family, IPAddr *addr)
{
if (family == IPADDR_INET4)
*addr = bind_cmd_address4.family != IPADDR_UNSPEC ? bind_cmd_address4 : bind_address4;
else if (family == IPADDR_INET6)
*addr = bind_cmd_address6.family != IPADDR_UNSPEC ? bind_cmd_address6 : bind_address6;
else
addr->family = IPADDR_UNSPEC;
} }
/* ================================================== */ /* ================================================== */
@@ -1235,3 +1435,18 @@ CNF_GetLinuxFreqScale(int *set, double *freq_scale)
*freq_scale = linux_freq_scale ; *freq_scale = linux_freq_scale ;
} }
/* ================================================== */
int
CNF_GetSchedPriority(void)
{
return sched_priority;
}
/* ================================================== */
int
CNF_GetLockMemory(void)
{
return lock_memory;
}

14
conf.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,12 +31,15 @@
#ifndef GOT_CONF_H #ifndef GOT_CONF_H
#define GOT_CONF_H #define GOT_CONF_H
#include "addressing.h"
extern char *CNF_GetRtcDevice(void); extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename); extern void CNF_ReadFile(const char *filename);
extern void CNF_AddSources(void); extern void CNF_AddSources(void);
extern void CNF_AddBroadcasts(void); extern void CNF_AddBroadcasts(void);
extern void CNF_AddRefclocks(void);
extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything); extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
@@ -49,6 +52,7 @@ extern int CNF_GetLogMeasurements(void);
extern int CNF_GetLogStatistics(void); extern int CNF_GetLogStatistics(void);
extern int CNF_GetLogTracking(void); extern int CNF_GetLogTracking(void);
extern int CNF_GetLogRtc(void); extern int CNF_GetLogRtc(void);
extern int CNF_GetLogRefclocks(void);
extern char *CNF_GetKeysFile(void); extern char *CNF_GetKeysFile(void);
extern char *CNF_GetRtcFile(void); extern char *CNF_GetRtcFile(void);
extern unsigned long CNF_GetCommandKey(void); extern unsigned long CNF_GetCommandKey(void);
@@ -59,8 +63,9 @@ extern int CNF_GetRTCOnUTC(void);
extern void CNF_GetLogChange(int *enabled, double *threshold); extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user); extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void); extern int CNF_GetNoClientLog(void);
extern void CNF_GetBindAddress(unsigned long *addr); extern unsigned long CNF_GetClientLogLimit(void);
extern void CNF_GetBindCommandAddress(unsigned long *addr); extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void); extern char *CNF_GetPidFile(void);
extern void CNF_GetLinuxHz(int *set, int *hz); extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale); extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
@@ -71,4 +76,7 @@ extern int CNF_AllowLocalReference(int *stratum);
extern void CNF_SetupAccessRestrictions(void); extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void);
#endif /* GOT_CONF_H */ #endif /* GOT_CONF_H */

362
configure vendored
View File

@@ -1,7 +1,4 @@
#!/bin/sh #!/bin/sh
#
# $Header: /cvs/src/chrony/configure,v 1.30 2003/09/22 21:53:57 richard Exp $
#
# ======================================================================= # =======================================================================
# #
# chronyd/chronyc - Programs for keeping computer clocks accurate. # chronyd/chronyc - Programs for keeping computer clocks accurate.
@@ -24,86 +21,47 @@ else
MYCFLAGS="${CFLAGS}" MYCFLAGS="${CFLAGS}"
fi fi
MYCPPFLAGS="${CPPFLAGS}"
if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
CCWARNFLAGS=""
fi
# ====================================================================== # ======================================================================
# FUNCTIONS # FUNCTIONS
#{{{ test_for_sqrt #{{{ test_code
test_for_sqrt () { test_code () {
# 0 : doesn't need -lm name=$1
# 1 : needs -lm headers=$2
# 2 : doesn't even link with -lm cflags=$3
ldflags=$4
code=$5
cat >docheck.c <<EOF; printf "Checking for $name : "
#include <math.h>
int main(int argc, char **argv) {
return (int) sqrt((double)argc);
}
EOF
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1 (
if [ $? -eq 0 ] for h in $headers; do
then echo "#include <$h>"
${MYCC} ${MYCFLAGS} -o docheck docheck.o >/dev/null 2>&1 done
if [ $? -eq 0 ] echo "int main(int argc, char **argv) {"
then echo "$code"
result=0 echo "return 0; }"
else ) > docheck.c
${MYCC} ${MYCFLAGS} -o docheck docheck.o -lm >/dev/null 2>&1
if [ $? -eq 0 ] ${MYCC} ${MYCFLAGS} ${MYCPPFLAGS} $cflags -o docheck docheck.c $ldflags >/dev/null 2>&1
then
result=1
else
result=2
fi
fi
else
result=2
fi
rm -f docheck.c docheck.o docheck
echo $result
}
#}}}
#{{{ test_for_stdint_h
test_for_stdint_h () {
cat >docheck.c <<EOF;
#include <stdint.h>
int main(int argc, char **argv) {
return 0;
}
EOF
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
if [ $? -eq 0 ] if [ $? -eq 0 ]
then then
printf "Yes\n"
result=0 result=0
else else
printf "No\n"
result=1 result=1
fi fi
rm -f docheck.c docheck
rm -f docheck.c docheck.o return $result
echo $result
}
#}}}
#{{{ test_for_inttypes_h
test_for_inttypes_h () {
cat >docheck.c <<EOF;
#include <inttypes.h>
int main(int argc, char **argv) {
return 0;
}
EOF
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
result=0
else
result=1
fi
rm -f docheck.c docheck.o
echo $result
} }
#}}} #}}}
#{{{ usage #{{{ usage
@@ -121,6 +79,8 @@ Configuration:
Installation directories: Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX --prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local] [/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in By default, \`make install' will install all the files in
\`/usr/local/bin', \`/usr/local/lib' etc. You can specify \`/usr/local/bin', \`/usr/local/lib' etc. You can specify
@@ -128,27 +88,43 @@ an installation prefix other than \`/usr/local' using \`--prefix',
for instance \`--prefix=$HOME'. for instance \`--prefix=$HOME'.
For better control, use the options below. For better control, use the options below.
--disable-readline Don't try to use GNU readline --disable-readline Disable line editing support
--without-readline Don't use GNU readline even if it is available
--without-editline Don't use editline even if it is available
--readline-dir=DIR Specify parent of readline include and lib directories --readline-dir=DIR Specify parent of readline include and lib directories
--readline-inc-dir=DIR Specify where readline include directory is --readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline lib directory is --readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is --with-ncurses-library=DIR Specify where ncurses lib directory is
--disable-ipv6 Disable IPv6 support
--disable-pps Disable PPS API support
--disable-rtc Don't include RTC even on Linux --disable-rtc Don't include RTC even on Linux
--disable-linuxcaps Disable Linux capabilities support
Fine tuning of the installation directories: Fine tuning of the installation directories:
--infodir=DIR info documentation [PREFIX/info] --sysconfdir=DIR chrony.conf location [/etc]
--mandir=DIR man documentation [PREFIX/man] --bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--datarootdir=DIR data root [PREFIX/share]
--infodir=DIR info documentation [DATAROOTDIR/info]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/chrony]
Overriding system detection when cross-compiling:
--host-system=OS Specify system name (uname -s)
--host-release=REL Specify system release (uname -r)
--host-machine=CPU Specify machine (uname -m)
Some influential environment variables: Some influential environment variables:
CC C compiler command CC C compiler command
CFLAGS C compiler flags CFLAGS C compiler flags
CPPFLAGS C preprocessor flags, e.g. -I<include dir> if you have
headers in a nonstandard directory <include dir>
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir> nonstandard directory <lib dir>
Use these variables to override the choices made by \`configure' or to help Use these variables to override the choices made by \`configure' or to help
it to find libraries and programs with nonstandard names/locations. it to find libraries and programs with nonstandard names/locations.
Report bugs to <rc@rc0.org.uk>.
EOF EOF
} }
@@ -162,37 +138,42 @@ OPERATINGSYSTEM=`uname -s`
VERSION=`uname -r` VERSION=`uname -r`
MACHINE=`uname -m` MACHINE=`uname -m`
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
EXTRA_LIBS="" EXTRA_LIBS=""
EXTRA_CLI_LIBS="" EXTRA_CLI_LIBS=""
EXTRA_OBJECTS="" EXTRA_OBJECTS=""
EXTRA_DEFS="" EXTRA_DEFS=""
INSTALL_PREFIX=/usr/local
SYSDEFS="" SYSDEFS=""
# Support for readline (on by default) # Support for readline (on by default)
feat_readline=1 feat_readline=1
try_readline=1
try_editline=1
feat_rtc=1 feat_rtc=1
feat_linuxcaps=1
try_linuxcaps=0
readline_lib="" readline_lib=""
readline_inc="" readline_inc=""
ncurses_lib="" ncurses_lib=""
feat_ipv6=1
SETINFODIR="" feat_pps=1
SETMANDIR="" try_setsched=0
try_lockmem=0
for option for option
do do
case "$option" in case "$option" in
--prefix=* | --install_prefix=* )
INSTALL_PREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--trace ) --trace )
EXTRA_DEFS="-DTRACEON" EXTRA_DEFS="-DTRACEON"
;; ;;
--disable-readline ) --disable-readline )
feat_readline=0 feat_readline=0
;; ;;
--without-readline )
try_readline=0
;;
--without-editline )
try_editline=0
;;
--with-readline-library=* ) --with-readline-library=* )
readline_lib=-L`echo $option | sed -e 's/^.*=//;'` readline_lib=-L`echo $option | sed -e 's/^.*=//;'`
;; ;;
@@ -202,15 +183,54 @@ do
--with-ncurses-library=* ) --with-ncurses-library=* )
ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'` ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'`
;; ;;
--prefix=* | --install_prefix=* )
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--exec-prefix=* )
SETEPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--sysconfdir=* )
SETSYSCONFDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--bindir=* )
SETBINDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--sbindir=* )
SETSBINDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--datarootdir=* )
SETDATAROOTDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--infodir=* ) --infodir=* )
SETINFODIR=`echo $option | sed -e 's/^.*=//;'` SETINFODIR=`echo $option | sed -e 's/^.*=//;'`
;; ;;
--mandir=* ) --mandir=* )
SETMANDIR=`echo $option | sed -e 's/^.*=//;'` SETMANDIR=`echo $option | sed -e 's/^.*=//;'`
;; ;;
--docdir=* )
SETDOCDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--disable-rtc) --disable-rtc)
feat_rtc=0 feat_rtc=0
;; ;;
--disable-ipv6)
feat_ipv6=0
;;
--disable-pps)
feat_pps=0
;;
--disable-linuxcaps)
feat_linuxcaps=0
;;
--host-system=* )
OPERATINGSYSTEM=`echo $option | sed -e 's/^.*=//;'`
;;
--host-release=* )
VERSION=`echo $option | sed -e 's/^.*=//;'`
;;
--host-machine=* )
MACHINE=`echo $option | sed -e 's/^.*=//;'`
;;
--help | -h ) --help | -h )
usage usage
exit 0 exit 0
@@ -220,6 +240,8 @@ do
esac esac
done done
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
case $SYSTEM in case $SYSTEM in
SunOS-sun4* ) SunOS-sun4* )
case $VERSION in case $VERSION in
@@ -245,9 +267,12 @@ case $SYSTEM in
Linux* ) Linux* )
EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o" EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o"
if [ $feat_rtc -eq 1 ] ; then if [ $feat_rtc -eq 1 ] ; then
EXTRA_OBJECTS+=" rtc_linux.o" EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
EXTRA_DEFS+=" -DFEAT_RTC=1" EXTRA_DEFS="$EXTRA_DEFS -DFEAT_RTC=1"
fi fi
try_linuxcaps=1
try_setsched=1
try_lockmem=1
SYSDEFS="-DLINUX" SYSDEFS="-DLINUX"
echo "Configuring for " $SYSTEM echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then if [ "${MACHINE}" = "alpha" ]; then
@@ -257,13 +282,13 @@ case $SYSTEM in
fi fi
;; ;;
BSD/386-i[3456]86|FreeBSD-i386 ) BSD/386-i[3456]86|FreeBSD-i386|FreeBSD-amd64 )
# Antti Jrvinen <costello@iki.fi> reported that this system can # Antti Jrvinen <costello@iki.fi> reported that this system can
# be supported with the SunOS 4.x driver files. # be supported with the SunOS 4.x driver files.
EXTRA_OBJECTS="sys_sunos.o strerror.o" EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm" EXTRA_LIBS="-lkvm"
SYSDEFS="-DSUNOS" SYSDEFS="-DSUNOS"
echo "Configuring for BSD/386 (using SunOS driver)" echo "Configuring for $SYSTEM (using SunOS driver)"
;; ;;
NetBSD-* ) NetBSD-* )
EXTRA_OBJECTS="sys_netbsd.o" EXTRA_OBJECTS="sys_netbsd.o"
@@ -292,74 +317,165 @@ case $SYSTEM in
;; ;;
esac esac
printf "Checking if sqrt() needs -lm : " MATHCODE='return (int) pow(2.0, log(sqrt((double)argc)));'
case `test_for_sqrt` if test_code 'math' 'math.h' '' '' "$MATHCODE"; then
in
0)
printf "No\n"
LIBS="" LIBS=""
;; else
1) if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
printf "Yes\n"
LIBS="-lm" LIBS="-lm"
;; else
*) printf "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out\n"
printf "\nCan't compile/link a program which uses sqrt(), bailing out\n"
exit 1 exit 1
;; fi
esac fi
printf "Checking for <stdint.h> : " if test_code '<stdint.h>' 'stdint.h' '' '' ''; then
if [ `test_for_stdint_h` -eq 0 ]; then
printf "Yes\n"
SYSDEFS="${SYSDEFS} -DHAS_STDINT_H" SYSDEFS="${SYSDEFS} -DHAS_STDINT_H"
else
printf "No\n"
fi fi
printf "Checking for <inttypes.h> : " if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then
if [ `test_for_inttypes_h` -eq 0 ]; then
printf "Yes\n"
SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H" SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H"
else
printf "No\n"
fi fi
if [ "x${MYCC}" = "xgcc" ]; then if [ $feat_ipv6 = "1" ] && \
CCWARNFLAGS="-Wmissing-prototypes -Wall" test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' '' '
else struct sockaddr_in6 n;
CCWARNFLAGS="" char p[100];
n.sin6_addr = in6addr_any;
return !inet_ntop(AF_INET6, &n.sin6_addr.s6_addr, p, sizeof(p));'
then
SYSDEFS="${SYSDEFS} -DHAVE_IPV6"
fi
if [ $feat_pps = "1" ] && \
test_code 'PPS API' 'timepps.h' '' '' '
pps_handle_t h;
pps_info_t i;
struct timespec ts;
return time_pps_fetch(&h, PPS_TSFMT_TSPEC, &i, &ts);'
then
SYSDEFS="${SYSDEFS} -DHAVE_PPSAPI"
fi
if [ $feat_linuxcaps = "1" ] && [ $try_linuxcaps = "1" ] && \
test_code \
linuxcaps \
'sys/types.h pwd.h sys/prctl.h sys/capability.h grp.h' \
'' '-lcap' \
'prctl(PR_SET_KEEPCAPS, 1);cap_set_proc(cap_from_text("cap_sys_time=ep"));'
then
EXTRA_DEFS="${EXTRA_DEFS} -DFEAT_LINUXCAPS=1"
EXTRA_LIBS="-lcap"
fi
if [ $try_setsched = "1" ] && \
test_code \
'sched_setscheduler()' \
'sched.h' '' '' '
struct sched_param sched;
sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sched);'
then
SYSDEFS="${SYSDEFS} -DHAVE_SCHED_SETSCHEDULER"
fi
if [ $try_lockmem = "1" ] && \
test_code \
'mlockall()' \
'sys/mman.h sys/resource.h' '' '' '
struct rlimit rlim;
setrlimit(RLIMIT_MEMLOCK, &rlim);
mlockall(MCL_CURRENT|MCL_FUTURE);'
then
SYSDEFS="${SYSDEFS} -DHAVE_MLOCKALL"
fi fi
if [ $feat_readline = "1" ]; then
READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
else
READLINE_COMPILE="" READLINE_COMPILE=""
READLINE_LINK="" READLINE_LINK=""
if [ $feat_readline = "1" ]; then
if [ $try_editline = "1" ]; then
if test_code editline 'stdio.h editline/readline.h' \
"$readline_inc" "$readline_lib -ledit" \
'add_history(readline("prompt"));'
then
READLINE_COMPILE="-DFEAT_READLINE=1 -DUSE_EDITLINE=1 $readline_inc"
READLINE_LINK="$readline_lib -ledit"
fi
fi fi
MANDIR=${INSTALL_PREFIX}/man if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
INFODIR=${INSTALL_PREFIX}/info if test_code readline 'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
'add_history(readline("prompt"));'
then
READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
fi
fi
fi
SYSCONFDIR=/etc
if [ "x$SETSYSCONFDIR" != "x" ]; then
SYSCONFDIR=$SETSYSCONFDIR
fi
PREFIX=/usr/local
if [ "x$SETPREFIX" != "x" ]; then
PREFIX=$SETPREFIX
fi
EPREFIX=${PREFIX}
if [ "x$SETEPREFIX" != "x" ]; then
EPREFIX=$SETEPREFIX
fi
BINDIR=${EPREFIX}/bin
if [ "x$SETBINDIR" != "x" ]; then
BINDIR=$SETBINDIR
fi
SBINDIR=${EPREFIX}/sbin
if [ "x$SETSBINDIR" != "x" ]; then
SBINDIR=$SETSBINDIR
fi
DATAROOTDIR=${PREFIX}/share
if [ "x$SETDATAROOTDIR" != "x" ]; then
DATAROOTDIR=$SETDATAROOTDIR
fi
INFODIR=${DATAROOTDIR}/info
if [ "x$SETINFODIR" != "x" ]; then if [ "x$SETINFODIR" != "x" ]; then
INFODIR=$SETINFODIR INFODIR=$SETINFODIR
fi fi
MANDIR=${DATAROOTDIR}/man
if [ "x$SETMANDIR" != "x" ]; then if [ "x$SETMANDIR" != "x" ]; then
MANDIR=$SETMANDIR MANDIR=$SETMANDIR
fi fi
DOCDIR=${DATAROOTDIR}/doc/chrony
if [ "x$SETDOCDIR" != "x" ]; then
DOCDIR=$SETDOCDIR
fi
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\ sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@CC@%${MYCC}%;\ s%@CC@%${MYCC}%;\
s%@CFLAGS@%${MYCFLAGS}%;\ s%@CFLAGS@%${MYCFLAGS}%;\
s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\ s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\
s%@CPPFLAGS@%${CPPFLAGS}%;\
s%@LIBS@%${LIBS}%;\ s%@LIBS@%${LIBS}%;\
s%@LDFLAGS@%${LDFLAGS}%;\
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\ s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
s%@SYSDEFS@%${SYSDEFS}%;\ s%@SYSDEFS@%${SYSDEFS}%;\
s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\ s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\ s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\ s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
s%@READLINE_LINK@%${READLINE_LINK}%;\ s%@READLINE_LINK@%${READLINE_LINK}%;\
s%@INSTALL_PREFIX@%${INSTALL_PREFIX}%;\ s%@SYSCONFDIR@%${SYSCONFDIR}%;\
s%@BINDIR@%${BINDIR}%;\
s%@SBINDIR@%${SBINDIR}%;\
s%@DOCDIR@%${DOCDIR}%;\
s%@MANDIR@%${MANDIR}%;\ s%@MANDIR@%${MANDIR}%;\
s%@INFODIR@%${INFODIR}%;"\ s%@INFODIR@%${INFODIR}%;"\
< Makefile.in > Makefile < Makefile.in > Makefile

View File

@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to the GNU Lesser General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
@@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
@@ -278,8 +278,8 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest 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 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ 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. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. 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 If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.
@@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. Public License instead of this License.

View File

@@ -14,7 +14,7 @@ my($copyrighttext) = <<'EOF';
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# SEE COPYING FOR DETAILS # SEE COPYING FOR DETAILS
EOF EOF

View File

@@ -162,5 +162,5 @@ DNSchrony.pl is covered by the GPL
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# SEE COPYING FOR DETAILS # SEE COPYING FOR DETAILS

View File

@@ -1,9 +1,8 @@
####################################################################### #######################################################################
# $Header: /cvs/src/chrony/examples/chrony.conf.example,v 1.2 2002/02/03 21:46:29 richard Exp $
# #
# This is an example chrony configuration file. You should copy it to # This is an example chrony configuration file. You should copy it to
# /etc/chrony.conf after uncommenting and editing the options that you # /etc/chrony.conf after uncommenting and editing the options that you
# want to enable. I have not included the more obscure options. Refer # want to enable. The more obscure options are not included. Refer
# to the documentation for these. # to the documentation for these.
# #
# Copyright 2002 Richard P. Curnow # Copyright 2002 Richard P. Curnow
@@ -19,7 +18,7 @@
# #
# You should have received a copy of the GNU General Public License along # 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., # with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
# #
####################################################################### #######################################################################
@@ -157,8 +156,8 @@ commandkey 1
! logdir /var/log/chrony ! logdir /var/log/chrony
! log measurements statistics tracking ! log measurements statistics tracking
If you have real time clock support enabled (see below), you might want # If you have real time clock support enabled (see below), you might want
this line instead: # this line instead:
! log measurements statistics tracking rtc ! log measurements statistics tracking rtc
@@ -209,6 +208,12 @@ this line instead:
! noclientlog ! noclientlog
# The clientlog size is limited to 512KB by default. If you have many
# clients, especially in many different subnets, you might want to
# increase the limit.
! clientloglimit 4194304
####################################################################### #######################################################################
### REPORTING BIG CLOCK CHANGES ### REPORTING BIG CLOCK CHANGES
# Perhaps you want to know if chronyd suddenly detects any large error # Perhaps you want to know if chronyd suddenly detects any large error
@@ -287,3 +292,21 @@ cmdallow 127.0.0.1
! rtcdevice /dev/misc/rtc ! rtcdevice /dev/misc/rtc
####################################################################### #######################################################################
### REAL TIME SCHEDULER
# This directive tells chronyd to use the real-time FIFO scheduler with the
# specified priority (which must be between 0 and 100). This should result
# in reduced latency. You don't need it unless you really have a requirement
# for extreme clock stability. Works only on Linux. Note that the "-P"
# command-line switch will override this.
! sched_priority 1
#######################################################################
### LOCKING CHRONYD INTO RAM
# This directive tells chronyd to use the mlockall() syscall to lock itself
# into RAM so that it will never be paged out. This should result in reduced
# latency. You don't need it unless you really have a requirement
# for extreme clock stability. Works only on Linux. Note that the "-m"
# command-line switch will also enable this feature.
! lock_all

67
faq.txt
View File

@@ -19,18 +19,12 @@
<p> <p>
This is a set of questions and answers to common problems and issues. This is a set of questions and answers to common problems and issues.
<p> <p>
As I receive more emails about the software, I will add new questions As we receive more emails about the software, we will add new questions
to this page. to this page.
<hr> <hr>
<p> <p>
The author can be reached by email The developers can be reached via the chrony-dev mailing list. See
<a href="mailto:rc@rc0.org.uk"> <a href="#question_1.4">question 1.4.</a> for details.
</a>
<p>
<b>PLEASE</b>
include the word &quot;chrony&quot; in your subject line if possible (so that my
mail reader can keep my mail sorted by topic)!
<hr> <hr>
<br clear=all> <br clear=all>
@@ -38,39 +32,34 @@ mail reader can keep my mail sorted by topic)!
S: Administrative issues S: Administrative issues
Q: Where can I get chrony source code? Q: Where can I get chrony source code?
Via the home page, see below. Tarballs are available via the <b>Download</b> link on the Chrony
Web site. For the current development from the developers' version control
system see the <b>Git</b> link on the Web site.
Q: Are there any packaged versions of chrony? Q: Are there any packaged versions of chrony?
I am aware of packages for Debian, Mandrake and Redhat. I am not personally We are aware of packages for Debian, Fedora, Gentoo, Mandriva, Slackware,
involved with how these are built or distributed. and Ubuntu. We are not involved with how these are built or distributed.
Q: Where is the home page? Q: Where is the home page?
It is currently at <a href="http://chrony.sunsite.dk/">http://chrony.sunsite.dk/</a>. It is currently at <a href="http://chrony.tuxfamily.org/">http://chrony.tuxfamily.org/</a>.
Q: Is there a mailing list? Q: Is there a mailing list?
Yes, it's currently at chrony-users@sunsite.dk. There is a low-volume Yes, it's currently at chrony-users@chrony.tuxfamily.org. There is a low-volume
list called chrony-announce which is just for announcements of new releases or list called chrony-announce which is just for announcements of new releases or
similar matters of high importance. You can join the lists by sending a similar matters of high importance. You can join the lists by sending a
message to <a href="mailto:chrony-users-subscribe@sunsite.dk">chrony-users-subscribe@sunsite.dk</a> or message with the subject subscribe to <a href="mailto:chrony-users-request@chrony.tuxfamily.org">chrony-users-request@chrony.tuxfamily.org</a> or
<a href="mailto:chrony-announce-subscribe@sunsite.dk">chrony-announce-subscribe@sunsite.dk</a> respectively. <a href="mailto:chrony-announce-request@chrony.tuxfamily.org">chrony-announce-request@chrony.tuxfamily.org</a> respectively.
For those who want to contribute to the development of chrony, there is a For those who want to contribute to the development of chrony, there is a
developers' mailing list. You can subscribe by sending mail to developers' mailing list. You can subscribe by sending mail with the
<a href="mailto:chrony-dev-subscribe@sunsite.dk">chrony-dev-subscribe@sunsite.dk</a>. subject subscribe to
<a href="mailto:chrony-dev-request@chrony.tuxfamily.org">chrony-dev-request@chrony.tuxfamily.org</a>.
Q: What licence is applied to chrony? Q: What licence is applied to chrony?
Starting from version 1.15, chrony is licensed under the GNU General Public Starting from version 1.15, chrony is licensed under the GNU General Public
License. Versions prior to 1.15 were licensed under a custom BSD-like License, Version 2. Versions prior to 1.15 were licensed under a custom BSD-like
license. license.
If you want to use parts of chrony in non-free software, you will need to use
older versions of the source code. Alternatively, contact me - I may be
prepared to licence parts of the source code to suit your purposes. I am quite
sympathetic to projects licensed under other free/open-source (but non-GPL)
licences, as well as to commercial projects which are of a single-customer
"turnkey" nature (as opposed to mass-market "shrink-wrap" or "floating-licence"
products).
S: Chrony compared to other programs S: Chrony compared to other programs
Q: How does chrony compare to xntpd? Q: How does chrony compare to xntpd?
If your computer is permenently connected, or connected for long periods (that If your computer is permenently connected, or connected for long periods (that
@@ -109,7 +98,7 @@ added some automated support in chrony to deal with this.
S: Compilation issues S: Compilation issues
Q:How do I apply source patches? Q:How do I apply source patches?
Sometimes I release source patches rather than a full version when I need to Sometimes we release source patches rather than a full version when we need to
provide a fix for small problems. Supposing you have chrony-1.X.tar.gz and a provide a fix for small problems. Supposing you have chrony-1.X.tar.gz and a
source patch chrony-1.X-1.X.1.gz. The steps required are: source patch chrony-1.X-1.X.1.gz. The steps required are:
@@ -221,12 +210,6 @@ files when chrony was compiled. The chrony.conf file can include options to
modify the HZ value (see the discussion of linux_hz and linux_freq_scale in the modify the HZ value (see the discussion of linux_hz and linux_freq_scale in the
documentation), however the problem is to find the value of HZ being used. documentation), however the problem is to find the value of HZ being used.
At the end of the chrony v1.18 section of the <a href="./download.php">download page</a>
you'll find instructions on how to do this.
This will be fixed in version 1.19, by getting chronyd to auto-detect the
kernel's value rather than relying on the compiled-in default.
S: Issues with chronyc S: Issues with chronyc
Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'. Q: I keep getting the error '510 No command access from this host --- Reply not authenticated'.
@@ -303,13 +286,11 @@ system-dependent. It needs adapting to work with Windows' equivalent of the
adjtimex() call, and it needs to be made to work as an NT service. adjtimex() call, and it needs to be made to work as an NT service.
Q: Are there any plans to support Windows? Q: Are there any plans to support Windows?
I have no personal plans to do this. I have neither the time nor the We have no plans to do this. Anyone is welcome to pick this work up and
Windows programming expertise. Some time ago I did start work on a port which
I was developing under Cygwin. Anyone is welcome to pick this work up and
contribute it back to the project. contribute it back to the project.
Q: What alternative NTP clients are there for Windows? Q: What alternative NTP clients are there for Windows?
Some of the names I've seen mentioned are Some of the names we've seen mentioned are
- Automachron - Automachron
- NetTime (nettime.sourceforge.net) - NetTime (nettime.sourceforge.net)
@@ -345,12 +326,10 @@ useful to avoid this situation.
S: Development S: Development
Q: Can I get the source via CVS from anywhere? Q: Can I get the source via git from anywhere?
Yes. See <a href="http://chrony.sunsite.dk/cvs.php">http://chrony.sunsite.dk/cvs.php</a> for information. Currently there is Yes. See the Git link at <a
only anonymous read-only access. I keep the master copy on my own PC, which is href="http://chrony.tuxfamily.org/">http://chrony.tuxfamily.org</a> for
more convenient for me because I don't have to connect to the Internet to do information.
CVS operations on the files. So for now, there is no read-write access for
other developers. Please email me your patches + documentation instead.
S: Linux-specific issues S: Linux-specific issues

2765
getdate.c

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Modified from the original to add stdlib.h and string.h */ /* Modified from the original to add stdlib.h and string.h */

1049
getdate.y Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,8 @@
/* Hmm. These constants vary a bit between systems. */ /* Hmm. These constants vary a bit between systems. */
/* (__sh__ includes both sh and sh64) */ /* (__sh__ includes both sh and sh64) */
#if defined(__i386__) || defined(__sh__) || defined(__arm__) /* (__s390__ includes both s390 and s390x) */
#if defined(__i386__) || defined(__sh__) || defined(__arm__) || defined(__x86_64__) || defined(__s390__)
#define CHRONY_IOC_NRBITS 8 #define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8 #define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 14 #define CHRONY_IOC_SIZEBITS 14
@@ -26,7 +27,7 @@
#define CHRONY_IOC_READ 2U #define CHRONY_IOC_READ 2U
#define CHRONY_IOC_WRITE 4U #define CHRONY_IOC_WRITE 4U
#elif defined(__mips__) || defined(__mips32__) #elif defined(__mips__) || defined(__mips32__) || defined(__powerpc__)
#define CHRONY_IOC_NRBITS 8 #define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8 #define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 13 #define CHRONY_IOC_SIZEBITS 13

2
keys.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

2
keys.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

19
local.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -54,6 +54,7 @@ static lcl_AccrueOffsetDriver drv_accrue_offset;
static lcl_ApplyStepOffsetDriver drv_apply_step_offset; static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
static lcl_OffsetCorrectionDriver drv_offset_convert; static lcl_OffsetCorrectionDriver drv_offset_convert;
static lcl_ImmediateStepDriver drv_immediate_step; static lcl_ImmediateStepDriver drv_immediate_step;
static lcl_SetLeapDriver drv_set_leap;
/* ================================================== */ /* ================================================== */
@@ -535,7 +536,8 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset, lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset, lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert, lcl_OffsetCorrectionDriver offset_convert,
lcl_ImmediateStepDriver immediate_step) lcl_ImmediateStepDriver immediate_step,
lcl_SetLeapDriver set_leap)
{ {
drv_read_freq = read_freq; drv_read_freq = read_freq;
drv_set_freq = set_freq; drv_set_freq = set_freq;
@@ -543,6 +545,7 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
drv_apply_step_offset = apply_step_offset; drv_apply_step_offset = apply_step_offset;
drv_offset_convert = offset_convert; drv_offset_convert = offset_convert;
drv_immediate_step = immediate_step; drv_immediate_step = immediate_step;
drv_set_leap = set_leap;
current_freq_ppm = (*drv_read_freq)(); current_freq_ppm = (*drv_read_freq)();
@@ -572,3 +575,15 @@ LCL_MakeStep(void)
} }
/* ================================================== */ /* ================================================== */
void
LCL_SetLeap(int leap)
{
if (drv_set_leap) {
(drv_set_leap)(leap);
}
return;
}
/* ================================================== */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -181,4 +181,9 @@ extern void LCL_Finalise(void);
to a timezone problem. */ to a timezone problem. */
extern int LCL_MakeStep(void); extern int LCL_MakeStep(void);
/* Routine to schedule a leap second. Leap second will be inserted
at the end of the day if argument is positive, deleted if negative,
and zero cancels scheduled leap second. */
extern void LCL_SetLeap(int leap);
#endif /* GOT_LOCAL_H */ #endif /* GOT_LOCAL_H */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -60,6 +60,9 @@ typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
as an immediate step instead */ as an immediate step instead */
typedef void (*lcl_ImmediateStepDriver)(void); typedef void (*lcl_ImmediateStepDriver)(void);
/* System driver to schedule leap second */
typedef void (*lcl_SetLeapDriver)(int leap);
extern void lcl_InvokeDispersionNotifyHandlers(double dispersion); extern void lcl_InvokeDispersionNotifyHandlers(double dispersion);
extern void extern void
@@ -68,6 +71,7 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset, lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset, lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert, lcl_OffsetCorrectionDriver offset_convert,
lcl_ImmediateStepDriver immediate_step_driver); lcl_ImmediateStepDriver immediate_step_driver,
lcl_SetLeapDriver set_leap);
#endif /* GOT_LOCALP_H */ #endif /* GOT_LOCALP_H */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -214,3 +214,19 @@ LOG_GoDaemon(void)
} }
/* ================================================== */ /* ================================================== */
/* Force a core dump and exit without doing abort() or assert(0).
These do funny things with the call stack in the core file that is
generated, which makes diagnosis difficult. */
int
croak(const char *file, int line, const char *msg)
{
int a;
LOG(LOGS_ERR, LOGF_Util, "Unexpected condition [%s] at %s:%d, core dumped",
msg, file, line);
a = * (int *) 0;
return a; /* Can't happen - this stops the optimiser optimising the
line above */
}
/* ================================================== */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -53,6 +53,7 @@ typedef enum {
LOGF_Local, LOGF_Local,
LOGF_Util, LOGF_Util,
LOGF_Main, LOGF_Main,
LOGF_ClientLog,
LOGF_Configure, LOGF_Configure,
LOGF_CmdMon, LOGF_CmdMon,
LOGF_Acquire, LOGF_Acquire,
@@ -60,11 +61,13 @@ typedef enum {
LOGF_Logging, LOGF_Logging,
LOGF_Rtc, LOGF_Rtc,
LOGF_Regress, LOGF_Regress,
LOGF_Sys,
LOGF_SysLinux, LOGF_SysLinux,
LOGF_SysSolaris, LOGF_SysSolaris,
LOGF_SysSunOS, LOGF_SysSunOS,
LOGF_SysWinnt, LOGF_SysWinnt,
LOGF_RtcLinux LOGF_RtcLinux,
LOGF_Refclock
} LOG_Facility; } LOG_Facility;
/* Init function */ /* Init function */
@@ -94,4 +97,13 @@ extern void LOG_GoDaemon(void);
#define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function #define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function
#endif /* defined (__GNUC__) */ #endif /* defined (__GNUC__) */
/* Like assert(0) */
#if defined(LINUX) && defined(__alpha__)
#define CROAK(message) assert(0) /* Added JGH Feb 24 2001 FIXME */
#else
extern int croak(const char *file, int line, const char *msg);
#define CROAK(message) croak(__FILE__, __LINE__, message);
#endif
#endif /* GOT_LOGGING_H */ #endif /* GOT_LOGGING_H */

60
main.c
View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -48,8 +49,10 @@
#include "manual.h" #include "manual.h"
#include "version.h" #include "version.h"
#include "rtc.h" #include "rtc.h"
#include "refclock.h"
#include "clientlog.h" #include "clientlog.h"
#include "broadcast.h" #include "broadcast.h"
#include "nameserv.h"
/* ================================================== */ /* ================================================== */
@@ -83,19 +86,20 @@ MAI_CleanupAndExit(void)
SRC_DumpSources(); SRC_DumpSources();
} }
RTC_Finalise();
MNL_Finalise(); MNL_Finalise();
ACQ_Finalise(); ACQ_Finalise();
CAM_Finalise();
KEY_Finalise(); KEY_Finalise();
CLG_Finalise(); CLG_Finalise();
NIO_Finalise();
NSR_Finalise(); NSR_Finalise();
NCR_Finalise(); NCR_Finalise();
BRD_Finalise(); BRD_Finalise();
SRC_Finalise(); SRC_Finalise();
SST_Finalise(); SST_Finalise();
REF_Finalise(); REF_Finalise();
RCL_Finalise();
RTC_Finalise();
CAM_Finalise();
NIO_Finalise();
SYS_Finalise(); SYS_Finalise();
SCH_Finalise(); SCH_Finalise();
LCL_Finalise(); LCL_Finalise();
@@ -113,7 +117,8 @@ static void
signal_cleanup(int x) signal_cleanup(int x)
{ {
LOG(LOGS_WARN, LOGF_Main, "chronyd exiting on signal"); LOG(LOGS_WARN, LOGF_Main, "chronyd exiting on signal");
MAI_CleanupAndExit(); if (!initialised) exit(0);
SCH_QuitProgram();
} }
/* ================================================== */ /* ================================================== */
@@ -134,6 +139,7 @@ post_acquire_hook(void *anything)
CNF_SetupAccessRestrictions(); CNF_SetupAccessRestrictions();
RTC_StartMeasurements(); RTC_StartMeasurements();
RCL_StartRefclocks();
} }
/* ================================================== */ /* ================================================== */
@@ -206,9 +212,11 @@ int main
(int argc, char **argv) (int argc, char **argv)
{ {
char *conf_file = NULL; char *conf_file = NULL;
char *user = NULL;
int debug = 0; int debug = 0;
int do_init_rtc = 0; int do_init_rtc = 0;
int other_pid; int other_pid;
int lock_memory = 0, sched_priority = 0;
LOG_Initialise(); LOG_Initialise();
@@ -218,8 +226,22 @@ int main
if (!strcmp("-f", *argv)) { if (!strcmp("-f", *argv)) {
++argv, --argc; ++argv, --argc;
conf_file = *argv; conf_file = *argv;
} else if (!strcmp("-P", *argv)) {
++argv, --argc;
if (argc == 0 || sscanf(*argv, "%d", &sched_priority) != 1) {
LOG_FATAL(LOGF_Main, "Bad scheduler priority");
}
} else if (!strcmp("-m", *argv)) {
lock_memory = 1;
} else if (!strcmp("-r", *argv)) { } else if (!strcmp("-r", *argv)) {
reload = 1; reload = 1;
} else if (!strcmp("-u", *argv)) {
++argv, --argc;
if (argc == 0) {
LOG_FATAL(LOGF_Main, "Missing user name");
} else {
user = *argv;
}
} else if (!strcmp("-s", *argv)) { } else if (!strcmp("-s", *argv)) {
do_init_rtc = 1; do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) { } else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
@@ -228,6 +250,10 @@ int main
exit(0); exit(0);
} else if (!strcmp("-d", *argv)) { } else if (!strcmp("-d", *argv)) {
debug = 1; debug = 1;
} else if (!strcmp("-4", *argv)) {
DNS_SetAddressFamily(IPADDR_INET4);
} else if (!strcmp("-6", *argv)) {
DNS_SetAddressFamily(IPADDR_INET6);
} else { } else {
LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv); LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv);
} }
@@ -269,19 +295,37 @@ int main
LCL_Initialise(); LCL_Initialise();
SCH_Initialise(); SCH_Initialise();
SYS_Initialise(); SYS_Initialise();
NIO_Initialise();
CAM_Initialise();
RTC_Initialise();
RCL_Initialise();
/* Command-line switch must have priority */
if (!sched_priority) {
sched_priority = CNF_GetSchedPriority();
}
if (sched_priority) {
SYS_SetScheduler(sched_priority);
}
if (lock_memory || CNF_GetLockMemory()) {
SYS_LockMemory();
}
if (user) {
SYS_DropRoot(user);
}
REF_Initialise(); REF_Initialise();
SST_Initialise(); SST_Initialise();
SRC_Initialise(); SRC_Initialise();
BRD_Initialise(); BRD_Initialise();
NCR_Initialise(); NCR_Initialise();
NSR_Initialise(); NSR_Initialise();
NIO_Initialise();
CLG_Initialise(); CLG_Initialise();
KEY_Initialise(); KEY_Initialise();
CAM_Initialise();
ACQ_Initialise(); ACQ_Initialise();
MNL_Initialise(); MNL_Initialise();
RTC_Initialise();
/* From now on, it is safe to do finalisation on exit */ /* From now on, it is safe to do finalisation on exit */
initialised = 1; initialised = 1;

2
main.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -13,13 +13,13 @@ unless (-d "RELEASES") {
mkdir "RELEASES", 0755; mkdir "RELEASES", 0755;
} }
system ("git-tag -s $version"); system ("git tag -s $version");
die "git-tag failed" if ($? != 0); die "git-tag failed" if ($? != 0);
if (-d "RELEASES/$subdir") { if (-d "RELEASES/$subdir") {
system ("rm -rf RELEASES/$subdir"); system ("rm -rf RELEASES/$subdir");
} }
system ("git-archive --format=tar --prefix=RELEASES/${subdir}/ $version | tar xf -"); system ("git archive --format=tar --prefix=RELEASES/${subdir}/ $version | tar xf -");
die "git-tar-tree failed" if ($? != 0); die "git-tar-tree failed" if ($? != 0);
chdir "RELEASES"; chdir "RELEASES";

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -287,7 +287,7 @@ MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n)
} }
for (i=0; i<n_samples && i<max; i++) { for (i=0; i<n_samples && i<max; i++) {
report[i].when = samples[i].when.tv_sec; report[i].when = samples[i].when;
report[i].slewed_offset = samples[i].offset; report[i].slewed_offset = samples[i].offset;
report[i].orig_offset = samples[i].orig_offset; report[i].orig_offset = samples[i].orig_offset;
report[i].residual = samples[i].residual; report[i].residual = samples[i].residual;

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -32,60 +33,146 @@
#include "sysincl.h" #include "sysincl.h"
#include "nameserv.h" #include "nameserv.h"
#include "util.h"
#include <resolv.h>
/* ================================================== */ /* ================================================== */
unsigned long #define MAXRETRIES 10
DNS_Name2IPAddress(const char *name) static unsigned int retries = 0;
{
struct hostent *host;
unsigned char *address0;
unsigned long result;
static int address_family = IPADDR_UNSPEC;
void
DNS_SetAddressFamily(int family)
{
address_family = family;
}
int
DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
{
#ifdef HAVE_IPV6
struct addrinfo hints, *res, *ai;
int result;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
#endif
try_again:
result = getaddrinfo(name, NULL, &hints, &res);
if (result) {
if (retry && result == EAI_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
return 0;
}
for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
switch (ai->ai_family) {
case AF_INET:
addr->family = IPADDR_INET4;
addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
result = 1;
break;
#ifdef HAVE_IPV6
case AF_INET6:
addr->family = IPADDR_INET6;
memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
result = 1;
break;
#endif
}
if (result && address_family != IPADDR_UNSPEC && address_family != addr->family)
result = 0;
}
freeaddrinfo(res);
return result;
#else
struct hostent *host;
char *address0;
try_again:
host = gethostbyname(name); host = gethostbyname(name);
if (host == NULL) { if (host == NULL) {
result = DNS_Failed_Address; if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
} else { } else {
addr->family = IPADDR_INET4;
address0 = host->h_addr_list[0]; address0 = host->h_addr_list[0];
result = ((((unsigned long)address0[0])<<24) | addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) | (((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) | (((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3]))); (((unsigned long)address0[3])));
return 1;
} }
return result; return 0;
#endif
} }
/* ================================================== */ /* ================================================== */
const char * void
DNS_IPAddress2Name(unsigned long ip_addr) DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
{ {
struct hostent *host; #ifdef HAVE_IPV6
static char buffer[16]; int result;
unsigned int a, b, c, d; struct sockaddr_in in4;
unsigned long addr; struct sockaddr_in6 in6;
addr = htonl(ip_addr); switch (ip_addr->family) {
if (addr == 0UL) { case IPADDR_INET4:
/* Catch this as a special case that will never resolve to memset(&in4, 0, sizeof (in4));
anything */ in4.sin_family = AF_INET;
strcpy(buffer, "0.0.0.0"); in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
return buffer; result = getnameinfo((const struct sockaddr *)&in4, sizeof (in4), name, len, NULL, 0, 0);
} else { break;
case IPADDR_INET6:
memset(&in6, 0, sizeof (in6));
in6.sin6_family = AF_INET6;
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
result = getnameinfo((const struct sockaddr *)&in6, sizeof (in6), name, len, NULL, 0, 0);
break;
default:
result = 1;
}
if (result)
snprintf(name, len, "%s", UTI_IPToString(ip_addr));
#else
struct hostent *host;
uint32_t addr;
switch (ip_addr->family) {
case IPADDR_INET4:
addr = htonl(ip_addr->addr.in4);
host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET); host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET);
if (!host) { break;
a = (ip_addr >> 24) & 0xff; #ifdef HAVE_IPV6
b = (ip_addr >> 16) & 0xff; case IPADDR_INET6:
c = (ip_addr >> 8) & 0xff; host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
d = (ip_addr) & 0xff; break;
snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", a, b, c, d); #endif
return buffer; default:
} else { host = NULL;
return host->h_name;
}
} }
snprintf(name, len, "%s", host ? host->h_name : UTI_IPToString(ip_addr));
#endif
} }
/* ================================================== */ /* ================================================== */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -32,11 +32,14 @@
#ifndef GOT_NAMESERV_H #ifndef GOT_NAMESERV_H
#define GOT_NAMESERV_H #define GOT_NAMESERV_H
static const unsigned long DNS_Failed_Address = 0x0UL; #include "addressing.h"
extern unsigned long DNS_Name2IPAddress(const char *name); /* Resolve names only to selected address family */
extern void DNS_SetAddressFamily(int family);
const char *DNS_IPAddress2Name(unsigned long ip_addr); extern int DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry);
extern void DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
#endif /* GOT_NAMESERV_H */ #endif /* GOT_NAMESERV_H */

2
ntp.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -300,6 +301,9 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
result->tx_count = 0; result->tx_count = 0;
result->remote_orig.hi = 0;
result->remote_orig.lo = 0;
result->score = 0; result->score = 0;
if (params->online) { if (params->online) {
@@ -316,10 +320,12 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
result->local_poll = params->minpoll; result->local_poll = params->minpoll;
/* Create a source instance for this NTP source */ /* Create a source instance for this NTP source */
result->source = SRC_CreateNewInstance(remote_addr->ip_addr); /* Will need extra params eventually */ result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, &result->remote_addr.ip_addr);
result->local_rx.tv_sec = 0; result->local_rx.tv_sec = 0;
result->local_rx.tv_usec = 0; result->local_rx.tv_usec = 0;
result->local_tx.tv_sec = 0;
result->local_tx.tv_usec = 0;
return result; return result;
@@ -621,7 +627,7 @@ transmit_timeout(void *arg)
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]", LOG(LOGS_INFO, LOGF_NtpCore, "Transmit timeout for [%s:%d]",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), inst->remote_addr.port); UTI_IPToString(&inst->remote_addr.ip_addr), inst->remote_addr.port);
#endif #endif
/* Check whether we need to 'warm up' the link to the other end by /* Check whether we need to 'warm up' the link to the other end by
@@ -809,8 +815,12 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
int valid_data; int valid_data;
int valid_header; int valid_header;
/* Kiss-of-Death packets */
int kod_rate = 0;
int valid_kod;
/* Variables used for doing logging */ /* Variables used for doing logging */
static char sync_stats[4] = {'N', '-', '+', '?'}; static char sync_stats[4] = {'N', '+', '-', '?'};
/* The estimated offset predicted from previous samples. The /* The estimated offset predicted from previous samples. The
convention here is that positive means local clock FAST of convention here is that positive means local clock FAST of
@@ -1015,6 +1025,14 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
test8 = 1; test8 = 1;
} }
/* Check for Kiss-of-Death */
if (message->stratum > NTP_MAX_STRATUM && !source_is_synchronized) {
if (!memcmp(&message->reference_id, "RATE", 4))
kod_rate = 1;
}
valid_kod = test1 && test2 && test5;
valid_data = test1 && test2 && test3 && test4 && test4a && test4b; valid_data = test1 && test2 && test3 && test4 && test4a && test4b;
valid_header = test5 && test6 && test7 && test8; valid_header = test5 && test6 && test7 && test8;
@@ -1026,8 +1044,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
message->lvm, message->stratum, message->poll, message->precision); message->lvm, message->stratum, message->poll, message->precision);
LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)", LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion); message->root_delay, pkt_root_delay, message->root_dispersion, pkt_root_dispersion);
LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%s], ref_time=%08lx.%08lx [%s]", LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
UTI_IPToDottedQuad(ntohl(message->reference_id)), ntohl(message->reference_id),
message->reference_ts.hi, message->reference_ts.lo, message->reference_ts.hi, message->reference_ts.lo,
UTI_TimestampToString(&message->reference_ts)); UTI_TimestampToString(&message->reference_ts));
LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]", LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]",
@@ -1049,9 +1067,11 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
LOG(LOGS_INFO, LOGF_NtpCore, "test5=%d test6=%d test7=%d test8=%d valid_header=%d", LOG(LOGS_INFO, LOGF_NtpCore, "test5=%d test6=%d test7=%d test8=%d valid_header=%d",
test5, test6, test7, test8, valid_header); test5, test6, test7, test8, valid_header);
LOG(LOGS_INFO, LOGF_NtpCore, "kod_rate=%d valid_kod=%d", kod_rate, valid_kod);
#endif #endif
if (valid_header) { if (valid_header && valid_data) {
inst->tx_count = 0; inst->tx_count = 0;
SRC_SetReachable(inst->source); SRC_SetReachable(inst->source);
} }
@@ -1216,6 +1236,19 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
} }
/* Reduce polling if KoD RATE was received */
if (kod_rate && valid_kod) {
if (inst->remote_poll > inst->minpoll) {
inst->minpoll = inst->remote_poll;
if (inst->minpoll > inst->maxpoll)
inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Received KoD RATE from %s, minpoll set to %d", UTI_IPToString(&inst->remote_addr.ip_addr), inst->minpoll);
}
/* Back off for a while */
delay_time += (double) (4 * (1UL << inst->minpoll));
}
if (requeue_transmit) { if (requeue_transmit) {
/* Get rid of old timeout and start a new one */ /* Get rid of old timeout and start a new one */
@@ -1236,7 +1269,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n", fprintf(logfile, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e\n",
UTI_TimeToLogForm(sample_time.tv_sec), UTI_TimeToLogForm(sample_time.tv_sec),
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), UTI_IPToString(&inst->remote_addr.ip_addr),
sync_stats[pkt_leap], sync_stats[pkt_leap],
message->stratum, message->stratum,
test1, test2, test3, test4, test1, test2, test3, test4,
@@ -1325,9 +1358,9 @@ process_known
one of the secondaries to flywheel it. The behaviour coded here one of the secondaries to flywheel it. The behaviour coded here
is required in the secondaries to make this possible. */ is required in the secondaries to make this possible. */
if (ADF_IsAllowed(access_auth_table, inst->remote_addr.ip_addr)) { if (ADF_IsAllowed(access_auth_table, &inst->remote_addr.ip_addr)) {
CLG_LogNTPClientAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
if (do_auth) { if (do_auth) {
auth_key_id = ntohl(message->auth_keyid); auth_key_id = ntohl(message->auth_keyid);
@@ -1360,7 +1393,7 @@ process_known
} else { } else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d", LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), UTI_IPToString(&inst->remote_addr.ip_addr),
inst->remote_addr.port); inst->remote_addr.port);
} }
@@ -1371,7 +1404,7 @@ process_known
switch(inst->mode) { switch(inst->mode) {
case MODE_ACTIVE: case MODE_ACTIVE:
/* Ordinary symmetric peering */ /* Ordinary symmetric peering */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@@ -1381,7 +1414,7 @@ process_known
case MODE_CLIENT: case MODE_CLIENT:
/* This is where we have the remote configured as a server and he has /* This is where we have the remote configured as a server and he has
us configured as a peer - fair enough. */ us configured as a peer - fair enough. */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_SERVER: case MODE_SERVER:
@@ -1402,7 +1435,7 @@ process_known
switch(inst->mode) { switch(inst->mode) {
case MODE_ACTIVE: case MODE_ACTIVE:
/* Slightly bizarre combination, but we can still process it */ /* Slightly bizarre combination, but we can still process it */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@@ -1430,7 +1463,7 @@ process_known
case MODE_ACTIVE: case MODE_ACTIVE:
/* This would arise if we have the remote configured as a peer and /* This would arise if we have the remote configured as a peer and
he does not have us configured */ he does not have us configured */
CLG_LogNTPPeerAccess(inst->remote_addr.ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&inst->remote_addr.ip_addr, (time_t) now->tv_sec);
receive_packet(message, now, inst, do_auth); receive_packet(message, now, inst, do_auth);
break; break;
case MODE_PASSIVE: case MODE_PASSIVE:
@@ -1492,19 +1525,19 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
NTP_Mode my_mode; NTP_Mode my_mode;
int my_poll; int my_poll;
if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) { if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07; his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) { if (his_mode == MODE_CLIENT) {
/* We are server */ /* We are server */
my_mode = MODE_SERVER; my_mode = MODE_SERVER;
CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) { } else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */ /* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE; my_mode = MODE_PASSIVE;
CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else { } else {
my_mode = MODE_UNDEFINED; my_mode = MODE_UNDEFINED;
@@ -1528,7 +1561,7 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
} }
} else { } else {
LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d", LOG(LOGS_WARN, LOGF_NtpCore, "NTP packet received from unauthorised host %s port %d",
UTI_IPToDottedQuad(remote_addr->ip_addr), UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port); remote_addr->port);
} }
@@ -1562,19 +1595,19 @@ NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Addr
int valid_key, valid_auth; int valid_key, valid_auth;
unsigned long key_id; unsigned long key_id;
if (ADF_IsAllowed(access_auth_table, remote_addr->ip_addr)) { if (ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) {
his_mode = message->lvm & 0x07; his_mode = message->lvm & 0x07;
if (his_mode == MODE_CLIENT) { if (his_mode == MODE_CLIENT) {
/* We are server */ /* We are server */
my_mode = MODE_SERVER; my_mode = MODE_SERVER;
CLG_LogNTPClientAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPClientAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else if (his_mode == MODE_ACTIVE) { } else if (his_mode == MODE_ACTIVE) {
/* We are symmetric passive, even though we don't ever lock to him */ /* We are symmetric passive, even though we don't ever lock to him */
my_mode = MODE_PASSIVE; my_mode = MODE_PASSIVE;
CLG_LogNTPPeerAccess(remote_addr->ip_addr, (time_t) now->tv_sec); CLG_LogNTPPeerAccess(&remote_addr->ip_addr, (time_t) now->tv_sec);
} else { } else {
my_mode = MODE_UNDEFINED; my_mode = MODE_UNDEFINED;
@@ -1646,7 +1679,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
case MD_OFFLINE: case MD_OFFLINE:
if (!inst->timer_running) { if (!inst->timer_running) {
/* We are not already actively polling it */ /* We are not already actively polling it */
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToDottedQuad(inst->remote_addr.ip_addr)); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
inst->local_poll = inst->minpoll; inst->local_poll = inst->minpoll;
inst->score = (ZONE_WIDTH >> 1); inst->score = (ZONE_WIDTH >> 1);
inst->opmode = MD_ONLINE; inst->opmode = MD_ONLINE;
@@ -1670,7 +1703,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
switch (inst->opmode) { switch (inst->opmode) {
case MD_ONLINE: case MD_ONLINE:
if (inst->timer_running) { if (inst->timer_running) {
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToDottedQuad(inst->remote_addr.ip_addr)); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s offline", UTI_IPToString(&inst->remote_addr.ip_addr));
SCH_RemoveTimeout(inst->timeout_id); SCH_RemoveTimeout(inst->timeout_id);
inst->timer_running = 0; inst->timer_running = 0;
inst->opmode = MD_OFFLINE; inst->opmode = MD_OFFLINE;
@@ -1693,7 +1726,7 @@ void
NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll) NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll)
{ {
inst->minpoll = new_minpoll; inst->minpoll = new_minpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_minpoll); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll);
} }
/* ================================================== */ /* ================================================== */
@@ -1702,7 +1735,7 @@ void
NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll) NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll)
{ {
inst->maxpoll = new_maxpoll; inst->maxpoll = new_maxpoll;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_maxpoll); LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll);
} }
/* ================================================== */ /* ================================================== */
@@ -1712,7 +1745,7 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
{ {
inst->max_delay = new_max_delay; inst->max_delay = new_max_delay;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f", LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay %f",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay); UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay);
} }
/* ================================================== */ /* ================================================== */
@@ -1722,7 +1755,7 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
{ {
inst->max_delay_ratio = new_max_delay_ratio; inst->max_delay_ratio = new_max_delay_ratio;
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f", LOG(LOGS_INFO, LOGF_NtpCore, "Source %s new max delay ratio %f",
UTI_IPToDottedQuad(inst->remote_addr.ip_addr), new_max_delay_ratio); UTI_IPToString(&inst->remote_addr.ip_addr), new_max_delay_ratio);
} }
/* ================================================== */ /* ================================================== */
@@ -1804,7 +1837,7 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *no
/* ================================================== */ /* ================================================== */
int int
NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all) NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{ {
ADF_Status status; ADF_Status status;
@@ -1834,7 +1867,7 @@ NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */ /* ================================================== */
int int
NCR_CheckAccessRestriction(unsigned long ip_addr) NCR_CheckAccessRestriction(IPAddr *ip_addr)
{ {
return ADF_IsAllowed(access_auth_table, ip_addr); return ADF_IsAllowed(access_auth_table, ip_addr);
} }
@@ -1880,3 +1913,11 @@ NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
} }
/* ================================================== */ /* ================================================== */
NTP_Remote_Address *
NCR_GetRemoteAddress(NCR_Instance inst)
{
return &inst->remote_addr;
}
/* ================================================== */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -94,12 +94,14 @@ extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now); extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
extern int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all); extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(unsigned long ip_addr); extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void); extern void NCR_CycleLogFile(void);
extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline, extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
int *burst_online, int *burst_offline); int *burst_online, int *burst_offline);
extern NTP_Remote_Address *NCR_GetRemoteAddress(NCR_Instance instance);
#endif /* GOT_NTP_CORE_H */ #endif /* GOT_NTP_CORE_H */

367
ntp_io.c
View File

@@ -7,6 +7,8 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +21,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -41,8 +43,19 @@
#include <fcntl.h> #include <fcntl.h>
/* The file descriptor for the socket */ union sockaddr_in46 {
static int sock_fd; struct sockaddr_in in4;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
/* The file descriptors for the IPv4 and IPv6 sockets */
static int sock_fd4;
#ifdef HAVE_IPV6
static int sock_fd6;
#endif
/* Flag indicating that we have been initialised */ /* Flag indicating that we have been initialised */
static int initialised=0; static int initialised=0;
@@ -50,6 +63,7 @@ static int initialised=0;
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
static int prepare_socket(int family);
static void read_from_socket(void *anything); static void read_from_socket(void *anything);
/* ================================================== */ /* ================================================== */
@@ -81,30 +95,30 @@ do_size_checks(void)
/* ================================================== */ /* ================================================== */
void static int
NIO_Initialise(void) prepare_socket(int family)
{ {
struct sockaddr_in my_addr; union sockaddr_in46 my_addr;
socklen_t my_addr_len;
int sock_fd;
unsigned short port_number; unsigned short port_number;
unsigned long bind_address; IPAddr bind_address;
int on_off = 1; int on_off = 1;
assert(!initialised);
initialised = 1;
do_size_checks();
port_number = CNF_GetNTPPort(); port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */ /* Open Internet domain UDP socket for NTP message transmissions */
#if 0 #if 0
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
#else #else
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); sock_fd = socket(family, SOCK_DGRAM, 0);
#endif #endif
if (sock_fd < 0) { if (sock_fd < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not open socket : %s", strerror(errno)); LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
return -1;
} }
/* Make the socket capable of re-using an old address */ /* Make the socket capable of re-using an old address */
@@ -119,28 +133,80 @@ NIO_Initialise(void)
/* Don't quit - we might survive anyway */ /* Don't quit - we might survive anyway */
} }
#ifdef SO_TIMESTAMP
/* Enable receiving of timestamp control messages */
if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMP, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set timestamp socket options");
/* Don't quit - we might survive anyway */
}
#endif
if (family == AF_INET) {
#ifdef IP_PKTINFO
/* We want the local IP info too */
if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
/* Don't quit - we might survive anyway */
}
#endif
}
#ifdef HAVE_IPV6
else if (family == AF_INET6) {
#ifdef IPV6_V6ONLY
/* Receive IPv6 packets only */
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not request IPV6_V6ONLY socket option");
}
#endif
}
#endif
/* Bind the port */ /* Bind the port */
my_addr.sin_family = AF_INET; memset(&my_addr, 0, sizeof (my_addr));
my_addr.sin_port = htons(port_number);
CNF_GetBindAddress(&bind_address); switch (family) {
case AF_INET:
my_addr_len = sizeof (my_addr.in4);
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons(port_number);
if (bind_address != 0UL) { CNF_GetBindAddress(IPADDR_INET4, &bind_address);
my_addr.sin_addr.s_addr = htonl(bind_address);
} else { if (bind_address.family == IPADDR_INET4)
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
else
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
break;
#ifdef HAVE_IPV6
case AF_INET6:
my_addr_len = sizeof (my_addr.in6);
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons(port_number);
CNF_GetBindAddress(IPADDR_INET6, &bind_address);
if (bind_address.family == IPADDR_INET6)
memcpy(my_addr.in6.sin6_addr.s6_addr, bind_address.addr.in6,
sizeof (my_addr.in6.sin6_addr.s6_addr));
else
my_addr.in6.sin6_addr = in6addr_any;
break;
#endif
default:
assert(0);
} }
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd); LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#endif #endif
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno)); LOG_FATAL(LOGF_NtpIO, "Could not bind %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
} }
/* Register handler for read events on the socket */ /* Register handler for read events on the socket */
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL); SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
#if 0 #if 0
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) { if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
@@ -151,6 +217,29 @@ NIO_Initialise(void)
LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal"); LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
} }
#endif #endif
return sock_fd;
}
void
NIO_Initialise(void)
{
assert(!initialised);
initialised = 1;
do_size_checks();
sock_fd4 = prepare_socket(AF_INET);
#ifdef HAVE_IPV6
sock_fd6 = prepare_socket(AF_INET6);
#endif
if (sock_fd4 < 0
#ifdef HAVE_IPV6
&& sock_fd6 < 0
#endif
) {
LOG_FATAL(LOGF_NtpIO, "Could not open any NTP socket");
}
return; return;
} }
@@ -160,11 +249,18 @@ NIO_Initialise(void)
void void
NIO_Finalise(void) NIO_Finalise(void)
{ {
if (sock_fd >= 0) { if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd); SCH_RemoveInputFileHandler(sock_fd4);
close(sock_fd); close(sock_fd4);
} }
sock_fd = -1; sock_fd4 = -1;
#ifdef HAVE_IPV6
if (sock_fd6 >= 0) {
SCH_RemoveInputFileHandler(sock_fd6);
close(sock_fd6);
}
sock_fd6 = -1;
#endif
initialised = 0; initialised = 0;
return; return;
} }
@@ -180,24 +276,33 @@ read_from_socket(void *anything)
/* This should only be called when there is something /* This should only be called when there is something
to read, otherwise it will block. */ to read, otherwise it will block. */
int status; int status, sock_fd;
ReceiveBuffer message; ReceiveBuffer message;
int message_length; union sockaddr_in46 where_from;
struct sockaddr_in where_from;
socklen_t from_length;
unsigned int flags = 0; unsigned int flags = 0;
struct timeval now; struct timeval now;
NTP_Remote_Address remote_addr; NTP_Remote_Address remote_addr;
double local_clock_err; char cmsgbuf[256];
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
assert(initialised); assert(initialised);
from_length = sizeof(where_from); SCH_GetFileReadyTime(&now);
message_length = sizeof(message);
LCL_ReadCookedTime(&now, &local_clock_err); iov.iov_base = message.arbitrary;
status = recvfrom(sock_fd, (char *)&message, message_length, flags, iov.iov_len = sizeof(message);
(struct sockaddr *)&where_from, &from_length); msg.msg_name = &where_from;
msg.msg_namelen = sizeof(where_from);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = (void *) cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0;
sock_fd = (long)anything;
status = recvmsg(sock_fd, &msg, flags);
/* Don't bother checking if read failed or why if it did. More /* Don't bother checking if read failed or why if it did. More
likely than not, it will be connection refused, resulting from a likely than not, it will be connection refused, resulting from a
@@ -207,8 +312,53 @@ read_from_socket(void *anything)
reponse on a subsequent recvfrom). */ reponse on a subsequent recvfrom). */
if (status > 0) { if (status > 0) {
remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr); memset(&remote_addr, 0, sizeof (remote_addr));
remote_addr.port = ntohs(where_from.sin_port);
switch (where_from.u.sa_family) {
case AF_INET:
remote_addr.ip_addr.family = IPADDR_INET4;
remote_addr.ip_addr.addr.in4 = ntohl(where_from.in4.sin_addr.s_addr);
remote_addr.port = ntohs(where_from.in4.sin_port);
break;
#ifdef HAVE_IPV6
case AF_INET6:
remote_addr.ip_addr.family = IPADDR_INET6;
memcpy(&remote_addr.ip_addr.addr.in6, where_from.in6.sin6_addr.s6_addr,
sizeof (remote_addr.ip_addr.addr.in6));
remote_addr.port = ntohs(where_from.in6.sin6_port);
break;
#endif
default:
assert(0);
}
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
#ifdef IP_PKTINFO
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
struct in_pktinfo ipi;
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
remote_addr.local_ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
remote_addr.local_ip_addr.family = IPADDR_INET4;
}
#endif
#ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
double correction;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
correction = LCL_GetOffsetCorrection(&tv);
UTI_AddDoubleToTimeval(&tv, correction, &tv);
#if 0
UTI_DiffTimevalsToDouble(&correction, &now, &tv);
LOG(LOGS_INFO, LOGF_NtpIO, "timestamp diff: %f", correction);
#endif
now = tv;
}
#endif
}
if (status == NTP_NORMAL_PACKET_SIZE) { if (status == NTP_NORMAL_PACKET_SIZE) {
@@ -228,27 +378,103 @@ read_from_socket(void *anything)
return; return;
} }
/* ================================================== */
/* Send a packet to given address */
static void
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr)
{
union sockaddr_in46 remote;
struct msghdr msg;
struct iovec iov;
char cmsgbuf[256];
int cmsglen;
int sock_fd;
socklen_t addrlen;
assert(initialised);
switch (remote_addr->ip_addr.family) {
case IPADDR_INET4:
memset(&remote.in4, 0, sizeof (remote.in4));
addrlen = sizeof (remote.in4);
remote.in4.sin_family = AF_INET;
remote.in4.sin_port = htons(remote_addr->port);
remote.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
sock_fd = sock_fd4;
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
memset(&remote.in6, 0, sizeof (remote.in6));
addrlen = sizeof (remote.in6);
remote.in6.sin6_family = AF_INET6;
remote.in6.sin6_port = htons(remote_addr->port);
memcpy(&remote.in6.sin6_addr.s6_addr, &remote_addr->ip_addr.addr.in6,
sizeof (remote.in6.sin6_addr.s6_addr));
sock_fd = sock_fd6;
break;
#endif
default:
return;
}
if (sock_fd < 0)
return;
iov.iov_base = packet;
iov.iov_len = packetlen;
msg.msg_name = &remote.u;
msg.msg_namelen = addrlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0;
cmsglen = 0;
#ifdef IP_PKTINFO
if (remote_addr->local_ip_addr.family == IPADDR_INET4) {
struct cmsghdr *cmsg;
struct in_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg);
memset(cmsg, 0, CMSG_SPACE(sizeof(struct in_pktinfo)));
cmsglen += CMSG_SPACE(sizeof(struct in_pktinfo));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
ipi = (struct in_pktinfo *) CMSG_DATA(cmsg);
ipi->ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr.addr.in4);
}
#endif
#if 0
LOG(LOGS_INFO, LOGF_NtpIO, "sending to %s:%d from %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, UTI_IPToString(&remote_addr->local_ip_addr));
#endif
msg.msg_controllen = cmsglen;
/* This is apparently required on some systems */
if (!cmsglen)
msg.msg_control = NULL;
if (sendmsg(sock_fd, &msg, 0) < 0) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
return;
}
/* ================================================== */ /* ================================================== */
/* Send an unauthenticated packet to a given address */ /* Send an unauthenticated packet to a given address */
void void
NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr) NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{ {
struct sockaddr_in remote; send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE, remote_addr);
assert(initialised);
remote.sin_family = AF_INET;
remote.sin_port = htons(remote_addr->port);
remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
if (sendto(sock_fd, (void *) packet, NTP_NORMAL_PACKET_SIZE, 0,
(struct sockaddr *) &remote, sizeof(remote)) < 0) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
return;
} }
/* ================================================== */ /* ================================================== */
@@ -257,21 +483,7 @@ NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
void void
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr) NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{ {
struct sockaddr_in remote; send_packet((void *) packet, sizeof(NTP_Packet), remote_addr);
assert(initialised);
remote.sin_family = AF_INET;
remote.sin_port = htons(remote_addr->port);
remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
if (sendto(sock_fd, (void *) packet, sizeof(NTP_Packet), 0,
(struct sockaddr *) &remote, sizeof(remote)) < 0) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
return;
} }
/* ================================================== */ /* ================================================== */
@@ -283,15 +495,10 @@ void
NIO_SendEcho(NTP_Remote_Address *remote_addr) NIO_SendEcho(NTP_Remote_Address *remote_addr)
{ {
unsigned long magic_message = 0xbe7ab1e7UL; unsigned long magic_message = 0xbe7ab1e7UL;
struct sockaddr_in addr; NTP_Remote_Address addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = htonl(remote_addr->ip_addr);
/* Just ignore error status on send - this is not a big deal anyway */
sendto(sock_fd, (void *) &magic_message, sizeof(unsigned long), 0,
(struct sockaddr *) &addr, sizeof(addr));
addr = *remote_addr;
addr.port = ECHO_PORT;
send_packet((void *) &magic_message, sizeof(unsigned long), &addr);
} }

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -43,8 +43,8 @@
/* Record type private to this file, used to store information about /* Record type private to this file, used to store information about
particular sources */ particular sources */
typedef struct { typedef struct {
NTP_Remote_Address remote_addr; /* The address of this source */ NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
int in_use; /* Whether this slot in the table is in use */ means this slot in table is in use */
NCR_Instance data; /* Data for the protocol engine for this source */ NCR_Instance data; /* Data for the protocol engine for this source */
} SourceRecord; } SourceRecord;
@@ -83,7 +83,7 @@ NSR_Initialise(void)
{ {
int i; int i;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
records[i].in_use = 0; records[i].remote_addr = NULL;
} }
n_sources = 0; n_sources = 0;
initialised = 1; initialised = 1;
@@ -120,23 +120,42 @@ static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found) find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{ {
unsigned long hash; unsigned long hash;
unsigned long ip = remote_addr->ip_addr; unsigned long ip;
unsigned short port = remote_addr->port; unsigned short port;
uint8_t *ip6;
assert(N_RECORDS == 256); assert(N_RECORDS == 256);
switch (remote_addr->ip_addr.family) {
case IPADDR_INET6:
ip6 = remote_addr->ip_addr.addr.in6;
ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
(ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
(ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
(ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
break;
case IPADDR_INET4:
ip = remote_addr->ip_addr.addr.in4;
break;
default:
*found = *slot = 0;
return;
}
port = remote_addr->port;
/* Compute hash value just by xor'ing the 4 bytes of the address together */ /* Compute hash value just by xor'ing the 4 bytes of the address together */
hash = ip ^ (ip >> 16); hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff; hash = (hash ^ (hash >> 8)) & 0xff;
while ((records[hash].in_use) && while (records[hash].remote_addr &&
(records[hash].remote_addr.ip_addr != ip)) { UTI_CompareIPs(&records[hash].remote_addr->ip_addr,
&remote_addr->ip_addr, NULL)) {
hash++; hash++;
if (hash == 256) hash = 0; if (hash == 256) hash = 0;
} }
if (records[hash].in_use) { if (records[hash].remote_addr) {
if (records[hash].remote_addr.port == port) { if (records[hash].remote_addr->port == port) {
*found = 2; *found = 2;
} else { } else {
*found = 1; *found = 1;
@@ -162,7 +181,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised); assert(initialised);
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long)remote_addr->ip_addr, remote_addr->port); LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif #endif
/* Find empty bin & check that we don't have the address already */ /* Find empty bin & check that we don't have the address already */
@@ -172,11 +191,13 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
} else { } else {
if (n_sources == MAX_SOURCES) { if (n_sources == MAX_SOURCES) {
return NSR_TooManySources; return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else { } else {
n_sources++; n_sources++;
records[slot].remote_addr = *remote_addr;
records[slot].in_use = 1;
records[slot].data = NCR_GetServerInstance(remote_addr, params); /* Will need params passing through */ records[slot].data = NCR_GetServerInstance(remote_addr, params); /* Will need params passing through */
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success; return NSR_Success;
} }
} }
@@ -193,7 +214,7 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised); assert(initialised);
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long) remote_addr->ip_addr, remote_addr->port); LOG(LOGS_INFO, LOGF_NtpSources, "IP=%s port=%d", UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
#endif #endif
/* Find empty bin & check that we don't have the address already */ /* Find empty bin & check that we don't have the address already */
@@ -203,11 +224,13 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
} else { } else {
if (n_sources == MAX_SOURCES) { if (n_sources == MAX_SOURCES) {
return NSR_TooManySources; return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else { } else {
n_sources++; n_sources++;
records[slot].remote_addr = *remote_addr;
records[slot].in_use = 1;
records[slot].data = NCR_GetPeerInstance(remote_addr, params); /* Will need params passing through */ records[slot].data = NCR_GetPeerInstance(remote_addr, params); /* Will need params passing through */
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success; return NSR_Success;
} }
} }
@@ -231,7 +254,7 @@ NSR_RemoveSource(NTP_Remote_Address *remote_addr)
return NSR_NoSuchSource; return NSR_NoSuchSource;
} else { } else {
n_sources--; n_sources--;
records[slot].in_use = 0; records[slot].remote_addr = NULL;
NCR_DestroyInstance(records[slot].data); NCR_DestroyInstance(records[slot].data);
return NSR_Success; return NSR_Success;
} }
@@ -249,7 +272,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
#if 0 #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s", LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), UTI_IPToString(&remote_addr->ip_addr),
remote_addr->port, UTI_TimevalToString(now)); remote_addr->port, UTI_TimevalToString(now));
#endif #endif
@@ -293,10 +316,10 @@ slew_sources(struct timeval *raw,
int i; int i;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].remote_addr) {
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f", LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f",
UTI_IPToDottedQuad(records[i].remote_addr.ip_addr), dfreq, doffset); UTI_IPToString(&records[i].remote_addr->ip_addr), dfreq, doffset);
#endif #endif
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset); NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
@@ -308,17 +331,16 @@ slew_sources(struct timeval *raw,
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOnline(unsigned long mask, unsigned long address) NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].remote_addr) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1; any = 1;
NCR_TakeSourceOnline(records[i].data); NCR_TakeSourceOnline(records[i].data);
} }
@@ -331,17 +353,16 @@ NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOffline(unsigned long mask, unsigned long address) NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].remote_addr) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1; any = 1;
NCR_TakeSourceOffline(records[i].data); NCR_TakeSourceOffline(records[i].data);
} }
@@ -354,11 +375,11 @@ NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMinpoll(unsigned long address, int new_minpoll) NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -373,11 +394,11 @@ NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll) NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -392,11 +413,11 @@ NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelay(unsigned long address, double new_max_delay) NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -411,11 +432,11 @@ NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio) NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = address; addr.ip_addr = *address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -431,17 +452,16 @@ NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
int int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
unsigned long mask, unsigned long address) IPAddr *mask, IPAddr *address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].remote_addr) {
ip = records[i].remote_addr.ip_addr; if (address->family == IPADDR_UNSPEC ||
if ((ip & mask) == address) { !UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1; any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples); NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
} }
@@ -486,7 +506,7 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
report->burst_offline = 0; report->burst_offline = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) { if (records[i].remote_addr) {
NCR_IncrementActivityCounters(records[i].data, &report->online, &report->offline, NCR_IncrementActivityCounters(records[i].data, &report->online, &report->offline,
&report->burst_online, &report->burst_offline); &report->burst_online, &report->burst_offline);
} }

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -46,7 +46,8 @@ typedef enum {
NSR_Success, /* Operation successful */ NSR_Success, /* Operation successful */
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */ NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */ NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
NSR_TooManySources /* AddServer, AddPeer - too many sources already present */ NSR_TooManySources, /* AddServer, AddPeer - too many sources already present */
NSR_InvalidAF /* AddServer, AddPeer - attempt to add a source with invalid address family */
} NSR_Status; } NSR_Status;
/* Procedure to add a new server source (to which this machine will be /* Procedure to add a new server source (to which this machine will be
@@ -75,22 +76,22 @@ extern void NSR_Finalise(void);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set online again. Returns a match a particular subnet should be set online again. Returns a
flag indicating whether any hosts matched the address */ flag indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOnline(unsigned long mask, unsigned long address); extern int NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set offline. Returns a flag match a particular subnet should be set offline. Returns a flag
indicating whether any hosts matched the address */ indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOffline(unsigned long mask, unsigned long address); extern int NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address);
extern int NSR_ModifyMinpoll(unsigned long address, int new_minpoll); extern int NSR_ModifyMinpoll(IPAddr *address, int new_minpoll);
extern int NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll); extern int NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll);
extern int NSR_ModifyMaxdelay(unsigned long address, double new_max_delay); extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay);
extern int NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio); extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio);
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, unsigned long mask, unsigned long address); extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now); extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

627
refclock.c Normal file
View File

@@ -0,0 +1,627 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
*
* 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.
*
**********************************************************************
=======================================================================
Routines implementing reference clocks.
*/
#include "refclock.h"
#include "reference.h"
#include "conf.h"
#include "local.h"
#include "memory.h"
#include "util.h"
#include "sources.h"
#include "logging.h"
#include "sched.h"
#include "mkdirpp.h"
/* list of refclock drivers */
extern RefclockDriver RCL_SHM_driver;
extern RefclockDriver RCL_SOCK_driver;
extern RefclockDriver RCL_PPS_driver;
struct FilterSample {
double offset;
struct timeval sample_time;
};
struct MedianFilter {
int length;
int index;
int used;
struct FilterSample *samples;
};
struct RCL_Instance_Record {
RefclockDriver *driver;
void *data;
char *driver_parameter;
int driver_poll;
int driver_polled;
int poll;
int missed_samples;
int leap_status;
int pps_rate;
struct MedianFilter filter;
unsigned long ref_id;
double offset;
double delay;
SCH_TimeoutID timeout_id;
SRC_Instance source;
};
#define MAX_RCL_SOURCES 8
static struct RCL_Instance_Record refclocks[MAX_RCL_SOURCES];
static int n_sources = 0;
#define REFCLOCKS_LOG "refclocks.log"
static FILE *logfile = NULL;
static char *logfilename = NULL;
static unsigned long logwrites = 0;
static int valid_sample_time(RCL_Instance instance, struct timeval *tv);
static int pps_stratum(RCL_Instance instance, struct timeval *tv);
static void poll_timeout(void *arg);
static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
double doffset, int is_step_change, void *anything);
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int pulse, double raw_offset, double cooked_offset);
static void filter_init(struct MedianFilter *filter, int length);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset);
static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
void
RCL_Initialise(void)
{
CNF_AddRefclocks();
if (CNF_GetLogRefclocks()) {
char *logdir = CNF_GetLogDir();
if (!mkdir_and_parents(logdir)) {
LOG(LOGS_ERR, LOGF_Refclock, "Could not create directory %s", logdir);
} else {
logfilename = MallocArray(char, 2 + strlen(logdir) + strlen(REFCLOCKS_LOG));
strcpy(logfilename, logdir);
strcat(logfilename, "/");
strcat(logfilename, REFCLOCKS_LOG);
}
}
}
void
RCL_Finalise(void)
{
int i;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = (RCL_Instance)&refclocks[i];
if (inst->driver->fini)
inst->driver->fini(inst);
filter_fini(&inst->filter);
Free(inst->driver_parameter);
}
if (n_sources > 0)
LCL_RemoveParameterChangeHandler(slew_samples, NULL);
if (logfile)
fclose(logfile);
Free(logfilename);
}
int
RCL_AddRefclock(RefclockParameters *params)
{
int pps_source = 0;
RCL_Instance inst = &refclocks[n_sources];
if (n_sources == MAX_RCL_SOURCES)
return 0;
if (strncmp(params->driver_name, "SHM", 4) == 0) {
inst->driver = &RCL_SHM_driver;
} else if (strncmp(params->driver_name, "SOCK", 4) == 0) {
inst->driver = &RCL_SOCK_driver;
pps_source = 1;
} else if (strncmp(params->driver_name, "PPS", 4) == 0) {
inst->driver = &RCL_PPS_driver;
pps_source = 1;
} else {
LOG_FATAL(LOGF_Refclock, "unknown refclock driver %s", params->driver_name);
return 0;
}
if (!inst->driver->init && !inst->driver->poll) {
LOG_FATAL(LOGF_Refclock, "refclock driver %s is not compiled in", params->driver_name);
return 0;
}
inst->data = NULL;
inst->driver_parameter = params->driver_parameter;
inst->driver_poll = params->driver_poll;
inst->poll = params->poll;
inst->missed_samples = 0;
inst->driver_polled = 0;
inst->leap_status = 0;
inst->pps_rate = params->pps_rate;
inst->offset = params->offset;
inst->delay = params->delay;
inst->timeout_id = -1;
inst->source = NULL;
if (pps_source) {
if (inst->pps_rate < 1)
inst->pps_rate = 1;
} else {
inst->pps_rate = 0;
}
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
if (params->ref_id)
inst->ref_id = params->ref_id;
else {
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
snprintf((char *)ref, 5, "%3s%d", params->driver_name, n_sources % 10);
inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
}
if (inst->driver->init)
if (!inst->driver->init(inst)) {
LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
return 0;
}
filter_init(&inst->filter, params->filter_length);
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock added poll=%d dpoll=%d filter=%d",
inst->poll, inst->driver_poll, params->filter_length);
#endif
n_sources++;
return 1;
}
void
RCL_StartRefclocks(void)
{
int i;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
}
if (n_sources > 0)
LCL_AddParameterChangeHandler(slew_samples, NULL);
}
void
RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
{
int i;
unsigned long ref_id;
assert(report->ip_addr.family == IPADDR_INET4);
ref_id = report->ip_addr.addr.in4;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
if (inst->ref_id == ref_id) {
report->poll = inst->poll;
report->mode = RPT_LOCAL_REFERENCE;
break;
}
}
}
void
RCL_SetDriverData(RCL_Instance instance, void *data)
{
instance->data = data;
}
void *
RCL_GetDriverData(RCL_Instance instance)
{
return instance->data;
}
char *
RCL_GetDriverParameter(RCL_Instance instance)
{
return instance->driver_parameter;
}
int
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
{
double correction;
struct timeval cooked_time;
correction = LCL_GetOffsetCorrection(sample_time);
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
if (!valid_sample_time(instance, sample_time))
return 0;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock sample offset=%.9f cooked=%.9f",
offset, offset - correction + instance->offset);
#endif
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset);
instance->leap_status = leap_status;
log_sample(instance, &cooked_time, 0, offset, offset - correction + instance->offset);
return 1;
}
int
RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
{
double correction, offset;
struct timeval cooked_time;
int rate;
struct timeval ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
NTP_Leap leap;
unsigned long ref_id;
correction = LCL_GetOffsetCorrection(pulse_time);
UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
if (!valid_sample_time(instance, pulse_time))
return 0;
rate = instance->pps_rate;
assert(rate > 0);
/* Ignore the pulse if we are not well synchronized */
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
distance = fabs(root_delay) / 2 + root_dispersion;
if (!is_synchronised || distance >= 0.5 / rate) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse dropped second=%.9f sync=%d dist=%.9f",
second, is_synchronised, distance);
#endif
/* Drop also all stored samples */
filter_reset(&instance->filter);
return 0;
}
offset = -second - correction + instance->offset;
/* Adjust the offset to [-0.5/rate, 0.5/rate) interval */
offset -= (long)(offset * rate) / (double)rate;
if (offset < -0.5 / rate)
offset += 1.0 / rate;
else if (offset >= 0.5 / rate)
offset -= 1.0 / rate;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f",
second, offset + instance->offset);
#endif
filter_add_sample(&instance->filter, &cooked_time, offset);
instance->leap_status = LEAP_Normal;
log_sample(instance, &cooked_time, 1, second, offset);
return 1;
}
void
RCL_CycleLogFile(void)
{
if (logfile) {
fclose(logfile);
logfile = NULL;
logwrites = 0;
}
}
static int
valid_sample_time(RCL_Instance instance, struct timeval *tv)
{
struct timeval raw_time;
double diff;
LCL_ReadRawTime(&raw_time);
UTI_DiffTimevalsToDouble(&diff, &raw_time, tv);
if (diff < 0.0 || diff > 1 << (instance->poll + 1))
return 0;
return 1;
}
static int
pps_stratum(RCL_Instance instance, struct timeval *tv)
{
struct timeval ref_time;
int is_synchronised, stratum, i;
double root_delay, root_dispersion;
NTP_Leap leap;
unsigned long ref_id;
REF_GetReferenceParams(tv, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
/* Don't change our stratum if local stratum is active
or this is the current source */
if (ref_id == instance->ref_id || REF_IsLocalActive())
return stratum - 1;
/* Or the current source is another PPS refclock */
for (i = 0; i < n_sources; i++) {
if (refclocks[i].ref_id == ref_id && refclocks[i].pps_rate)
return stratum - 1;
}
return 0;
}
static void
poll_timeout(void *arg)
{
double next;
int poll;
RCL_Instance inst = (RCL_Instance)arg;
poll = inst->poll;
if (inst->driver->poll) {
poll = inst->driver_poll;
inst->driver->poll(inst);
inst->driver_polled++;
}
if (!(inst->driver->poll && inst->driver_polled < (1 << (inst->poll - inst->driver_poll)))) {
double offset, dispersion;
struct timeval sample_time;
int sample_ok, stratum;
sample_ok = filter_get_sample(&inst->filter, &sample_time, &offset, &dispersion);
filter_reset(&inst->filter);
inst->driver_polled = 0;
if (sample_ok) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock filtered sample: offset=%.9f dispersion=%.9f [%s]",
offset, dispersion, UTI_TimevalToString(&sample_time));
#endif
if (inst->pps_rate)
/* Handle special case when PPS is used with local stratum */
stratum = pps_stratum(inst, &sample_time);
else
stratum = 0;
SRC_SetReachable(inst->source);
SRC_AccumulateSample(inst->source, &sample_time, offset,
inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
inst->missed_samples = 0;
} else {
inst->missed_samples++;
if (inst->missed_samples > 9)
SRC_UnsetReachable(inst->source);
}
}
if (poll >= 0)
next = 1 << poll;
else
next = 1.0 / (1 << -poll);
inst->timeout_id = SCH_AddTimeoutByDelay(next, poll_timeout, arg);
}
static void
slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
double doffset, int is_step_change, void *anything)
{
int i;
for (i = 0; i < n_sources; i++)
filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset);
}
static void
log_sample(RCL_Instance instance, struct timeval *sample_time, int pulse, double raw_offset, double cooked_offset)
{
char sync_stats[4] = {'N', '+', '-', '?'};
if (!logfilename)
return;
if (!logfile) {
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_Refclock, "Couldn't open logfile %s for update", logfilename);
Free(logfilename);
logfilename = NULL;
return;
}
}
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"====================================================================\n"
" Date (UTC) Time Refid DP L P Raw offset Cooked offset\n"
"====================================================================\n");
}
fprintf(logfile, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e\n",
UTI_TimeToLogForm(sample_time->tv_sec),
(int)sample_time->tv_usec,
UTI_RefidToString(instance->ref_id),
instance->driver_polled,
sync_stats[instance->leap_status],
pulse,
raw_offset,
cooked_offset);
fflush(logfile);
}
static void
filter_init(struct MedianFilter *filter, int length)
{
if (length < 1)
length = 1;
filter->length = length;
filter->index = -1;
filter->used = 0;
filter->samples = MallocArray(struct FilterSample, filter->length);
}
static void
filter_fini(struct MedianFilter *filter)
{
Free(filter->samples);
}
static void
filter_reset(struct MedianFilter *filter)
{
filter->index = -1;
filter->used = 0;
}
static void
filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset)
{
filter->index++;
filter->index %= filter->length;
if (filter->used < filter->length)
filter->used++;
filter->samples[filter->index].sample_time = *sample_time;
filter->samples[filter->index].offset = offset;
}
static int
sample_compare(const void *a, const void *b)
{
const struct FilterSample *s1 = a, *s2 = b;
if (s1->offset < s2->offset)
return -1;
else if (s1->offset > s2->offset)
return 1;
return 0;
}
static int
filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
{
if (filter->used == 0)
return 0;
if (filter->used == 1) {
*sample_time = filter->samples[filter->index].sample_time;
*offset = filter->samples[filter->index].offset;
*dispersion = 0.0;
} else {
int i, from, to;
double x, x1, y, d;
/* sort samples by offset */
qsort(filter->samples, filter->used, sizeof (struct FilterSample), sample_compare);
/* average the half of the samples closest to the median */
if (filter->used > 2) {
from = (filter->used + 2) / 4;
to = filter->used - from;
} else {
from = 0;
to = filter->used;
}
for (i = from, x = y = 0.0; i < to; i++) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock averaging offset %.9f [%s]",
filter->samples[i].offset, UTI_TimevalToString(&filter->samples[i].sample_time));
#endif
UTI_DiffTimevalsToDouble(&x1, &filter->samples[i].sample_time, &filter->samples[0].sample_time);
x += x1;
y += filter->samples[i].offset;
}
x /= to - from;
y /= to - from;
for (i = from, d = 0.0; i < to; i++)
d += (filter->samples[i].offset - y) * (filter->samples[i].offset - y);
d = sqrt(d / (to - from));
UTI_AddDoubleToTimeval(&filter->samples[0].sample_time, x, sample_time);
*offset = y;
*dispersion = d;
}
return 1;
}
static void
filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset)
{
int i;
double elapsed, delta_time, prev_offset;
struct timeval *sample;
for (i = 0; i < filter->used; i++) {
sample = &filter->samples[i].sample_time;
UTI_DiffTimevalsToDouble(&elapsed, when, sample);
delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(sample, delta_time, sample);
prev_offset = filter->samples[i].offset;
filter->samples[i].offset -= delta_time;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "i=%d old_off=%.9f new_off=%.9f",
i, prev_offset, filter->samples[i].offset);
#endif
}
}

69
refclock.h Normal file
View File

@@ -0,0 +1,69 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
*
* 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 refclocks.
*/
#ifndef GOT_REFCLOCK_H
#define GOT_REFCLOCK_H
#include "srcparams.h"
#include "sources.h"
typedef struct {
char driver_name[4];
char *driver_parameter;
int driver_poll;
int poll;
int filter_length;
int pps_rate;
unsigned long ref_id;
double offset;
double delay;
} RefclockParameters;
typedef struct RCL_Instance_Record *RCL_Instance;
typedef struct {
int (*init)(RCL_Instance instance);
void (*fini)(RCL_Instance instance);
int (*poll)(RCL_Instance instance);
} RefclockDriver;
extern void RCL_Initialise(void);
extern void RCL_Finalise(void);
extern int RCL_AddRefclock(RefclockParameters *params);
extern void RCL_StartRefclocks(void);
extern void RCL_StartRefclocks(void);
extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
extern void RCL_CycleLogFile(void);
/* functions used by drivers */
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
extern void *RCL_GetDriverData(RCL_Instance instance);
extern char *RCL_GetDriverParameter(RCL_Instance instance);
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
#endif

168
refclock_pps.c Normal file
View File

@@ -0,0 +1,168 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
*
* 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.
*
**********************************************************************
=======================================================================
PPSAPI refclock driver.
*/
#include "refclock.h"
#if HAVE_PPSAPI
#include <timepps.h>
#include "logging.h"
#include "memory.h"
#include "util.h"
struct pps_instance {
pps_handle_t handle;
pps_seq_t last_seq;
int edge_clear;
};
static int pps_initialise(RCL_Instance instance) {
pps_handle_t handle;
pps_params_t params;
struct pps_instance *pps;
int fd, edge_clear, mode;
char *path, *s;
path = RCL_GetDriverParameter(instance);
edge_clear = 0;
if ((s = strrchr(path, ':')) != NULL) {
*s = '\0';
edge_clear = atoi(s + 1);
}
fd = open(path, O_RDWR);
if (fd < 0) {
LOG_FATAL(LOGF_Refclock, "open() failed on %s", path);
return 0;
}
if (time_pps_create(fd, &handle) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_create() failed on %s", path);
return 0;
}
if (time_pps_getcap(handle, &mode) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_getcap() failed on %s", path);
return 0;
}
if (time_pps_getparams(handle, &params) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_getparams() failed on %s", path);
return 0;
}
if (!edge_clear) {
if (!(mode & PPS_CAPTUREASSERT)) {
LOG_FATAL(LOGF_Refclock, "CAPTUREASSERT not supported on %s", path);
return 0;
}
params.mode |= PPS_CAPTUREASSERT;
params.mode &= ~PPS_CAPTURECLEAR;
} else {
if (!(mode & PPS_CAPTURECLEAR)) {
LOG_FATAL(LOGF_Refclock, "CAPTURECLEAR not supported on %s", path);
return 0;
}
params.mode |= PPS_CAPTURECLEAR;
params.mode &= ~PPS_CAPTUREASSERT;
}
if (time_pps_setparams(handle, &params) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_setparams() failed on %s", path);
return 0;
}
pps = MallocNew(struct pps_instance);
pps->handle = handle;
pps->last_seq = 0;
pps->edge_clear = edge_clear;
RCL_SetDriverData(instance, pps);
return 1;
}
static void pps_finalise(RCL_Instance instance)
{
struct pps_instance *pps;
pps = (struct pps_instance *)RCL_GetDriverData(instance);
time_pps_destroy(pps->handle);
Free(pps);
}
static int pps_poll(RCL_Instance instance)
{
struct pps_instance *pps;
struct timespec ts;
struct timeval tv;
pps_info_t pps_info;
pps_seq_t seq;
pps = (struct pps_instance *)RCL_GetDriverData(instance);
ts.tv_sec = 0;
ts.tv_nsec = 0;
if (time_pps_fetch(pps->handle, PPS_TSFMT_TSPEC, &pps_info, &ts) < 0) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "time_pps_fetch error");
#endif
return 0;
}
if (!pps->edge_clear) {
seq = pps_info.assert_sequence;
ts = pps_info.assert_timestamp;
} else {
seq = pps_info.clear_sequence;
ts = pps_info.clear_timestamp;
}
if (seq == pps->last_seq || (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
return 0;
}
pps->last_seq = seq;
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
return RCL_AddPulse(instance, &tv, ts.tv_nsec / 1e9);
}
RefclockDriver RCL_PPS_driver = {
pps_initialise,
pps_finalise,
pps_poll
};
#else
RefclockDriver RCL_PPS_driver = { NULL, NULL, NULL };
#endif

118
refclock_shm.c Normal file
View File

@@ -0,0 +1,118 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
*
* 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.
*
**********************************************************************
=======================================================================
SHM refclock driver.
*/
#include "refclock.h"
#include "logging.h"
#include "util.h"
#include <sys/types.h>
#include <sys/shm.h>
#define SHMKEY 0x4e545030
struct shmTime {
int mode; /* 0 - if valid set
* use values,
* clear valid
* 1 - if valid set
* if count before and after read of values is equal,
* use values
* clear valid
*/
int count;
time_t clockTimeStampSec;
int clockTimeStampUSec;
time_t receiveTimeStampSec;
int receiveTimeStampUSec;
int leap;
int precision;
int nsamples;
int valid;
int dummy[10];
};
static int shm_initialise(RCL_Instance instance) {
int id, param;
struct shmTime *shm;
param = atoi(RCL_GetDriverParameter(instance));
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | 0700);
if (id == -1) {
LOG_FATAL(LOGF_Refclock, "shmget() failed");
return 0;
}
shm = (struct shmTime *)shmat(id, 0, 0);
if ((long)shm == -1) {
LOG_FATAL(LOGF_Refclock, "shmat() failed");
return 0;
}
RCL_SetDriverData(instance, shm);
return 1;
}
static void shm_finalise(RCL_Instance instance)
{
shmdt(RCL_GetDriverData(instance));
}
static int shm_poll(RCL_Instance instance)
{
struct timeval tv1, tv2;
struct shmTime t, *shm;
double offset;
shm = (struct shmTime *)RCL_GetDriverData(instance);
t = *shm;
if ((t.mode == 1 && t.count != shm->count) ||
!(t.mode == 0 || t.mode == 1) || !t.valid) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "sample ignored mode: %d count: %d valid: %d", t.mode, t.count, t.valid);
#endif
return 0;
}
shm->valid = 0;
tv1.tv_sec = t.receiveTimeStampSec;
tv1.tv_usec = t.receiveTimeStampUSec;
tv2.tv_sec = t.clockTimeStampSec;
tv2.tv_usec = t.clockTimeStampUSec;
UTI_DiffTimevalsToDouble(&offset, &tv2, &tv1);
return RCL_AddSample(instance, &tv1, offset, t.leap);
}
RefclockDriver RCL_SHM_driver = {
shm_initialise,
shm_finalise,
shm_poll
};

132
refclock_sock.c Normal file
View File

@@ -0,0 +1,132 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009
*
* 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.
*
**********************************************************************
=======================================================================
Unix domain socket refclock driver.
*/
#include "refclock.h"
#include "logging.h"
#include "util.h"
#include "sched.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCK_MAGIC 0x534f434b
struct sock_sample {
struct timeval tv;
double offset;
int pulse;
int leap;
int _pad;
int magic;
};
static void read_sample(void *anything)
{
struct sock_sample sample;
RCL_Instance instance;
int sockfd, s;
instance = (RCL_Instance)anything;
sockfd = (long)RCL_GetDriverData(instance);
s = recv(sockfd, &sample, sizeof (sample), 0);
if (s < 0) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "Error reading from SOCK socket : %s", strerror(errno));
#endif
return;
}
if (s != sizeof (sample)) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "Unexpected length of SOCK sample : %d != %d", s, sizeof (sample));
#endif
return;
}
if (sample.magic != SOCK_MAGIC) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "Unexpected magic number in SOCK sample : %x != %x", sample.magic, SOCK_MAGIC);
#endif
return;
}
if (sample.pulse) {
RCL_AddPulse(instance, &sample.tv, sample.offset);
} else {
RCL_AddSample(instance, &sample.tv, sample.offset, sample.leap);
}
}
static int sock_initialise(RCL_Instance instance)
{
struct sockaddr_un s;
int sockfd;
char *path;
path = RCL_GetDriverParameter(instance);
s.sun_family = AF_UNIX;
if (snprintf(s.sun_path, sizeof (s.sun_path), "%s", path) >= sizeof (s.sun_path)) {
LOG_FATAL(LOGF_Refclock, "path %s is too long", path);
return 0;
}
sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sockfd < 0) {
LOG_FATAL(LOGF_Refclock, "socket() failed");
return 0;
}
unlink(path);
if (bind(sockfd, (struct sockaddr *)&s, sizeof (s)) < 0) {
LOG_FATAL(LOGF_Refclock, "bind() failed");
return 0;
}
RCL_SetDriverData(instance, (void *)(long)sockfd);
SCH_AddInputFileHandler(sockfd, read_sample, instance);
return 1;
}
static void sock_finalise(RCL_Instance instance)
{
int sockfd;
sockfd = (long)RCL_GetDriverData(instance);
SCH_RemoveInputFileHandler(sockfd);
close(sockfd);
}
RefclockDriver RCL_SOCK_driver = {
sock_initialise,
sock_finalise,
NULL
};

View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -44,8 +45,10 @@ static int are_we_synchronised;
static int enable_local_stratum; static int enable_local_stratum;
static int local_stratum; static int local_stratum;
static NTP_Leap our_leap_status; static NTP_Leap our_leap_status;
static int our_leap_sec;
static int our_stratum; static int our_stratum;
static unsigned long our_ref_id; static unsigned long our_ref_id;
static IPAddr our_ref_ip;
struct timeval our_ref_time; /* Stored relative to reference, NOT local time */ struct timeval our_ref_time; /* Stored relative to reference, NOT local time */
static double our_offset; static double our_offset;
static double our_skew; static double our_skew;
@@ -102,7 +105,8 @@ REF_Initialise(void)
double our_frequency_ppm; double our_frequency_ppm;
are_we_synchronised = 0; are_we_synchronised = 0;
our_leap_status = LEAP_Normal; our_leap_status = LEAP_Unsynchronised;
our_leap_sec = 0;
initialised = 1; initialised = 1;
our_root_dispersion = 1.0; our_root_dispersion = 1.0;
our_root_delay = 1.0; our_root_delay = 1.0;
@@ -176,6 +180,10 @@ REF_Initialise(void)
void void
REF_Finalise(void) REF_Finalise(void)
{ {
if (our_leap_sec) {
LCL_SetLeap(0);
}
if (logfile) { if (logfile) {
fclose(logfile); fclose(logfile);
} }
@@ -311,11 +319,50 @@ maybe_log_offset(double offset)
/* ================================================== */ /* ================================================== */
static void
update_leap_status(NTP_Leap leap)
{
time_t now;
struct tm stm;
int leap_sec;
leap_sec = 0;
if (leap == LEAP_InsertSecond || leap == LEAP_DeleteSecond) {
/* Insert/delete leap second only on June 30 or December 31
and in other months ignore the leap status completely */
now = time(NULL);
stm = *gmtime(&now);
if (stm.tm_mon != 5 && stm.tm_mon != 11) {
leap = LEAP_Normal;
} else if ((stm.tm_mon == 5 && stm.tm_mday == 30) ||
(stm.tm_mon == 11 && stm.tm_mday == 31)) {
if (leap == LEAP_InsertSecond) {
leap_sec = 1;
} else {
leap_sec = -1;
}
}
}
if (leap_sec != our_leap_sec) {
LCL_SetLeap(leap_sec);
our_leap_sec = leap_sec;
}
our_leap_status = leap;
}
/* ================================================== */
void void
REF_SetReference(int stratum, REF_SetReference(int stratum,
NTP_Leap leap, NTP_Leap leap,
unsigned long ref_id, unsigned long ref_id,
IPAddr *ref_ip,
struct timeval *ref_time, struct timeval *ref_time,
double offset, double offset,
double frequency, double frequency,
@@ -335,6 +382,12 @@ REF_SetReference(int stratum,
assert(initialised); assert(initialised);
/* Avoid getting NaNs */
if (skew == 0.0)
skew = 1e-10;
if (our_skew == 0.0)
our_skew = 1e-10;
/* If we get a serious rounding error in the source stats regression /* If we get a serious rounding error in the source stats regression
processing, there is a remote chance that the skew argument is a processing, there is a remote chance that the skew argument is a
'not a number'. If such a quantity gets propagated into the 'not a number'. If such a quantity gets propagated into the
@@ -356,13 +409,18 @@ REF_SetReference(int stratum,
are_we_synchronised = 1; are_we_synchronised = 1;
our_stratum = stratum + 1; our_stratum = stratum + 1;
our_leap_status = leap;
our_ref_id = ref_id; our_ref_id = ref_id;
if (ref_ip)
our_ref_ip = *ref_ip;
else
our_ref_ip.family = IPADDR_UNSPEC;
our_ref_time = *ref_time; our_ref_time = *ref_time;
our_offset = offset; our_offset = offset;
our_root_delay = root_delay; our_root_delay = root_delay;
our_root_dispersion = root_dispersion; our_root_dispersion = root_dispersion;
update_leap_status(leap);
/* Eliminate updates that are based on totally unreliable frequency /* Eliminate updates that are based on totally unreliable frequency
information */ information */
@@ -423,7 +481,7 @@ REF_SetReference(int stratum,
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n", fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(ref_time->tv_sec), UTI_TimeToLogForm(ref_time->tv_sec),
UTI_IPToDottedQuad(our_ref_id), our_ref_ip.family != IPADDR_UNSPEC ? UTI_IPToString(&our_ref_ip) : UTI_RefidToString(our_ref_id),
our_stratum, our_stratum,
abs_freq_ppm, abs_freq_ppm,
1.0e6*our_skew, 1.0e6*our_skew,
@@ -517,6 +575,8 @@ REF_SetUnsynchronised(void)
} }
are_we_synchronised = 0; are_we_synchronised = 0;
update_leap_status(LEAP_Unsynchronised);
} }
/* ================================================== */ /* ================================================== */
@@ -636,6 +696,14 @@ REF_DisableLocal(void)
/* ================================================== */ /* ================================================== */
int
REF_IsLocalActive(void)
{
return !are_we_synchronised && enable_local_stratum;
}
/* ================================================== */
void void
REF_GetTrackingReport(RPT_TrackingReport *rep) REF_GetTrackingReport(RPT_TrackingReport *rep)
{ {
@@ -654,9 +722,10 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed; extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed;
rep->ref_id = our_ref_id; rep->ref_id = our_ref_id;
rep->ip_addr = our_ref_ip;
rep->stratum = our_stratum; rep->stratum = our_stratum;
rep->ref_time = our_ref_time; rep->ref_time = our_ref_time;
UTI_DoubleToTimeval(correction, &rep->current_correction); rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency(); rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 1.0e6 * our_residual_freq; rep->resid_freq_ppm = 1.0e6 * our_residual_freq;
rep->skew_ppm = 1.0e6 * our_skew; rep->skew_ppm = 1.0e6 * our_skew;
@@ -666,9 +735,10 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
} else if (enable_local_stratum) { } else if (enable_local_stratum) {
rep->ref_id = LOCAL_REFERENCE_ID; rep->ref_id = LOCAL_REFERENCE_ID;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = local_stratum; rep->stratum = local_stratum;
rep->ref_time = now_cooked; rep->ref_time = now_cooked;
UTI_DoubleToTimeval(correction, &rep->current_correction); rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency(); rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0; rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0; rep->skew_ppm = 0.0;
@@ -678,10 +748,11 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
} else { } else {
rep->ref_id = 0UL; rep->ref_id = 0UL;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = 0; rep->stratum = 0;
rep->ref_time.tv_sec = 0; rep->ref_time.tv_sec = 0;
rep->ref_time.tv_usec = 0; rep->ref_time.tv_usec = 0;
UTI_DoubleToTimeval(correction, &rep->current_correction); rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency(); rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0; rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0; rep->skew_ppm = 0.0;

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -110,6 +110,7 @@ extern void REF_SetReference
int stratum, int stratum,
NTP_Leap leap, NTP_Leap leap,
unsigned long ref_id, unsigned long ref_id,
IPAddr *ref_ip,
struct timeval *ref_time, struct timeval *ref_time,
double offset, double offset,
double frequency, double frequency,
@@ -139,6 +140,7 @@ extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
extern void REF_EnableLocal(int stratum); extern void REF_EnableLocal(int stratum);
extern void REF_DisableLocal(void); extern void REF_DisableLocal(void);
extern int REF_IsLocalActive(void);
extern void REF_GetTrackingReport(RPT_TrackingReport *rep); extern void REF_GetTrackingReport(RPT_TrackingReport *rep);

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -363,7 +363,7 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
l = u + 1; l = u + 1;
r = v; r = v;
do { do {
while (x[l] < piv) l++; while (x[l] < piv && l < v) l++;
while (x[r] > piv) r--; while (x[r] > piv) r--;
if (r <= l) break; if (r <= l) break;
EXCH(x[l], x[r]); EXCH(x[l], x[r]);

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -32,31 +32,29 @@
#define GOT_REPORTS_H #define GOT_REPORTS_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000 #define REPORT_INVALID_OFFSET 0x80000000
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
int stratum; int stratum;
int poll; int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_OTHER} state; enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_OTHER} state;
unsigned long latest_meas_ago; /* seconds */ unsigned long latest_meas_ago; /* seconds */
long orig_latest_meas; /* microseconds (us) */ double orig_latest_meas; /* seconds */
long latest_meas; /* us */ double latest_meas; /* seconds */
unsigned long latest_meas_err; /* us */ double latest_meas_err; /* seconds */
long est_offset; /* us */
unsigned long est_offset_err; /* us */
long resid_freq; /* ppm * 1000 */
unsigned long resid_skew; /* ppm * 1000 */
} RPT_SourceReport ; } RPT_SourceReport ;
typedef struct { typedef struct {
unsigned long ref_id; unsigned long ref_id;
IPAddr ip_addr;
unsigned long stratum; unsigned long stratum;
struct timeval ref_time; struct timeval ref_time;
struct timeval current_correction; double current_correction;
double freq_ppm; double freq_ppm;
double resid_freq_ppm; double resid_freq_ppm;
double skew_ppm; double skew_ppm;
@@ -65,17 +63,20 @@ typedef struct {
} RPT_TrackingReport; } RPT_TrackingReport;
typedef struct { typedef struct {
unsigned long ip_addr; unsigned long ref_id;
IPAddr ip_addr;
unsigned long n_samples; unsigned long n_samples;
unsigned long n_runs; unsigned long n_runs;
unsigned long span_seconds; unsigned long span_seconds;
double resid_freq_ppm; double resid_freq_ppm;
double skew_ppm; double skew_ppm;
double sd_us; double sd;
double est_offset;
double est_offset_err;
} RPT_SourcestatsReport; } RPT_SourcestatsReport;
typedef struct { typedef struct {
unsigned long ref_time; struct timeval ref_time;
unsigned short n_samples; unsigned short n_samples;
unsigned short n_runs; unsigned short n_runs;
unsigned long span_seconds; unsigned long span_seconds;
@@ -94,7 +95,7 @@ typedef struct {
} RPT_ClientAccess_Report; } RPT_ClientAccess_Report;
typedef struct { typedef struct {
unsigned long ip_addr; IPAddr ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_auth; unsigned long cmd_hits_auth;
@@ -105,7 +106,7 @@ typedef struct {
} RPT_ClientAccessByIndex_Report; } RPT_ClientAccessByIndex_Report;
typedef struct { typedef struct {
time_t when; struct timeval when;
double slewed_offset; double slewed_offset;
double orig_offset; double orig_offset;
double residual; double residual;

2
rtc.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

2
rtc.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -107,6 +107,8 @@ static int measurement_period = LOWEST_MEASUREMENT_PERIOD;
static int timeout_running = 0; static int timeout_running = 0;
static SCH_TimeoutID timeout_id; static SCH_TimeoutID timeout_id;
static int skip_interrupts;
/* ================================================== */ /* ================================================== */
/* Maximum number of samples held */ /* Maximum number of samples held */
@@ -627,16 +629,11 @@ RTC_Linux_Initialise(void)
direc = CNF_GetLogDir(); direc = CNF_GetLogDir();
if (!mkdir_and_parents(direc)) { if (!mkdir_and_parents(direc)) {
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not create directory %s", direc); LOG(LOGS_ERR, LOGF_RtcLinux, "Could not create directory %s", direc);
logfile = NULL;
} else { } else {
logfilename = MallocArray(char, 2 + strlen(direc) + strlen(RTC_LOG)); logfilename = MallocArray(char, 2 + strlen(direc) + strlen(RTC_LOG));
strcpy(logfilename, direc); strcpy(logfilename, direc);
strcat(logfilename, "/"); strcat(logfilename, "/");
strcat(logfilename, RTC_LOG); strcat(logfilename, RTC_LOG);
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Couldn't open logfile %s for update", logfilename);
}
} }
} }
@@ -666,7 +663,7 @@ RTC_Linux_Finalise(void)
if (logfile) { if (logfile) {
fclose(logfile); fclose(logfile);
} }
Free(logfilename);
} }
/* ================================================== */ /* ================================================== */
@@ -682,6 +679,7 @@ switch_interrupts(int onoff)
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno)); LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno));
return; return;
} }
skip_interrupts = 1;
} else { } else {
status = ioctl(fd, RTC_UIE_OFF, 0); status = ioctl(fd, RTC_UIE_OFF, 0);
if (status < 0) { if (status < 0) {
@@ -837,7 +835,17 @@ process_reading(time_t rtc_time, struct timeval *system_time)
} }
if (logfile) { if (logfilename) {
if (!logfile) {
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Couldn't open logfile %s for update", logfilename);
Free(logfilename);
logfilename = NULL;
return;
}
}
rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec; rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec;
if (((logwrites++) % 32) == 0) { if (((logwrites++) % 32) == 0) {
@@ -869,12 +877,10 @@ read_from_device(void *any)
struct rtc_time rtc_raw; struct rtc_time rtc_raw;
struct tm rtc_tm; struct tm rtc_tm;
time_t rtc_t; time_t rtc_t;
double read_err;
int error = 0; int error = 0;
status = read(fd, &data, sizeof(data)); status = read(fd, &data, sizeof(data));
if (operating_mode == OM_NORMAL)
status = read(fd, &data, sizeof(data));
if (status < 0) { if (status < 0) {
/* This looks like a bad error : the file descriptor was indicating it was /* This looks like a bad error : the file descriptor was indicating it was
* ready to read but we couldn't read anything. Give up. */ * ready to read but we couldn't read anything. Give up. */
@@ -891,13 +897,19 @@ read_from_device(void *any)
return; return;
} }
if (skip_interrupts > 0) {
/* Wait for the next interrupt, this one may be bogus */
skip_interrupts--;
return;
}
if ((data & RTC_UIE) == RTC_UIE) { if ((data & RTC_UIE) == RTC_UIE) {
/* Update interrupt detected */ /* Update interrupt detected */
/* Read RTC time, sandwiched between two polls of the system clock /* Read RTC time, sandwiched between two polls of the system clock
so we can bound any error. */ so we can bound any error. */
LCL_ReadCookedTime(&sys_time, &read_err); SCH_GetFileReadyTime(&sys_time);
status = ioctl(fd, RTC_RD_TIME, &rtc_raw); status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status < 0) { if (status < 0) {
@@ -1104,7 +1116,8 @@ RTC_Linux_TimePreInit(void)
int int
RTC_Linux_GetReport(RPT_RTC_Report *report) RTC_Linux_GetReport(RPT_RTC_Report *report)
{ {
report->ref_time = (unsigned long) coef_ref_time; report->ref_time.tv_sec = coef_ref_time;
report->ref_time.tv_usec = 0;
report->n_samples = n_samples; report->n_samples = n_samples;
report->n_runs = n_runs; report->n_runs = n_runs;
if (n_samples > 1) { if (n_samples > 1) {
@@ -1169,12 +1182,9 @@ RTC_Linux_Trim(void)
void void
RTC_Linux_CycleLogFile(void) RTC_Linux_CycleLogFile(void)
{ {
if (logfile && logfilename) { if (logfile) {
fclose(logfile); fclose(logfile);
logfile = fopen(logfilename, "a"); logfile = NULL;
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not reopen logfile %s", logfilename);
}
logwrites = 0; logwrites = 0;
} }
} }

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

25
sched.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -71,6 +71,9 @@ typedef struct {
static FileHandlerEntry file_handlers[FD_SET_SIZE]; static FileHandlerEntry file_handlers[FD_SET_SIZE];
/* Last timestamp when a file descriptor became readable */
static struct timeval last_fdready;
/* ================================================== */ /* ================================================== */
/* Variables to handler the timer queue */ /* Variables to handler the timer queue */
@@ -225,6 +228,14 @@ SCH_RemoveInputFileHandler(int fd)
/* ================================================== */ /* ================================================== */
void
SCH_GetFileReadyTime(struct timeval *tv)
{
*tv = last_fdready;
}
/* ================================================== */
#define TQE_ALLOC_QUANTUM 32 #define TQE_ALLOC_QUANTUM 32
static TimerQueueEntry * static TimerQueueEntry *
@@ -510,10 +521,11 @@ handle_slew(struct timeval *raw,
void void
SCH_MainLoop(void) SCH_MainLoop(void)
{ {
fd_set rd, wr, ex; fd_set rd;
int status; int status;
struct timeval tv, *ptv; struct timeval tv, *ptv;
struct timeval now; struct timeval now;
double err;
if (!initialised) { if (!initialised) {
CROAK("Should be initialised"); CROAK("Should be initialised");
@@ -524,11 +536,6 @@ SCH_MainLoop(void)
/* Copy current set of read file descriptors */ /* Copy current set of read file descriptors */
memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set)); memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
/* Blank the write and exception descriptors - we aren't very
interested */
FD_ZERO(&wr);
FD_ZERO(&ex);
/* Try to dispatch any timeouts that have already gone by, and /* Try to dispatch any timeouts that have already gone by, and
keep going until all are done. (The earlier ones may take so keep going until all are done. (The earlier ones may take so
long to do that the later ones come around by the time they are long to do that the later ones come around by the time they are
@@ -555,13 +562,15 @@ SCH_MainLoop(void)
LOG_FATAL(LOGF_Scheduler, "No descriptors or timeout to wait for"); LOG_FATAL(LOGF_Scheduler, "No descriptors or timeout to wait for");
} }
status = select(one_highest_fd, &rd, &wr, &ex, ptv); status = select(one_highest_fd, &rd, NULL, NULL, ptv);
if (status < 0) { if (status < 0) {
if (!need_to_exit)
CROAK("Status < 0 after select"); CROAK("Status < 0 after select");
} else if (status > 0) { } else if (status > 0) {
/* A file descriptor is ready to read */ /* A file descriptor is ready to read */
LCL_ReadCookedTime(&last_fdready, &err);
dispatch_filehandlers(status, &rd); dispatch_filehandlers(status, &rd);
} else { } else {

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -60,6 +60,10 @@ extern void SCH_AddInputFileHandler
); );
extern void SCH_RemoveInputFileHandler(int fd); extern void SCH_RemoveInputFileHandler(int fd);
/* Get the time (cooked) when file descriptor became ready, intended for use
in file handlers */
extern void SCH_GetFileReadyTime(struct timeval *tv);
/* This queues a timeout to elapse at a given (raw) local time */ /* This queues a timeout to elapse at a given (raw) local time */
extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument); extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);

124
sources.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -88,6 +88,7 @@ struct SRC_Instance_Record {
unsigned long ref_id; /* The reference ID of this source unsigned long ref_id; /* The reference ID of this source
(i.e. its IP address, NOT the (i.e. its IP address, NOT the
reference _it_ is sync'd to) */ reference _it_ is sync'd to) */
IPAddr *ip_addr; /* Its IP address if NTP source */
/* Flag indicating that we are receiving packets with valid headers /* Flag indicating that we are receiving packets with valid headers
from this source and can use it as a reference */ from this source and can use it as a reference */
@@ -96,6 +97,9 @@ struct SRC_Instance_Record {
/* Flag indicating the status of the source */ /* Flag indicating the status of the source */
SRC_Status status; SRC_Status status;
/* Type of the source */
SRC_Type type;
struct SelectInfo sel_info; struct SelectInfo sel_info;
}; };
@@ -126,6 +130,8 @@ static int selected_source_index; /* Which source index is currently
static void static void
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq, slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
double doffset, int is_step_change, void *anything); double doffset, int is_step_change, void *anything);
static char *
source_to_string(SRC_Instance inst);
/* ================================================== */ /* ================================================== */
/* Initialisation function */ /* Initialisation function */
@@ -155,7 +161,7 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
SRC_Instance SRC_CreateNewInstance(unsigned long ref_id) SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
{ {
SRC_Instance result; SRC_Instance result;
@@ -164,7 +170,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
} }
result = MallocNew(struct SRC_Instance_Record); result = MallocNew(struct SRC_Instance_Record);
result->stats = SST_CreateInstance(ref_id); result->stats = SST_CreateInstance(ref_id, addr);
if (n_sources == max_n_sources) { if (n_sources == max_n_sources) {
/* Reallocate memory */ /* Reallocate memory */
@@ -184,8 +190,10 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
result->index = n_sources; result->index = n_sources;
result->leap_status = LEAP_Normal; result->leap_status = LEAP_Normal;
result->ref_id = ref_id; result->ref_id = ref_id;
result->ip_addr = addr;
result->reachable = 0; result->reachable = 0;
result->status = SRC_BAD_STATS; result->status = SRC_BAD_STATS;
result->type = type;
n_sources++; n_sources++;
@@ -280,7 +288,7 @@ void SRC_AccumulateSample
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d", LOG(LOGS_INFO, LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
UTI_IPToDottedQuad(inst->ref_id), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum); source_to_string(inst), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
#endif #endif
/* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET /* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
@@ -301,7 +309,7 @@ SRC_SetReachable(SRC_Instance inst)
inst->reachable = 1; inst->reachable = 1;
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s", UTI_IPToDottedQuad(inst->ref_id)); LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
#endif #endif
/* Don't do selection at this point, though - that will come about /* Don't do selection at this point, though - that will come about
@@ -316,7 +324,7 @@ SRC_UnsetReachable(SRC_Instance inst)
inst->reachable = 0; inst->reachable = 0;
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s%s", UTI_IPToDottedQuad(inst->ref_id), LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
(inst->index == selected_source_index) ? "(REF)":""); (inst->index == selected_source_index) ? "(REF)":"");
#endif #endif
@@ -349,6 +357,22 @@ compare_sort_elements(const void *a, const void *b)
} }
} }
/* ================================================== */
static char *
source_to_string(SRC_Instance inst)
{
switch (inst->type) {
case SRC_NTP:
return UTI_IPToString(inst->ip_addr);
case SRC_REFCLOCK:
return UTI_RefidToString(inst->ref_id);
default:
CROAK("Unknown source type");
}
return NULL;
}
/* ================================================== */ /* ================================================== */
/* This function selects the current reference from amongst the pool /* This function selects the current reference from amongst the pool
of sources we are holding. of sources we are holding.
@@ -418,7 +442,7 @@ SRC_SelectSource(unsigned long match_addr)
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f", LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f",
UTI_IPToDottedQuad(sources[i]->ref_id), source_to_string(sources[i]),
si->best_offset, si->root_distance, si->best_offset, si->root_distance,
si->lo_limit, si->hi_limit); si->lo_limit, si->hi_limit);
#endif #endif
@@ -491,7 +515,7 @@ SRC_SelectSource(unsigned long match_addr)
for (i=0; i<n_endpoints; i++) { for (i=0; i<n_endpoints; i++) {
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "i=%d t=%f tag=%d addr=%s", i, sort_list[i].offset, sort_list[i].tag, LOG(LOGS_INFO, LOGF_Sources, "i=%d t=%f tag=%d addr=%s", i, sort_list[i].offset, sort_list[i].tag,
UTI_IPToDottedQuad(sources[sort_list[i].index]->ref_id)); source_to_string(sources[sort_list[i].index]));
#endif #endif
switch(sort_list[i].tag) { switch(sort_list[i].tag) {
case LOW: case LOW:
@@ -565,12 +589,12 @@ SRC_SelectSource(unsigned long match_addr)
sel_sources[n_sel_sources++] = i; sel_sources[n_sel_sources++] = i;
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, UTI_IPToDottedQuad(sources[i]->ref_id)); LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, source_to_string(sources[i]));
#endif #endif
} else { } else {
sources[i]->status = SRC_FALSETICKER; sources[i]->status = SRC_FALSETICKER;
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, UTI_IPToDottedQuad(sources[i]->ref_id)); LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, source_to_string(sources[i]));
#endif #endif
} }
} }
@@ -603,7 +627,7 @@ SRC_SelectSource(unsigned long match_addr)
sel_sources[i] = INVALID_SOURCE; sel_sources[i] = INVALID_SOURCE;
sources[index]->status = SRC_JITTERY; sources[index]->status = SRC_JITTERY;
#if 0 #if 0
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, UTI_IPToDottedQuad(sources[i]->ref_id)); LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, source_to_string(sources[i]));
#endif #endif
} }
} }
@@ -632,18 +656,7 @@ SRC_SelectSource(unsigned long match_addr)
if (stratum < min_stratum) min_stratum = stratum; if (stratum < min_stratum) min_stratum = stratum;
} }
#if 0 /* Find the best source with minimum stratum */
LOG(LOGS_INFO, LOGF_Sources, "min_stratum=%d", min_stratum);
#endif
/* Does the current source have this stratum and is it still a
survivor? */
if ((selected_source_index == INVALID_SOURCE) ||
(sources[selected_source_index]->status != SRC_SELECTABLE) ||
(sources[selected_source_index]->sel_info.stratum > min_stratum)) {
/* We have to elect a new synchronisation source */
min_distance_index = INVALID_SOURCE; min_distance_index = INVALID_SOURCE;
for (i=0; i<n_sel_sources; i++) { for (i=0; i<n_sel_sources; i++) {
index = sel_sources[i]; index = sel_sources[i];
@@ -656,9 +669,23 @@ SRC_SelectSource(unsigned long match_addr)
} }
} }
#if 0
LOG(LOGS_INFO, LOGF_Sources, "min_stratum=%d", min_stratum);
#endif
/* Does the current source have this stratum, doesn't have distance
much worse than the best source and is it still a survivor? */
if ((selected_source_index == INVALID_SOURCE) ||
(sources[selected_source_index]->status != SRC_SELECTABLE) ||
(sources[selected_source_index]->sel_info.stratum > min_stratum) ||
(sources[selected_source_index]->sel_info.root_distance > 10 * min_distance)) {
/* We have to elect a new synchronisation source */
selected_source_index = min_distance_index; selected_source_index = min_distance_index;
LOG(LOGS_INFO, LOGF_Sources, "Selected source %s", LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
UTI_IPToDottedQuad(sources[selected_source_index]->ref_id)); source_to_string(sources[selected_source_index]));
#if 0 #if 0
@@ -687,11 +714,29 @@ SRC_SelectSource(unsigned long match_addr)
total_root_dispersion = (src_accrued_dispersion + total_root_dispersion = (src_accrued_dispersion +
sources[selected_source_index]->sel_info.root_dispersion); sources[selected_source_index]->sel_info.root_dispersion);
/* Accept leap second status if more than half of selectable sources agree */
for (i=j1=j2=0; i<n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->leap_status == LEAP_InsertSecond) {
j1++;
} else if (sources[index]->leap_status == LEAP_DeleteSecond) {
j2++;
}
}
if (j1 > n_sel_sources / 2) {
leap_status = LEAP_InsertSecond;
} else if (j2 > n_sel_sources / 2) {
leap_status = LEAP_DeleteSecond;
}
if ((match_addr == 0) || if ((match_addr == 0) ||
(match_addr == sources[selected_source_index]->ref_id)) { (match_addr == sources[selected_source_index]->ref_id)) {
REF_SetReference(min_stratum, leap_status, REF_SetReference(min_stratum, leap_status,
sources[selected_source_index]->ref_id, sources[selected_source_index]->ref_id,
sources[selected_source_index]->ip_addr,
&now, &now,
src_offset, src_offset,
src_frequency, src_frequency,
@@ -873,7 +918,16 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
return 0; return 0;
} else { } else {
src = sources[index]; src = sources[index];
report->ip_addr = src->ref_id;
memset(&report->ip_addr, 0, sizeof (report->ip_addr));
if (src->ip_addr)
report->ip_addr = *src->ip_addr;
else {
/* Use refid as an address */
report->ip_addr.addr.in4 = src->ref_id;
report->ip_addr.family = IPADDR_INET4;
}
switch (src->status) { switch (src->status) {
case SRC_SYNC: case SRC_SYNC:
report->state = RPT_SYNC; report->state = RPT_SYNC;
@@ -902,7 +956,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
/* ================================================== */ /* ================================================== */
int int
SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report) SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timeval *now)
{ {
SRC_Instance src; SRC_Instance src;
@@ -910,14 +964,28 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
return 0; return 0;
} else { } else {
src = sources[index]; src = sources[index];
report->ip_addr = src->ref_id; report->ref_id = src->ref_id;
SST_DoSourcestatsReport(src->stats, report); if (src->ip_addr)
report->ip_addr = *src->ip_addr;
else
report->ip_addr.family = IPADDR_UNSPEC;
SST_DoSourcestatsReport(src->stats, report, now);
return 1; return 1;
} }
} }
/* ================================================== */ /* ================================================== */
SRC_Type
SRC_GetType(int index)
{
if ((index >= n_sources) || (index < 0))
return -1;
return sources[index]->type;
}
/* ================================================== */
SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst) SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
{ {
SRC_Skew_Direction result = SRC_Skew_Nochange; SRC_Skew_Direction result = SRC_Skew_Nochange;

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -50,10 +50,15 @@ extern void SRC_Initialise(void);
/* Finalisation function */ /* Finalisation function */
extern void SRC_Finalise(void); extern void SRC_Finalise(void);
typedef enum {
SRC_NTP, /* NTP client/peer */
SRC_REFCLOCK /* Rerefence clock */
} SRC_Type;
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id); extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr);
/* Function to get rid of a source when it is being unconfigured. /* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this This may cause the current reference source to be reselected, if this
@@ -141,7 +146,9 @@ extern int SRC_IsSyncPeer(SRC_Instance inst);
extern int SRC_ReadNumberOfSources(void); extern int SRC_ReadNumberOfSources(void);
extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now); extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now);
extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report); extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timeval *now);
extern SRC_Type SRC_GetType(int index);
typedef enum { typedef enum {
SRC_Skew_Decrease, SRC_Skew_Decrease,

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -66,8 +66,9 @@ static unsigned long logwrites = 0;
struct SST_Stats_Record { struct SST_Stats_Record {
/* Reference ID of source, used for logging to statistics log */ /* Reference ID and IP address of source, used for logging to statistics log */
unsigned long refid; unsigned long refid;
IPAddr *ip_addr;
/* Number of samples currently stored. sample[n_samples-1] is the /* Number of samples currently stored. sample[n_samples-1] is the
newest. The samples are expected to be sorted in order, but that newest. The samples are expected to be sorted in order, but that
@@ -187,17 +188,20 @@ SST_Finalise(void)
/* This function creates a new instance of the statistics handler */ /* This function creates a new instance of the statistics handler */
SST_Stats SST_Stats
SST_CreateInstance(unsigned long refid) SST_CreateInstance(unsigned long refid, IPAddr *addr)
{ {
SST_Stats inst; SST_Stats inst;
inst = MallocNew(struct SST_Stats_Record); inst = MallocNew(struct SST_Stats_Record);
inst->refid = refid; inst->refid = refid;
inst->ip_addr = addr;
inst->n_samples = 0; inst->n_samples = 0;
inst->estimated_frequency = 0; inst->estimated_frequency = 0;
inst->skew = 2000.0e-6; inst->skew = 2000.0e-6;
inst->skew_dirn = SST_Skew_Nochange; inst->skew_dirn = SST_Skew_Nochange;
inst->estimated_offset = 0.0; inst->estimated_offset = 0.0;
inst->estimated_offset_sd = 86400.0; /* Assume it's at least within a day! */ inst->estimated_offset_sd = 86400.0; /* Assume it's at least within a day! */
inst->offset_time.tv_sec = 0;
inst->offset_time.tv_usec = 0;
inst->variance = 16.0; inst->variance = 16.0;
inst->nruns = 0; inst->nruns = 0;
return inst; return inst;
@@ -471,7 +475,7 @@ SST_DoNewRegression(SST_Stats inst)
fprintf(logfile, "%s %-15s %10.3e %10.3e %10.3e %10.3e %10.3e %7.1e %3d %3d %3d\n", fprintf(logfile, "%s %-15s %10.3e %10.3e %10.3e %10.3e %10.3e %7.1e %3d %3d %3d\n",
UTI_TimeToLogForm(inst->offset_time.tv_sec), UTI_TimeToLogForm(inst->offset_time.tv_sec),
UTI_IPToDottedQuad(inst->refid), inst->ip_addr ? UTI_IPToString(inst->ip_addr) : UTI_RefidToString(inst->refid),
sqrt(inst->variance), sqrt(inst->variance),
inst->estimated_offset, inst->estimated_offset,
inst->estimated_offset_sd, inst->estimated_offset_sd,
@@ -721,8 +725,12 @@ SST_PredictOffset(SST_Stats inst, struct timeval *when)
if (inst->n_samples < 3) { if (inst->n_samples < 3) {
/* We don't have any useful statistics, and presumably the poll /* We don't have any useful statistics, and presumably the poll
interval is minimal. We can't do any useful prediction other interval is minimal. We can't do any useful prediction other
than use the latest sample */ than use the latest sample or zero if we don't have any samples */
if (inst->n_samples > 0) {
return inst->offsets[inst->n_samples - 1]; return inst->offsets[inst->n_samples - 1];
} else {
return 0.0;
}
} else { } else {
UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time); UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
return inst->estimated_offset + elapsed * inst->estimated_frequency; return inst->estimated_offset + elapsed * inst->estimated_frequency;
@@ -837,47 +845,24 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
void void
SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now) SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now)
{ {
int n, nb; int n;
double est_offset, est_err, elapsed, sample_elapsed;
struct timeval ago; struct timeval ago;
if (inst->n_samples > 0) { if (inst->n_samples > 0) {
n = inst->n_samples - 1; n = inst->n_samples - 1;
report->orig_latest_meas = (long)(0.5 + 1.0e6 * inst->orig_offsets[n]); report->orig_latest_meas = inst->orig_offsets[n];
report->latest_meas = (long)(0.5 + 1.0e6 * inst->offsets[n]); report->latest_meas = inst->offsets[n];
report->latest_meas_err = (unsigned long)(0.5 + 1.0e6 * (0.5*inst->root_delays[n] + inst->root_dispersions[n])); report->latest_meas_err = 0.5*inst->root_delays[n] + inst->root_dispersions[n];
report->stratum = inst->strata[n]; report->stratum = inst->strata[n];
UTI_DiffTimevals(&ago, now, &inst->sample_times[n]); UTI_DiffTimevals(&ago, now, &inst->sample_times[n]);
report->latest_meas_ago = ago.tv_sec; report->latest_meas_ago = ago.tv_sec;
if (inst->n_samples > 3) {
UTI_DiffTimevalsToDouble(&elapsed, now, &inst->offset_time);
nb = inst->best_single_sample;
UTI_DiffTimevalsToDouble(&sample_elapsed, now, &(inst->sample_times[nb]));
est_offset = inst->estimated_offset + elapsed * inst->estimated_frequency;
est_err = (inst->estimated_offset_sd +
sample_elapsed * inst->skew +
(0.5*inst->root_delays[nb] + inst->root_dispersions[nb]));
report->est_offset = (long)(0.5 + 1.0e6 * est_offset);
report->est_offset_err = (unsigned long) (0.5 + 1.0e6 * est_err);
report->resid_freq = (long) (0.5 * 1.0e9 * inst->estimated_frequency);
report->resid_skew = (unsigned long) (0.5 + 1.0e9 * inst->skew);
} else {
report->est_offset = report->latest_meas;
report->est_offset_err = report->latest_meas_err;
report->resid_freq = 0;
report->resid_skew = 0;
}
} else { } else {
report->latest_meas_ago = 86400 * 365 * 10;
report->orig_latest_meas = 0; report->orig_latest_meas = 0;
report->latest_meas = 0; report->latest_meas = 0;
report->latest_meas_err = 0; report->latest_meas_err = 0;
report->stratum = 0; report->stratum = 0;
report->est_offset = 0;
report->est_offset_err = 0;
report->resid_freq = 0;
report->resid_skew = 0;
} }
} }
@@ -892,10 +877,11 @@ SST_Skew_Direction SST_LastSkewChange(SST_Stats inst)
/* ================================================== */ /* ================================================== */
void void
SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report) SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now)
{ {
double dspan; double dspan;
int n; double elapsed, sample_elapsed;
int n, nb;
report->n_samples = inst->n_samples; report->n_samples = inst->n_samples;
report->n_runs = inst->nruns; report->n_runs = inst->nruns;
@@ -904,13 +890,28 @@ SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report)
n = inst->n_samples - 1; n = inst->n_samples - 1;
UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[n], &inst->sample_times[0]); UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[n], &inst->sample_times[0]);
report->span_seconds = (unsigned long) (dspan + 0.5); report->span_seconds = (unsigned long) (dspan + 0.5);
if (inst->n_samples > 3) {
UTI_DiffTimevalsToDouble(&elapsed, now, &inst->offset_time);
nb = inst->best_single_sample;
UTI_DiffTimevalsToDouble(&sample_elapsed, now, &(inst->sample_times[nb]));
report->est_offset = inst->estimated_offset + elapsed * inst->estimated_frequency;
report->est_offset_err = (inst->estimated_offset_sd +
sample_elapsed * inst->skew +
(0.5*inst->root_delays[nb] + inst->root_dispersions[nb]));
} else {
report->est_offset = inst->offsets[n];
report->est_offset_err = 0.5*inst->root_delays[n] + inst->root_dispersions[n];
}
} else { } else {
report->span_seconds = 0; report->span_seconds = 0;
report->est_offset = 0;
report->est_offset_err = 0;
} }
report->resid_freq_ppm = 1.0e6 * inst->estimated_frequency; report->resid_freq_ppm = 1.0e6 * inst->estimated_frequency;
report->skew_ppm = 1.0e6 * inst->skew; report->skew_ppm = 1.0e6 * inst->skew;
report->sd_us = 1.0e6 * sqrt(inst->variance); report->sd = sqrt(inst->variance);
} }
/* ================================================== */ /* ================================================== */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -42,7 +42,7 @@ extern void SST_Initialise(void);
extern void SST_Finalise(void); extern void SST_Finalise(void);
/* This function creates a new instance of the statistics handler */ /* This function creates a new instance of the statistics handler */
extern SST_Stats SST_CreateInstance(unsigned long refid); extern SST_Stats SST_CreateInstance(unsigned long refid, IPAddr *addr);
/* This function deletes an instance of the statistics handler. */ /* This function deletes an instance of the statistics handler. */
extern void SST_DeleteInstance(SST_Stats inst); extern void SST_DeleteInstance(SST_Stats inst);
@@ -140,7 +140,7 @@ extern int SST_LoadFromFile(SST_Stats inst, FILE *in);
extern void SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now); extern void SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now);
extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report); extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now);
typedef enum { typedef enum {
SST_Skew_Decrease, SST_Skew_Decrease,

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -20,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

39
sys.c
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -30,6 +30,7 @@
*/ */
#include "sys.h" #include "sys.h"
#include "logging.h"
#if defined (LINUX) #if defined (LINUX)
#include "sys_linux.h" #include "sys_linux.h"
@@ -97,8 +98,42 @@ SYS_Finalise(void)
} }
/* ================================================== */ /* ================================================== */
/* ================================================== */
void SYS_DropRoot(char *user)
{
#if defined(LINUX) && defined (FEAT_LINUXCAPS)
SYS_Linux_DropRoot(user);
#else
LOG_FATAL(LOGF_Sys, "dropping root privileges not supported");
#endif
return;
}
/* ================================================== */ /* ================================================== */
void SYS_SetScheduler(int SchedPriority)
{
#if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
SYS_Linux_SetScheduler(SchedPriority);
#else
LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported");
#endif
return;
}
/* ================================================== */
void SYS_LockMemory(void)
{
#if defined(LINUX) && defined(HAVE_MLOCKALL)
SYS_Linux_MemLockAll(1);
#else
LOG_FATAL(LOGF_Sys, "memory locking not supported");
#endif
return;
}
/* ================================================== */

8
sys.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -39,4 +39,10 @@ extern void SYS_Initialise(void);
/* Called at the end of the run to do final clean-up */ /* Called at the end of the run to do final clean-up */
extern void SYS_Finalise(void); extern void SYS_Finalise(void);
/* Drop root privileges to the specified user */
extern void SYS_DropRoot(char *user);
extern void SYS_SetScheduler(int SchedPriority);
extern void SYS_LockMemory(void);
#endif /* GOT_SYS_H */ #endif /* GOT_SYS_H */

View File

@@ -7,6 +7,8 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +21,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -39,6 +41,25 @@
#include <assert.h> #include <assert.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#if defined(HAVE_SCHED_SETSCHEDULER)
# include <sched.h>
int SchedPriority = 0;
#endif
#if defined(HAVE_MLOCKALL)
# include <sys/mman.h>
#include <sys/resource.h>
int LockAll = 0;
#endif
#ifdef FEAT_LINUXCAPS
#include <sys/types.h>
#include <pwd.h>
#include <sys/prctl.h>
#include <sys/capability.h>
#include <grp.h>
#endif
#include "localp.h" #include "localp.h"
#include "sys_linux.h" #include "sys_linux.h"
#include "sched.h" #include "sched.h"
@@ -84,10 +105,11 @@ static int version_major;
static int version_minor; static int version_minor;
static int version_patchlevel; static int version_patchlevel;
/* Flag indicating whether adjtimex() with txc.modes equal to zero /* Flag indicating whether adjtimex() returns the remaining time adjustment
returns the remaining time adjustment or not. If not we have to read or not. If not we have to read the outstanding adjustment by setting it to
the outstanding adjustment by setting it to zero, examining the return zero, examining the return value and setting the outstanding adjustment back
value and setting the outstanding adjustment back again. */ again. If 1, txc.modes equal to zero is used to read the time. If 2,
txc.modes is set to ADJ_OFFSET_SS_READ. */
static int have_readonly_adjtime; static int have_readonly_adjtime;
@@ -106,10 +128,24 @@ our_round(double x) {
return y; return y;
} }
inline static long
our_lround(double x) {
int y;
if (x > 0.0)
y = x + 0.5;
else
y = x - 0.5;
return y;
}
/* ================================================== */ /* ================================================== */
/* Amount of outstanding offset to process */ /* Amount of outstanding offset to process */
static double offset_register; static double offset_register;
/* Flag set true if an adjtime slew was started and still may be running */
static int slow_slewing;
/* Flag set true if a fast slew (one done by altering tick) is being /* Flag set true if a fast slew (one done by altering tick) is being
run at the moment */ run at the moment */
static int fast_slewing; static int fast_slewing;
@@ -233,16 +269,28 @@ initiate_slew(void)
return; return;
} }
/* Cancel any standard adjtime that is running */
if (slow_slewing) {
offset = 0;
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in accrue_offset");
}
offset_register -= (double) offset / 1.0e6;
slow_slewing = 0;
}
if (fabs(offset_register) < MAX_ADJUST_WITH_ADJTIME) { if (fabs(offset_register) < MAX_ADJUST_WITH_ADJTIME) {
/* Use adjtime to do the shift */ /* Use adjtime to do the shift */
offset = (long)(0.5 + 1.0e6*(-offset_register)); offset = our_lround(1.0e6 * -offset_register);
offset_register += offset * 1e-6;
if (offset != 0) {
if (TMX_ApplyOffset(&offset) < 0) { if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in initiate_slew"); CROAK("adjtimex() failed in initiate_slew");
} }
slow_slewing = 1;
offset_register = 0.0; }
} else { } else {
/* If the system clock has a high drift rate, the combination of /* If the system clock has a high drift rate, the combination of
@@ -353,19 +401,9 @@ abort_slew(void)
static void static void
accrue_offset(double offset) accrue_offset(double offset)
{ {
long toffset;
/* Add the new offset to the register */ /* Add the new offset to the register */
offset_register += offset; offset_register += offset;
/* Cancel any standard adjtime that is running */
toffset = 0;
if (TMX_ApplyOffset(&toffset) < 0) {
CROAK("adjtimex() failed in accrue_offset");
}
offset_register -= (double) toffset / 1.0e6;
if (!fast_slewing) { if (!fast_slewing) {
initiate_slew(); initiate_slew();
} /* Otherwise, when the fast slew completes, any other stuff } /* Otherwise, when the fast slew completes, any other stuff
@@ -511,28 +549,47 @@ get_offset_correction(struct timeval *raw,
double fast_slew_duration; double fast_slew_duration;
double fast_slew_achieved; double fast_slew_achieved;
double fast_slew_remaining; double fast_slew_remaining;
long offset; long offset, toffset;
if (have_readonly_adjtime) { if (!slow_slewing) {
if (TMX_GetOffsetLeft(&offset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
}
adjtime_left = (double)offset / 1.0e6;
} else {
offset = 0; offset = 0;
if (TMX_ApplyOffset(&offset) < 0) { } else {
again:
switch (have_readonly_adjtime) {
case 2:
if (TMX_GetOffsetLeft(&offset) < 0) {
LOG(LOGS_INFO, LOGF_SysLinux, "adjtimex() doesn't support ADJ_OFFSET_SS_READ");
have_readonly_adjtime = 0;
goto again;
}
break;
case 0:
toffset = 0;
if (TMX_ApplyOffset(&toffset) < 0) {
CROAK("adjtimex() failed in get_offset_correction"); CROAK("adjtimex() failed in get_offset_correction");
} }
offset = toffset;
if (TMX_ApplyOffset(&toffset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
}
break;
case 1:
if (TMX_GetOffsetLeftOld(&offset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
}
break;
default:
assert(0);
}
if (offset == 0) {
/* adjtime slew has finished */
slow_slewing = 0;
}
}
adjtime_left = (double)offset / 1.0e6; adjtime_left = (double)offset / 1.0e6;
/* txc.offset still set from return value of last call */
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
}
}
if (fast_slewing) { if (fast_slewing) {
UTI_DiffTimevalsToDouble(&fast_slew_duration, raw, &slew_start_tv); UTI_DiffTimevalsToDouble(&fast_slew_duration, raw, &slew_start_tv);
fast_slew_achieved = delta_total_tick * fast_slew_duration / fast_slew_achieved = delta_total_tick * fast_slew_duration /
@@ -566,6 +623,7 @@ immediate_step(void)
} }
offset_register -= (double) offset / 1.0e6; offset_register -= (double) offset / 1.0e6;
slow_slewing = 0;
if (gettimeofday(&old_time, &tz) < 0) { if (gettimeofday(&old_time, &tz) < 0) {
CROAK("gettimeofday() failed in immediate_step"); CROAK("gettimeofday() failed in immediate_step");
@@ -584,6 +642,21 @@ immediate_step(void)
/* ================================================== */ /* ================================================== */
static void
set_leap(int leap)
{
if (TMX_SetLeap(leap) < 0) {
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed in set_leap");
}
LOG(LOGS_INFO, LOGF_SysLinux, "System clock status set to %s leap second",
leap ? (leap > 0 ? "insert" : "delete") : "not insert/delete");
return;
}
/* ================================================== */
/* Estimate the value of HZ given the value of txc.tick that chronyd finds when /* Estimate the value of HZ given the value of txc.tick that chronyd finds when
* it starts. The only credible values are 100 (Linux/x86) or powers of 2. * it starts. The only credible values are 100 (Linux/x86) or powers of 2.
* Also, the bounds checking inside the kernel's adjtimex system call enforces * Also, the bounds checking inside the kernel's adjtimex system call enforces
@@ -762,13 +835,19 @@ get_version_specific_details(void)
case 4: case 4:
case 5: case 5:
case 6: case 6:
if (minor < 6 || patch < 27) {
/* These seem to be like 2.0.32 */
freq_scale = (hz==100) ? (128.0 / 128.125) : basic_freq_scale;
have_readonly_adjtime = 0;
break;
}
/* Let's be optimistic that these will be the same until proven /* Let's be optimistic that these will be the same until proven
otherwise :-) */ otherwise :-) */
case 7: case 7:
case 8: case 8:
/* These seem to be like 2.0.32 */ /* These don't need scaling */
freq_scale = (hz==100) ? (128.0 / 128.125) : basic_freq_scale; freq_scale = 1.0;
have_readonly_adjtime = 0; have_readonly_adjtime = 2;
break; break;
default: default:
LOG_FATAL(LOGF_SysLinux, "Kernel version not supported yet, sorry."); LOG_FATAL(LOGF_SysLinux, "Kernel version not supported yet, sorry.");
@@ -805,7 +884,7 @@ SYS_Linux_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency, lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset, accrue_offset, apply_step_offset,
get_offset_correction, immediate_step); get_offset_correction, immediate_step, set_leap);
} }
/* ================================================== */ /* ================================================== */
@@ -831,6 +910,106 @@ SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel)
/* ================================================== */ /* ================================================== */
#ifdef FEAT_LINUXCAPS
void
SYS_Linux_DropRoot(char *user)
{
struct passwd *pw;
cap_t cap;
if (user == NULL)
return;
if ((pw = getpwnam(user)) == NULL) {
LOG_FATAL(LOGF_SysLinux, "getpwnam(%s) failed", user);
}
if (prctl(PR_SET_KEEPCAPS, 1)) {
LOG_FATAL(LOGF_SysLinux, "prcap() failed");
}
if (setgroups(0, NULL)) {
LOG_FATAL(LOGF_SysLinux, "setgroups() failed");
}
if (setgid(pw->pw_gid)) {
LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", pw->pw_gid);
}
if (setuid(pw->pw_uid)) {
LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", pw->pw_uid);
}
if ((cap = cap_from_text("cap_sys_time=ep")) == NULL) {
LOG_FATAL(LOGF_SysLinux, "cap_from_text() failed");
}
if (cap_set_proc(cap)) {
LOG_FATAL(LOGF_SysLinux, "cap_set_proc() failed");
}
cap_free(cap);
LOG(LOGS_INFO, LOGF_SysLinux, "Privileges dropped to user %s", user);
}
#endif
/* ================================================== */
#if defined(HAVE_SCHED_SETSCHEDULER)
/* Install SCHED_FIFO real-time scheduler with specified priority */
void SYS_Linux_SetScheduler(int SchedPriority)
{
int pmax, pmin;
struct sched_param sched;
if (SchedPriority < 1 || SchedPriority > 99) {
LOG_FATAL(LOGF_SysLinux, "Bad scheduler priority: %d", SchedPriority);
} else {
sched.sched_priority = SchedPriority;
pmax = sched_get_priority_max(SCHED_FIFO);
pmin = sched_get_priority_min(SCHED_FIFO);
if ( SchedPriority > pmax ) {
sched.sched_priority = pmax;
}
else if ( SchedPriority < pmin ) {
sched.sched_priority = pmin;
}
if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) {
LOG(LOGS_ERR, LOGF_SysLinux, "sched_setscheduler() failed");
}
else {
LOG(LOGS_INFO, LOGF_SysLinux, "Enabled SCHED_FIFO with priority %d", sched.sched_priority);
}
}
}
#endif /* HAVE_SCHED_SETSCHEDULER */
#if defined(HAVE_MLOCKALL)
/* Lock the process into RAM so that it will never be swapped out */
void SYS_Linux_MemLockAll(int LockAll)
{
struct rlimit rlim;
if (LockAll == 1 ) {
/* Make sure that we will be able to lock all the memory we need */
/* even after dropping privileges. This does not actually reaerve any memory */
rlim.rlim_max = RLIM_INFINITY;
rlim.rlim_cur = RLIM_INFINITY;
if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
LOG(LOGS_ERR, LOGF_SysLinux, "setrlimit() failed: not locking into RAM");
}
else {
if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
LOG(LOGS_ERR, LOGF_SysLinux, "mlockall() failed");
}
else {
LOG(LOGS_INFO, LOGF_SysLinux, "Successfully locked into RAM");
}
}
}
}
#endif /* HAVE_MLOCKALL */
#endif /* LINUX */ #endif /* LINUX */
/* vim:ts=8 /* vim:ts=8

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -37,4 +37,10 @@ extern void SYS_Linux_Finalise(void);
extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel); extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel);
extern void SYS_Linux_DropRoot(char *user);
extern void SYS_Linux_MemLockAll(int LockAll);
extern void SYS_Linux_SetScheduler(int SchedPriority);
#endif /* GOT_SYS_LINUX_H */ #endif /* GOT_SYS_LINUX_H */

View File

@@ -20,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -308,7 +308,8 @@ SYS_NetBSD_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency, lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset, accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */); get_offset_correction, NULL /* immediate_step */,
NULL /* set_leap */);
} }

View File

@@ -20,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -444,7 +444,8 @@ SYS_Solaris_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency, lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset, accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */); get_offset_correction, NULL /* immediate_step */,
NULL /* set_leap */);
/* Turn off the kernel switch that keeps the system clock in step /* Turn off the kernel switch that keeps the system clock in step
with the non-volatile clock */ with the non-volatile clock */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -368,7 +368,7 @@ setup_kernel(unsigned long on_off)
} }
if (kvm_write(kt, nl[2].n_value, if (kvm_write(kt, nl[2].n_value,
(char *)(&(on_off ? default_tickadj : our_tickadj)), (char *)(on_off ? &default_tickadj : &our_tickadj),
sizeof(unsigned long)) < 0) { sizeof(unsigned long)) < 0) {
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _tickadj"); LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _tickadj");
kvm_close(kt); kvm_close(kt);
@@ -395,7 +395,8 @@ SYS_SunOS_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency, lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset, accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */); get_offset_correction, NULL /* immediate_step */,
NULL /* set_leap */);
/* Turn off the kernel switch that keeps the system clock in step /* Turn off the kernel switch that keeps the system clock in step
with the non-volatile clock */ with the non-volatile clock */

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************

View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -79,6 +79,11 @@
#endif #endif
#ifdef HAVE_IPV6
/* For inet_ntop() */
#include <arpa/inet.h>
#endif
#if defined (SOLARIS) || defined(SUNOS) #if defined (SOLARIS) || defined(SUNOS)
/* Only needed on these platforms, and doesn't exist on some Linux /* Only needed on these platforms, and doesn't exist on some Linux
versions. */ versions. */

330
util.c
View File

@@ -7,6 +7,7 @@
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -19,7 +20,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -31,7 +32,7 @@
#include "sysincl.h" #include "sysincl.h"
#include "util.h" #include "util.h"
#include "logging.h" #include "md5.h"
/* ================================================== */ /* ================================================== */
@@ -65,21 +66,14 @@ UTI_CompareTimevals(struct timeval *a, struct timeval *b)
} else if (a->tv_sec > b->tv_sec) { } else if (a->tv_sec > b->tv_sec) {
return +1; return +1;
} else { } else {
if (a->tv_sec != b->tv_sec) {
CROAK("a->tv_sec != b->tv_sec");
}
if (a->tv_usec < b->tv_usec) { if (a->tv_usec < b->tv_usec) {
return -1; return -1;
} else if (a->tv_usec > b->tv_usec) { } else if (a->tv_usec > b->tv_usec) {
return +1; return +1;
} else { } else {
if (a->tv_usec != b->tv_usec) {
CROAK("a->tv_usec != b->tv_usec");
}
return 0; return 0;
} }
} }
CROAK("Impossible"); /* Shouldn't be able to fall through. */
} }
/* ================================================== */ /* ================================================== */
@@ -87,12 +81,14 @@ UTI_CompareTimevals(struct timeval *a, struct timeval *b)
INLINE_STATIC void INLINE_STATIC void
UTI_NormaliseTimeval(struct timeval *x) UTI_NormaliseTimeval(struct timeval *x)
{ {
while (x->tv_usec >= 1000000) { /* Reduce tv_usec to within +-1000000 of zero. JGH */
++x->tv_sec; if ((x->tv_usec >= 1000000) || (x->tv_usec <= -1000000)) {
x->tv_usec -= 1000000; x->tv_sec += x->tv_usec/1000000;
x->tv_usec = x->tv_usec%1000000;
} }
while (x->tv_usec < 0) { /* Make tv_usec positive. JGH */
if (x->tv_usec < 0) {
--x->tv_sec; --x->tv_sec;
x->tv_usec += 1000000; x->tv_usec += 1000000;
} }
@@ -110,17 +106,9 @@ UTI_DiffTimevals(struct timeval *result,
result->tv_usec = a->tv_usec - b->tv_usec; result->tv_usec = a->tv_usec - b->tv_usec;
/* Correct microseconds field to bring it into the range /* Correct microseconds field to bring it into the range
[0,1000000) */ (0,1000000) */
while (result->tv_usec < 0) { UTI_NormaliseTimeval(result); /* JGH */
result->tv_usec += 1000000;
--result->tv_sec;
}
while (result->tv_usec > 999999) {
result->tv_usec -= 1000000;
++result->tv_sec;
}
return; return;
} }
@@ -191,7 +179,7 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
} }
tvhalf.tv_sec = tvdiff.tv_sec / 2; tvhalf.tv_sec = tvdiff.tv_sec / 2;
tvhalf.tv_usec = tvdiff.tv_usec / 2 + (tvdiff.tv_sec % 2); tvhalf.tv_usec = tvdiff.tv_usec / 2 + (tvdiff.tv_sec % 2) * 500000; /* JGH */
average->tv_sec = earlier->tv_sec + tvhalf.tv_sec; average->tv_sec = earlier->tv_sec + tvhalf.tv_sec;
average->tv_usec = earlier->tv_usec + tvhalf.tv_usec; average->tv_usec = earlier->tv_usec + tvhalf.tv_usec;
@@ -199,16 +187,6 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
/* Bring into range */ /* Bring into range */
UTI_NormaliseTimeval(average); UTI_NormaliseTimeval(average);
while (average->tv_usec >= 1000000) {
++average->tv_sec;
average->tv_usec -= 1000000;
}
while (average->tv_usec < 0) {
--average->tv_sec;
average->tv_usec += 1000000;
}
} }
/* ================================================== */ /* ================================================== */
@@ -264,21 +242,184 @@ UTI_TimestampToString(NTP_int64 *ts)
/* ================================================== */ /* ================================================== */
char * char *
UTI_IPToDottedQuad(unsigned long ip) UTI_RefidToString(unsigned long ref_id)
{ {
unsigned long a, b, c, d; unsigned int a, b, c, d;
char *result; char *result;
a = (ref_id>>24) & 0xff;
b = (ref_id>>16) & 0xff;
c = (ref_id>> 8) & 0xff;
d = (ref_id>> 0) & 0xff;
result = NEXT_BUFFER;
snprintf(result, BUFFER_LENGTH, "%c%c%c%c", a, b, c, d);
return result;
}
/* ================================================== */
char *
UTI_IPToString(IPAddr *addr)
{
unsigned long a, b, c, d, ip;
uint8_t *ip6;
char *result;
result = NEXT_BUFFER;
switch (addr->family) {
case IPADDR_UNSPEC:
snprintf(result, BUFFER_LENGTH, "[UNSPEC]");
break;
case IPADDR_INET4:
ip = addr->addr.in4;
a = (ip>>24) & 0xff; a = (ip>>24) & 0xff;
b = (ip>>16) & 0xff; b = (ip>>16) & 0xff;
c = (ip>> 8) & 0xff; c = (ip>> 8) & 0xff;
d = (ip>> 0) & 0xff; d = (ip>> 0) & 0xff;
result = NEXT_BUFFER;
snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d); snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d);
break;
case IPADDR_INET6:
ip6 = addr->addr.in6;
#ifdef HAVE_IPV6
inet_ntop(AF_INET6, ip6, result, BUFFER_LENGTH);
#else
snprintf(result, BUFFER_LENGTH, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7],
ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]);
#endif
break;
default:
snprintf(result, BUFFER_LENGTH, "[UNKNOWN]");
}
return result; return result;
} }
/* ================================================== */ /* ================================================== */
int
UTI_StringToIP(const char *addr, IPAddr *ip)
{
#ifdef HAVE_IPV6
struct in_addr in4;
struct in6_addr in6;
if (inet_pton(AF_INET, addr, &in4) > 0) {
ip->family = IPADDR_INET4;
ip->addr.in4 = ntohl(in4.s_addr);
return 1;
}
if (inet_pton(AF_INET6, addr, &in6) > 0) {
ip->family = IPADDR_INET6;
memcpy(ip->addr.in6, in6.s6_addr, sizeof (ip->addr.in6));
return 1;
}
#else
unsigned long a, b, c, d, n;
n = sscanf(addr, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n == 4) {
ip->family = IPADDR_INET4;
ip->addr.in4 = ((a & 0xff) << 24) | ((b & 0xff) << 16) |
((c & 0xff) << 8) | (d & 0xff);
return 1;
}
#endif
return 0;
}
/* ================================================== */
unsigned long
UTI_IPToRefid(IPAddr *ip)
{
MD5_CTX ctx;
switch (ip->family) {
case IPADDR_INET4:
return ip->addr.in4;
case IPADDR_INET6:
MD5Init(&ctx);
MD5Update(&ctx, (unsigned const char *) ip->addr.in6, sizeof (ip->addr.in6));
MD5Final(&ctx);
return ctx.digest[0] << 24 | ctx.digest[1] << 16 | ctx.digest[2] << 8 | ctx.digest[3];
}
return 0;
}
/* ================================================== */
void
UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest)
{
/* Don't send uninitialized bytes over network */
memset(dest, 0, sizeof (IPAddr));
dest->family = htons(src->family);
switch (src->family) {
case IPADDR_INET4:
dest->addr.in4 = htonl(src->addr.in4);
break;
case IPADDR_INET6:
memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
break;
}
}
/* ================================================== */
void
UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest)
{
dest->family = ntohs(src->family);
switch (dest->family) {
case IPADDR_INET4:
dest->addr.in4 = ntohl(src->addr.in4);
break;
case IPADDR_INET6:
memcpy(dest->addr.in6, src->addr.in6, sizeof (dest->addr.in6));
break;
}
}
/* ================================================== */
int
UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask)
{
int i, d;
if (a->family != b->family)
return a->family - b->family;
if (mask && mask->family != b->family)
mask = NULL;
switch (a->family) {
case IPADDR_UNSPEC:
return 0;
case IPADDR_INET4:
if (mask)
return (a->addr.in4 & mask->addr.in4) - (b->addr.in4 & mask->addr.in4);
else
return a->addr.in4 - b->addr.in4;
case IPADDR_INET6:
for (i = 0, d = 0; !d && i < 16; i++) {
if (mask)
d = (a->addr.in6[i] & mask->addr.in6[i]) -
(b->addr.in6[i] & mask->addr.in6[i]);
else
d = a->addr.in6[i] - b->addr.in6[i];
}
return d;
}
return 0;
}
/* ================================================== */
char * char *
UTI_TimeToLogForm(time_t t) UTI_TimeToLogForm(time_t t)
{ {
@@ -346,19 +487,112 @@ UTI_Int64ToTimeval(NTP_int64 *src,
} }
/* ================================================== */ /* ================================================== */
/* Force a core dump and exit without doing abort() or assert(0).
These do funny things with the call stack in the core file that is
generated, which makes diagnosis difficult. */
int void
croak(const char *file, int line, const char *msg) UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
{ {
int a; uint32_t sec_low, sec_high;
LOG(LOGS_ERR, LOGF_Util, "Unexpected condition [%s] at %s:%d, core dumped",
msg, file, line); dest->tv_usec = ntohl(src->tv_nsec) / 1000;
a = * (int *) 0; sec_high = ntohl(src->tv_sec_high);
return a; /* Can't happen - this stops the optimiser optimising the sec_low = ntohl(src->tv_sec_low);
line above */
/* get the missing bits from current time when received timestamp
is only 32-bit */
if (sizeof (time_t) > 4 && sec_high == TV_NOHIGHSEC) {
struct timeval now;
struct timezone tz;
gettimeofday(&now, &tz);
sec_high = now.tv_sec >> 16 >> 16;
}
dest->tv_sec = (time_t)sec_high << 16 << 16 | sec_low;
}
/* ================================================== */
void
UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
{
dest->tv_nsec = htonl(src->tv_usec * 1000);
if (sizeof (time_t) > 4)
dest->tv_sec_high = htonl(src->tv_sec >> 16 >> 16);
else
dest->tv_sec_high = htonl(TV_NOHIGHSEC);
dest->tv_sec_low = htonl(src->tv_sec);
}
/* ================================================== */
#define FLOAT_EXP_BITS 7
#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
double
UTI_FloatNetworkToHost(Float f)
{
int32_t exp, coef, x;
x = ntohl(f.f);
exp = (x >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
coef = x << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
return coef * pow(2.0, exp);
}
Float
UTI_FloatHostToNetwork(double x)
{
int32_t exp, coef, neg;
Float f;
if (x < 0.0) {
x = -x;
neg = 1;
} else {
neg = 0;
}
if (x < 1.0e-100) {
exp = coef = 0;
} else if (x > 1.0e100) {
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else {
exp = log(x) / log(2) + 1;
coef = x * pow(2.0, -exp + FLOAT_COEF_BITS) + 0.5;
assert(coef > 0);
/* we may need to shift up to two bits down */
while (coef > FLOAT_COEF_MAX + neg) {
coef >>= 1;
exp++;
}
if (exp > FLOAT_EXP_MAX) {
/* overflow */
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else if (exp < FLOAT_EXP_MIN) {
/* underflow */
if (exp + FLOAT_COEF_BITS >= FLOAT_EXP_MIN) {
coef >>= FLOAT_EXP_MIN - exp;
exp = FLOAT_EXP_MIN;
} else {
exp = coef = 0;
}
}
}
/* negate back */
if (neg)
coef = (uint32_t)-coef << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
f.f = htonl(exp << FLOAT_COEF_BITS | coef);
return f;
} }
/* ================================================== */ /* ================================================== */

28
util.h
View File

@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * 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., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
********************************************************************** **********************************************************************
@@ -33,7 +33,9 @@
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#include "ntp.h" #include "ntp.h"
#include "candm.h"
/* Convert a timeval into a floating point number of seconds */ /* Convert a timeval into a floating point number of seconds */
extern void UTI_TimevalToDouble(struct timeval *a, double *b); extern void UTI_TimevalToDouble(struct timeval *a, double *b);
@@ -72,8 +74,17 @@ extern char *UTI_TimevalToString(struct timeval *tv);
diagnostic display */ diagnostic display */
extern char *UTI_TimestampToString(NTP_int64 *ts); extern char *UTI_TimestampToString(NTP_int64 *ts);
/* Convert an IP address to dotted quad notation, for diagnostics */ /* Convert ref_id into a temporary string, for diagnostics */
extern char *UTI_IPToDottedQuad(unsigned long ip); extern char *UTI_RefidToString(unsigned long ref_id);
/* Convert an IP address to string, for diagnostics */
extern char *UTI_IPToString(IPAddr *ip);
extern int UTI_StringToIP(const char *addr, IPAddr *ip);
extern unsigned long UTI_IPToRefid(IPAddr *ip);
extern void UTI_IPHostToNetwork(IPAddr *src, IPAddr *dest);
extern void UTI_IPNetworkToHost(IPAddr *src, IPAddr *dest);
extern int UTI_CompareIPs(IPAddr *a, IPAddr *b, IPAddr *mask);
extern char *UTI_TimeToLogForm(time_t t); extern char *UTI_TimeToLogForm(time_t t);
@@ -85,14 +96,11 @@ extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest);
extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest); extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
/* Like assert(0) */ extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
#if defined(LINUX) && defined(__alpha__) extern double UTI_FloatNetworkToHost(Float x);
#define CROAK(message) assert(0) /* Added JGH Feb 24 2001 FIXME */ extern Float UTI_FloatHostToNetwork(double x);
#else
extern int croak(const char *file, int line, const char *msg);
#define CROAK(message) croak(__FILE__, __LINE__, message);
#endif
#if defined (INLINE_UTILITIES) #if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static #define INLINE_STATIC inline static

Some files were not shown because too many files have changed in this diff Show More