Compare commits

...

131 Commits
1.23.1 ... 1.24

Author SHA1 Message Date
Miroslav Lichvar
fe2dbfb6cb Update NEWS 2010-02-04 13:07:19 +01:00
Miroslav Lichvar
032ac800aa Limit rate of syslog messages
Error messages caused by incoming packets need to be rate limited
to avoid filling up disk space.
2010-02-04 13:07:19 +01:00
Miroslav Lichvar
5e86eeacfb Don't reply to invalid chronyc packets 2010-02-04 13:07:19 +01:00
Miroslav Lichvar
75b7d33fb7 Update list of commands not using authentication in documentation 2010-02-04 13:07:19 +01:00
Miroslav Lichvar
a6e532442b Initialize local_ntp_tx in ntp_core
This fixes another valgrind error.
2010-02-04 12:42:48 +01:00
Miroslav Lichvar
a123a12f59 Allow to set only permission bits with perm option 2010-01-29 09:50:51 +01:00
Miroslav Lichvar
f261251a9b Add perm option to SHM driver 2010-01-28 10:10:16 +01:00
Miroslav Lichvar
a0e1154bfb Add common refclock driver option parsing 2010-01-28 10:10:16 +01:00
Miroslav Lichvar
e261278a5c Add lock option for PPS refclocks 2010-01-28 10:10:13 +01:00
Miroslav Lichvar
dbb550e6db Don't start chronyd with unrecognized command line options 2010-01-27 13:53:49 +01:00
Hattink, Tjalling (FINT)
27a9b0e7b1 Fix scheduler to allow stepping clock from timeout handler 2010-01-26 17:20:08 +01:00
Miroslav Lichvar
8a00758cf5 Add makestep directive 2010-01-25 15:51:15 +01:00
Miroslav Lichvar
15e154c09d Handle immediate step in local module instead of system driver
This fixes the problem where scheduler wasn't notified about performed
steps and it also makes the command available on all supported systems.
2010-01-25 15:51:15 +01:00
Miroslav Lichvar
52d0c9a057 Limit timeout for end of slew to avoid overflow 2010-01-25 15:50:45 +01:00
Miroslav Lichvar
4593471ad5 Don't require _bigadj kernel symbol in NetBSD driver 2010-01-13 14:40:13 +01:00
Miroslav Lichvar
a3288d4284 Print only printable characters from refid 2010-01-13 14:00:12 +01:00
Miroslav Lichvar
22f0da4da6 Fix name resolving on NetBSD 2010-01-12 18:28:04 +01:00
Miroslav Lichvar
baa977a3ed Increase buffers used to print IPv6 addresses 2010-01-12 18:05:41 +01:00
Miroslav Lichvar
b4b2491015 Return 0 from DNS_IPAddress2Name when name was truncated 2010-01-12 17:58:03 +01:00
Miroslav Lichvar
902ed3c694 Write banner to tracking log when not synchronized 2010-01-12 16:59:11 +01:00
Bill Unruh
4a9205b341 Log warning when changing file ownership fails 2009-12-20 12:29:24 +01:00
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
102 changed files with 8822 additions and 3309 deletions

30
COPYING
View File

@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -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
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU 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.
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
modification follow.
GNU GENERAL PUBLIC LICENSE
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
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -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
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -278,8 +278,8 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
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
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.
<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
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
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

22
INSTALL
View File

@@ -32,13 +32,17 @@ for Bourne-family shells, or
for C-family shells.
If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, the files `options.h' and `Makefile' will
be generated.
will be shown. Otherwise, `Makefile' will be generated.
By default, chronyc will be built to make use of the readline library. If you
don't want this, specify the --disable-readline flag to configure. If you have
readline and/or ncurses installed in a non-standard location, please refer to
the chrony.txt file for information.
If editline or readline library is available, chronyc will be built
with line editing support. If you don't want this, specify the
--disable-readline flag to configure. Please refer to the chrony.txt
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
@@ -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
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
(/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
/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
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
# 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
INSTALL_PREFIX=@INSTALL_PREFIX@
SYSCONFDIR=@SYSCONFDIR@
BINDIR=@BINDIR@
SBINDIR=@SBINDIR@
MANDIR=@MANDIR@
INFODIR=@INFODIR@
DOCDIR=@DOCDIR@
CC = @CC@
CCWARNFLAGS = @CCWARNFLAGS@
OPTFLAGS = @CFLAGS@ @EXTRA_DEFS@
OPTFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@ @SYSDEFS@ @EXTRA_DEFS@
DESTDIR=
@@ -41,25 +45,25 @@ OBJS = util.o sched.o regress.o local.o \
logging.o conf.o cmdmon.o md5.o keys.o \
nameserv.o acquire.o manual.o addrfilt.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@
CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \
pktlength.o
pktlength.o util.o
SRCS = $(patsubst %.o,%.c,$(OBJS))
EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS))
CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS))
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
EXTRA_LIBS=@EXTRA_LIBS@
EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@
DEFS=@SYSDEFS@
CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
# Until we have a main procedure we can link, just build object files
@@ -68,13 +72,16 @@ CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
all : chronyd chronyc
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)
$(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
$(CC) $(CFLAGS) $(DEFS) @READLINE_COMPILE@ -c $<
$(CC) $(CFLAGS) $(CPPFLAGS) @READLINE_COMPILE@ -c $<
.depend :
gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend
@@ -88,45 +95,47 @@ clean :
version.h : version.txt
./mkversion
getdate.c : ;
getdate :
bison -o getdate.c getdate.y
# For install, don't use the install command, because its switches
# seem to vary between systems.
install: chronyd chronyc
[ -d $(DESTDIR)$(INSTALL_PREFIX) ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)
[ -d $(DESTDIR)$(INSTALL_PREFIX)/sbin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/sbin
[ -d $(DESTDIR)$(INSTALL_PREFIX)/bin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/bin
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc
[ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR)
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony
if [ -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ; fi
if [ -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ; fi
cp chronyd $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd
chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd
cp chronyc $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc
chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc
cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
cp COPYING $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING
cp README $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi
if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi
cp chronyd $(DESTDIR)$(SBINDIR)/chronyd
chmod 755 $(DESTDIR)$(SBINDIR)/chronyd
cp chronyc $(DESTDIR)$(BINDIR)/chronyc
chmod 755 $(DESTDIR)$(BINDIR)/chronyc
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
cp COPYING $(DESTDIR)$(DOCDIR)/COPYING
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING
cp README $(DESTDIR)$(DOCDIR)/README
chmod 644 $(DESTDIR)$(DOCDIR)/README
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
chmod 444 $(DESTDIR)$(MANDIR)/man1/chronyc.1
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1
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
chmod 444 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5
chmod 644 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5
%.o : %.c
$(CC) $(CFLAGS) $(DEFS) -c $<
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
%.s : %.c
$(CC) $(CFLAGS) $(DEFS) -S $<
$(CC) $(CFLAGS) $(CPPFLAGS) -S $<
main.o logging.o client.o : version.h
@@ -134,17 +143,14 @@ main.o logging.o client.o : version.h
MAKEINFO:=makeinfo
install-docs : docs
[ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc
cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chown root $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
cp chrony.html $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html
chown root $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html
chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.html
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR)
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt
cp chrony.html $(DESTDIR)$(DOCDIR)/chrony.html
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.html
[ -d $(DESTDIR)$(INFODIR) ] || mkdir -p $(DESTDIR)$(INFODIR)
cp chrony.info* $(DESTDIR)$(INFODIR)
chown root $(DESTDIR)$(INFODIR)/chrony.info*
chmod 444 $(DESTDIR)$(INFODIR)/chrony.info*
chmod 644 $(DESTDIR)$(INFODIR)/chrony.info*
docs : chrony.txt chrony.html chrony.info

37
NEWS
View File

@@ -1,3 +1,40 @@
New in version 1.24
===================
Security fixes
--------------
* Don't reply to invalid cmdmon packets (CVE-2010-0292)
* Limit client log memory size (CVE-2010-0293)
* Limit rate of syslog messages (CVE-2010-0294)
Bug fixes/Enhancements
----------------------
* Support for reference clocks (SHM, SOCK, PPS drivers)
* IPv6 support
* Linux capabilities support (to drop root privileges)
* Memory locking support on Linux
* Real-time scheduler support on Linux
* Leap second support on Linux
* Support for editline library
* Support for new Linux readonly adjtime
* NTP client support for KoD RATE
* Read kernel timestamps for received NTP packets
* Reply to NTP requests with correct address on multihomed hosts
* Retry name resolving after temporary failure
* Fix makestep command, make it available on all systems
* Add makestep directive for automatic clock stepping
* Don't require _bigadj kernel symbol on NetBSD
* Avoid blocking read in Linux RTC driver
* Support for Linux on S/390 and PowerPC
* Fix various bugs on 64-bit systems
* Fix valgrind errors and compiler warnings
* Improve configure to support common options and variables
* Improve status checking and printing in chronyc
* Return non-zero exit code on errors in chronyc
* Reduce request timeout in chronyc
* Print estimated offset in sourcestats
* Changed chronyc protocol, incompatible with older versions
New in version 1.23
===================

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
between measurements from the reference.
The reference time can be derived from either Network Time Protocol
(NTP) servers (preferred), or wristwatch-and-keyboard (via chronyc).
The reference time can be derived from Network Time Protocol (NTP)
servers, reference clocks, or wristwatch-and-keyboard (via chronyc).
The main source of information about the Network Time Protocol is
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
on computers with permanent connections too.
In addition, the Linux 2.0.x (for x >= 32), 2.2.x and 2.3.x versions
can monitor the system's real time clock performance, so the system
can maintain accurate time even across reboots.
In addition, on Linux it can monitor the system's real time clock
performance, so the system can maintain accurate time even across
reboots.
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
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.
@@ -46,9 +48,10 @@ What will chrony 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).
Real time clock support is limited to 2.0.32 onwards and to 2.2, 2.3 and
2.4 series only. PowerPC is also known to be supported.
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,
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)
@@ -69,8 +72,7 @@ How do I set it up?
The file INSTALL gives instructions. On supported systems the
compilation process should be automatic.
You will need an ANSI C compiler -- gcc is recommended. Versions
2.7.2/2.7.2.2 are known to work.
You will need an ANSI C compiler -- gcc is recommended.
The manual (in texinfo and text formats) describes how to set the
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
through the URL
http://chrony.sunsite.dk/
http://chrony.tuxfamily.org/
What can chrony not do?
=======================
Compared to the `reference' RFC1305 implementation xntpd, chronyd does
not support hardware reference clocks, leap seconds or broadcast
modes.
not support broadcast modes.
Where are new versions announced?
=================================
There is a low volume mailing list where new versions and other
important news relating to chrony is announced. You can join this list
by sending mail 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
to announce new versions 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.
These messages will be copied to chrony-users (see below). New versions
are announced also on Freshmeat (http://freshmeat.net/).
How can I get support for chrony?
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
technical list, e.g. for discussing how new features should be
implemented, exchange of information between developers etc. To
subscribe to either of these lists, send 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
chrony-dev-subscribe@sunsite.dk
chrony-dev-request@chrony.tuxfamily.org
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
find me through one of the mailing lists. It would be nice if:
Richard P. Curnow <rc@rc0.org.uk>
- 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
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 ...).
Maintainers
===========
John Hasler <john@dhh.gt.org>
Miroslav Lichvar <mlichvar@redhat.com>
Acknowledgements
================
@@ -199,6 +189,8 @@ John Hasler <john@dhh.gt.org>
sizeof(unsigned long) > 4)
Bug fix to initstepslew directive
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>
Advice on configuring for Linux on PPC
@@ -212,6 +204,13 @@ Jim Knoble <jmknoble@pobox.com>
Antti Jrvinen <costello@iki.fi>
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>
Patch to support Linux with HZ!=100
@@ -224,6 +223,9 @@ Frank Otto <sandwichmacher@web.de>
Andreas Piesk <apiesk@virbus.de>
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>
Entries in contrib directory
@@ -240,9 +242,4 @@ Doug Woodward <dougw@whistler.com>
Many other people have contributed bug reports and suggestions. I'm
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

174
acquire.c
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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)
typedef struct { unsigned long ip_addr;
typedef struct {
IPAddr ip_addr; /* Address of the server */
int sanity; /* Flag indicating whether source
looks sane or not */
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 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
initialise_io(void)
static int
prepare_socket(int family)
{
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) {
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
number it gets */
} else {
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
union sockaddr_in46 my_addr;
memset(&my_addr, 0, sizeof (my_addr));
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));
/* 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
finalise_io(void)
{
if (sock_fd >= 0) {
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd4);
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;
}
@@ -195,10 +249,12 @@ probe_source(SourceRecord *src)
NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked;
double local_time_err;
struct sockaddr_in his_addr;
union sockaddr_in46 his_addr;
int sock_fd;
socklen_t addrlen;
#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
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
@@ -219,18 +275,39 @@ probe_source(SourceRecord *src)
pkt.receive_ts.lo = 0; /* Set to 0 */
/* And do transmission */
his_addr.sin_addr.s_addr = htonl(src->ip_addr);
his_addr.sin_port = htons(123); /* Fixed for now */
his_addr.sin_family = AF_INET;
memset(&his_addr, 0, sizeof (his_addr));
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);
UTI_TimevalToInt64(&cooked, &pkt.transmit_ts);
if (sendto(sock_fd, (void *) &pkt, NTP_NORMAL_PACKET_SIZE,
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",
UTI_IPToDottedQuad(src->ip_addr),
UTI_IPToString(&src->ip_addr),
strerror(errno));
}
@@ -253,7 +330,7 @@ transmit_timeout(void *x)
src->timer_running = 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
if (src->n_dead_probes < MAX_DEAD_PROBES) {
@@ -357,14 +434,14 @@ read_from_socket(void *anything)
{
int status;
ReceiveBuffer msg;
struct sockaddr_in his_addr;
union sockaddr_in46 his_addr;
int sock_fd;
socklen_t his_addr_len;
int flags;
int message_length;
unsigned long remote_ip;
IPAddr remote_ip;
int i, ok;
struct timeval now;
double local_time_err;
SourceRecord *src;
flags = 0;
@@ -372,26 +449,41 @@ read_from_socket(void *anything)
his_addr_len = sizeof(his_addr);
/* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err);
SCH_GetFileReadyTime(&now);
sock_fd = (long)anything;
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) {
LOG(LOGS_WARN, LOGF_Acquire, "Error reading from socket, %s", strerror(errno));
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
printf("Got message from %08lx\n", remote_ip);
printf("Got message from %s\n", UTI_IPToString(&remote_ip));
#endif
/* Find matching host */
ok = 0;
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;
break;
}
@@ -418,7 +510,7 @@ read_from_socket(void *anything)
(src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources;
#if 0
printf("Source %08lx completed\n", src->ip_addr);
printf("Source %s completed\n", UTI_IPToString(&src->ip_addr));
#endif
if (n_completed_sources == n_sources) {
wind_up_acquisition();
@@ -440,7 +532,7 @@ start_next_source(void)
{
probe_source(sources + n_started_sources);
#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
n_started_sources++;
@@ -552,10 +644,10 @@ process_measurements(void)
for (i=0; i<2*n_sane_sources; i++) {
#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].index,
sources[eps[i].index].ip_addr,
UTI_IPToString(&sources[eps[i].index].ip_addr),
eps[i].offset);
#endif
@@ -655,10 +747,10 @@ start_source_timeout_handler(void *not_used)
/* ================================================== */
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_anything = anything;
@@ -670,14 +762,18 @@ ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after
n_sources = 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].n_samples = 0;
sources[i].n_total_samples = 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_next_source();

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#define GOT_ACQUIRE_H
#include "addressing.h"
typedef struct ACQ_SourceRecord *ACQ_Source;
extern void ACQ_Initialise(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);
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
* 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
#define GOT_ADDRESSING_H
/* This type is used to represent an IPv4 address and port
number. Both parts are in HOST order, NOT network order. */
#include "sysincl.h"
/* This type is used to represent an IPv4 address or IPv6 address.
All parts are in HOST order, NOT network order. */
#define IPADDR_UNSPEC 0
#define IPADDR_INET4 1
#define IPADDR_INET6 2
typedef struct {
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;
} NTP_Remote_Address;
#if 0
unsigned long NTP_IP_Address;
#endif
#endif /* GOT_ADDRESSING_H */

View File

@@ -7,6 +7,7 @@
**********************************************************************
* 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
* 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
* 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;
struct ADF_AuthTableInst {
TableNode base;
TableNode base4; /* IPv4 node */
TableNode base6; /* IPv6 node */
};
/* ================================================== */
inline static unsigned long
get_subnet(unsigned long addr)
static void
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
get_residual(unsigned long addr)
inline static uint32_t
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);
/* Default is that nothing is allowed */
result->base.state = DENY;
result->base.extended = NULL;
result->base4.state = DENY;
result->base4.extended = NULL;
result->base6.state = DENY;
result->base6.extended = NULL;
return result;
}
@@ -135,22 +150,22 @@ open_node(TableNode *node)
static ADF_Status
set_subnet(TableNode *start_node,
unsigned long ip,
uint32_t *ip,
int ip_len,
int subnet_bits,
State new_state,
int delete_children)
{
int bits_to_go;
unsigned long residual;
unsigned long subnet;
int bits_to_go, bits_consumed;
uint32_t subnet;
TableNode *node;
bits_consumed = 0;
bits_to_go = subnet_bits;
residual = ip;
node = start_node;
if ((subnet_bits < 0) ||
(subnet_bits > 32)) {
(subnet_bits > 32 * ip_len)) {
return ADF_BADSUBNET;
@@ -159,13 +174,13 @@ set_subnet(TableNode *start_node,
if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
bits_consumed += NBITS;
}
if (delete_children) {
@@ -178,18 +193,18 @@ set_subnet(TableNode *start_node,
TableNode *this_node;
while (bits_to_go >= NBITS) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
open_node(node);
}
node = &(node->extended[subnet]);
bits_to_go -= NBITS;
bits_consumed += NBITS;
}
/* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go);
subnet = get_subnet(residual);
subnet = get_subnet(ip, bits_consumed);
if (!(node->extended)) {
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_Allow(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_AllowAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_Deny(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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_DenyAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
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
ADF_DestroyTable(ADF_AuthTable table)
{
close_node(&(table->base));
close_node(&table->base4);
close_node(&table->base6);
Free(table);
}
/* ================================================== */
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 finished = 0;
TableNode *node;
State state=DENY;
node = start_node;
residual = ip;
do {
if (node->state != AS_PARENT) {
state = node->state;
}
if (node->extended) {
subnet = get_subnet(residual);
residual = get_residual(residual);
subnet = get_subnet(ip, bits_consumed);
node = &(node->extended[subnet]);
bits_consumed += NBITS;
} else {
/* Make decision on this node */
finished = 1;
@@ -306,38 +351,63 @@ check_ip_in_node(TableNode *start_node, unsigned long ip)
int
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
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;
TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' ');
printf("%d.%d.%d.%d/%d : %s\n",
((addr >> 24) & 255),
((addr >> 16) & 255),
((addr >> 8) & 255),
((addr ) & 255),
if (ip_len == 1)
printf("%d.%d.%d.%d",
((addr[0] >> 24) & 255),
((addr[0] >> 16) & 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,
(node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent");
if (node->extended) {
for (i=0; i<16; i++) {
sub_node = &((*(node->extended))[i]);
new_addr = addr | ((unsigned long) i << shift);
print_node(sub_node, new_addr, shift - 4, subnet_bits + 4);
sub_node = &(node->extended[i]);
new_addr[0] = addr[0];
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;
@@ -346,11 +416,15 @@ static void print_node(TableNode *node, unsigned long addr, int shift, int subne
static void print_table(ADF_AuthTable table)
{
unsigned long addr = 0;
int shift = 28;
int subnet_bits = 0;
uint32_t addr[4];
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;
}
@@ -358,13 +432,41 @@ static void print_table(ADF_AuthTable table)
int main (int argc, char **argv)
{
IPAddr ip;
ADF_AuthTable table;
table = ADF_CreateTable();
ADF_Allow(table, 0x7e800000, 9);
ADF_Deny(table, 0x7ecc0000, 14);
/* ADF_Deny(table, 0x7f000001, 32); */
/* ADF_Allow(table, 0x7f000000, 8); */
ip.family = IPADDR_INET4;
ip.addr.in4 = 0x7e800000;
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);

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#define GOT_ADDRFILT_H
#include "addressing.h"
typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum {
@@ -45,25 +47,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
/* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
unsigned long ip,
IPAddr *ip,
int subnet_bits);
/* 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
the table */
extern int ADF_IsAllowed(ADF_AuthTable table,
unsigned long ip);
IPAddr *ip);
#endif /* GOT_ADDRFILT_H */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
{
if (max_destinations == n_destinations) {
/* 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].interval = interval;

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#define GOT_BROADCAST_H
#include "addressing.h"
extern void BRD_Initialise(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 */

160
candm.h
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#include "sysincl.h"
#include "addressing.h"
/* This is the default port to use for CANDM, if no alternative is
defined */
@@ -91,38 +92,55 @@
password. (This time value has long since gone by) */
#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
pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */
typedef struct {
uint32_t mask;
uint32_t address;
IPAddr mask;
IPAddr address;
int32_t EOR;
} REQ_Online;
typedef struct {
uint32_t mask;
uint32_t address;
IPAddr mask;
IPAddr address;
int32_t EOR;
} REQ_Offline;
typedef struct {
uint32_t mask;
uint32_t address;
IPAddr mask;
IPAddr address;
int32_t n_good_samples;
int32_t n_total_samples;
int32_t EOR;
} REQ_Burst;
typedef struct {
uint32_t address;
IPAddr address;
int32_t new_minpoll;
int32_t EOR;
} REQ_Modify_Minpoll;
typedef struct {
uint32_t address;
IPAddr address;
int32_t new_maxpoll;
int32_t EOR;
} REQ_Modify_Maxpoll;
@@ -133,29 +151,29 @@ typedef struct {
} REQ_Dump;
typedef struct {
uint32_t address;
int32_t new_max_delay;
IPAddr address;
Float new_max_delay;
int32_t EOR;
} REQ_Modify_Maxdelay;
typedef struct {
uint32_t address;
int32_t new_max_delay_ratio;
IPAddr address;
Float new_max_delay_ratio;
int32_t EOR;
} REQ_Modify_Maxdelayratio;
typedef struct {
int32_t new_max_update_skew;
Float new_max_update_skew;
int32_t EOR;
} REQ_Modify_Maxupdateskew;
typedef struct {
struct timeval ts;
Timeval ts;
int32_t EOR;
} REQ_Logon;
typedef struct {
struct timeval ts;
Timeval ts;
int32_t EOR;
} REQ_Settime;
@@ -184,32 +202,35 @@ typedef struct {
} REQ_Rekey;
typedef struct {
uint32_t ip;
IPAddr ip;
int32_t subnet_bits;
int32_t EOR;
} REQ_Allow_Deny;
typedef struct {
uint32_t ip;
IPAddr ip;
int32_t EOR;
} REQ_Ac_Check;
/* Flags used in NTP source requests */
#define REQ_ADDSRC_ONLINE 0x1
#define REQ_ADDSRC_AUTOOFFLINE 0x2
typedef struct {
uint32_t ip_addr;
IPAddr ip_addr;
uint32_t port;
int32_t minpoll;
int32_t maxpoll;
int32_t presend_minpoll;
int32_t online;
int32_t auto_offline;
uint32_t authkey;
int32_t max_delay;
int32_t max_delay_ratio;
Float max_delay;
Float max_delay_ratio;
uint32_t flags;
int32_t EOR;
} REQ_NTP_Source;
typedef struct {
uint32_t ip_addr;
IPAddr ip_addr;
int32_t EOR;
} REQ_Del_Source;
@@ -218,7 +239,7 @@ typedef struct {
} REQ_WriteRtc;
typedef struct {
int32_t dfreq;
Float dfreq;
int32_t EOR;
} REQ_Dfreq;
@@ -250,7 +271,7 @@ typedef struct {
} REQ_CycleLogs;
typedef struct {
uint32_t ip;
IPAddr ip;
uint32_t bits_specd;
} REQ_SubnetsAccessed_Subnet;
@@ -263,11 +284,11 @@ typedef struct {
/* This is based on the response size rather than the
request size */
#define MAX_CLIENT_ACCESSES 16
#define MAX_CLIENT_ACCESSES 8
typedef struct {
uint32_t n_clients;
uint32_t client_ips[MAX_CLIENT_ACCESSES];
IPAddr client_ips[MAX_CLIENT_ACCESSES];
} REQ_ClientAccesses;
typedef struct {
@@ -310,9 +331,18 @@ typedef struct {
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_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 */
@@ -419,6 +442,9 @@ typedef struct {
#define STT_BADRTCFILE 14
#define STT_INACTIVE 15
#define STT_BADSAMPLE 16
#define STT_INVALIDAF 17
#define STT_BADPKTVERSION 18
#define STT_BADPKTLENGTH 19
typedef struct {
int32_t EOR;
@@ -440,67 +466,65 @@ typedef struct {
#define RPY_SD_ST_OTHER 4
typedef struct {
uint32_t ip_addr;
IPAddr ip_addr;
uint16_t poll;
uint16_t stratum;
uint16_t state;
uint16_t mode;
uint32_t since_sample;
int32_t orig_latest_meas;
int32_t latest_meas;
uint32_t latest_meas_err;
int32_t est_offset;
uint32_t est_offset_err;
int32_t resid_freq;
uint32_t resid_skew;
Float orig_latest_meas;
Float latest_meas;
Float latest_meas_err;
int32_t EOR;
} RPY_Source_Data;
typedef struct {
uint32_t ref_id;
IPAddr ip_addr;
uint32_t stratum;
uint32_t ref_time_s;
uint32_t ref_time_us;
uint32_t current_correction_s;
uint32_t current_correction_us;
int32_t freq_ppm;
int32_t resid_freq_ppm;
int32_t skew_ppm;
int32_t root_delay;
int32_t root_dispersion;
Timeval ref_time;
Float current_correction;
Float freq_ppm;
Float resid_freq_ppm;
Float skew_ppm;
Float root_delay;
Float root_dispersion;
int32_t EOR;
} RPY_Tracking;
typedef struct {
uint32_t ip_addr;
uint32_t ref_id;
IPAddr ip_addr;
uint32_t n_samples;
uint32_t n_runs;
uint32_t span_seconds;
uint32_t sd_us;
int32_t resid_freq_ppm;
int32_t skew_ppm;
Float sd;
Float resid_freq_ppm;
Float skew_ppm;
Float est_offset;
Float est_offset_err;
int32_t EOR;
} RPY_Sourcestats;
typedef struct {
uint32_t ref_time;
Timeval ref_time;
uint16_t n_samples;
uint16_t n_runs;
uint32_t span_seconds;
int32_t rtc_seconds_fast;
int32_t rtc_gain_rate_ppm;
Float rtc_seconds_fast;
Float rtc_gain_rate_ppm;
int32_t EOR;
} RPY_Rtc;
typedef struct {
uint32_t centiseconds;
int32_t dfreq_ppm;
int32_t new_afreq_ppm;
Float dfreq_ppm;
Float new_afreq_ppm;
int32_t EOR;
} RPY_ManualTimestamp;
typedef struct {
uint32_t ip;
IPAddr ip;
uint32_t bits_specd;
uint32_t bitmap[8];
} RPY_SubnetsAccessed_Subnet;
@@ -511,7 +535,7 @@ typedef struct {
} RPY_SubnetsAccessed;
typedef struct {
uint32_t ip;
IPAddr ip;
uint32_t client_hits;
uint32_t peer_hits;
uint32_t cmd_hits_auth;
@@ -536,10 +560,10 @@ typedef struct {
#define MAX_MANUAL_LIST_SAMPLES 32
typedef struct {
uint32_t when;
int32_t slewed_offset;
int32_t orig_offset;
int32_t residual;
Timeval when;
Float slewed_offset;
Float orig_offset;
Float residual;
} RPY_ManualListSample;
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
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.
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
\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
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.
.SH "SEE ALSO"
.BR chronyc(1),
.BR chrony(1)
.I http://chrony.sunsite.dk/
.I http://chrony.tuxfamily.org/
.SH AUTHOR
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
chrony.conf \- chronyd configuration file
@@ -37,9 +37,9 @@ useful configuration file would look something like
.SH "SEE ALSO"
.BR chrony(1),
.BR chronyc(1),
.BR chronyd(1)
.BR chronyd(8)
.I http://chrony.sunsite.dk/
.I http://chrony.tuxfamily.org/
.SH AUTHOR
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
Author: 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
2k chrony.lsm
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
@subsection Getting the software
Links on @uref{http://chrony.sunsite.dk/download.php, the
chrony home page} describe how to obtain the software.
Links on @uref{http://chrony.tuxfamily.org, the chrony home page}
describe how to obtain the software.
@node Platforms
@@ -125,8 +125,9 @@ different quirks in its behaviour.
The software is known to work in the following environments:
@itemize @bullet
@item Linux/i386 and Linux/ppc. The software is known to work on Linux 2.0.x,
2.2.x and 2.4.x. Prior to 2.0.31, the real time clock can't be used.
@item Linux on i386, x86_64 and PowerPC architectures. The software is known
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 BSD/386
@@ -203,18 +204,10 @@ integrated into @code{chronyd}.
Things @code{xntpd} can do that @code{chronyd} can't:
@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
@code{xntpd} supports effectively all of RFC1305, including broadcast /
multicast clients, leap seconds, and extra encryption schemes for
authenticating data packets.
multicast clients and extra encryption schemes for authenticating
data packets.
@item
@code{xntpd} has been ported to more types of computer / operating
@@ -276,29 +269,19 @@ version 2, reproduced in @xref{GPL}.
@node Bug reporting
@section Bug reporting and suggestions
If you think you've found a bug in chrony, or have a suggestion, please let me
know. My primary current email address is @email{rc@@rc0.org.uk}. If that
fails, you could try finding me through one of the chrony mailing lists, or by
looking up my name on a search engine.
If you think you've found a bug in chrony, or have a suggestion, please let us
know. You can join chrony users mailing list by sending a message with the
subject subscribe to @email{chrony-users-request@@chrony.tuxfamily.org}. Only
subscribers can post to the list.
I can't promise a timescale to fix a bug; it depends a lot on the how complex
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.
When you are reporting a bug, please send us all the information you can.
Unfortunately, chrony has proven to be one of those programs where it is very
difficult to reproduce bugs in a different environment. So 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
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
patch to fix it, I will be very grateful!
Of course, if you can debug the problem yourself and send us a source code
patch to fix it, we will be very grateful!
@c }}}
@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
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
@item Porting to other Unices
@@ -331,7 +314,7 @@ setsid() etc with so that chronyd can be automatically started in the system
bootstrap.
@end enumerate
@item Hardware clock support
@item More drivers for reference clock support
@item Automation of the trimrtc and writertc mechanisms
@@ -394,13 +377,16 @@ setenv CFLAGS -O
for C-family shells.
If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, the files @file{options.h} and
@file{Makefile} will be generated.
will be shown. Otherwise, @file{Makefile} will be generated.
By default, chronyc will be built to make use of the readline library. If you
don't want this, specify the --disable-readline flag to configure. If you have
readline and/or ncurses installed in a non-standard location, please refer to
@pxref{readline support} for information.
If editline or readline library is available, chronyc will be built with line
editing support. If you don't want this, specify the --disable-readline flag
to configure. Please refer to @pxref{line editing support} for more 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
@@ -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
@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
@file{/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
@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/share/info/dir}. So
the typical command line would be
@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
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.
@c }}}
@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
@end menu
@c {{{ readline support
@node readline support
@section Support for the readline library
By default, chronyc is built to make use of the readline library. This allows
you to use the cursor keys to replay and edit old commands. If you don't want
to use readline (in which case chronyc will use a minimal command line
interface), invoke configure like this:
@c {{{ line editing support
@node line editing support
@section Support for line editing libraries
Chronyc can be built with support for line editing, this allows you to use the
cursor keys to replay and edit old commands. Two libraries are supported which
provide such functionality, editline and GNU readline.
Please note that readline since version 6.0 is licensed under GPLv3+ which is
incompatible with chrony's license GPLv2. You should use editline instead if
you don't want to use older readline versions.
The configure script will automatically enable the line editing support if one
of the supported libraries is available. If they are both available, the
editline library will be used.
If you don't want to use it (in which case chronyc will use a minimal command
line interface), invoke configure like this:
@example
./configure --disable-readline other-options...
@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
@item --with-readline-includes=directory_name
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
the named directory.
is. @file{readline.h} is assumed to be in @file{editline} or @file{readline}
subdirectory of the named directory.
@item --with-readline-library=directory_name
This defines the directory containing the @file{libreadline.a} or
@file{libreadline.so} file.
This defines the directory containing the @file{libedit.a} or @file{libedit.so}
file, or @file{libreadline.a} or @file{libreadline.so} file.
@item --with-ncurses-library=directory_name
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
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
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
@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
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
accurate statistics for the difference between the real time clock and
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
This option displays @code{chronyd's} version number to the terminal and
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
On systems that support an @file{/etc/rc.local} file for starting
@@ -1174,16 +1184,22 @@ directives can occur in any order in the file.
* logchange directive:: Generate syslog messages if large offsets occur
* logdir directive:: Specify directory for logging
* mailonchange directive:: Send email if a clock correction above a threshold occurs
* makestep directive:: Step system clock if large correction is needed
* manual directive:: Allow manual entry using chronyc's settime cmd.
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
* noclientlog directive:: Prevent chronyd from gathering data about clients
* clientloglimit directive:: Set client log memory limit
* peer directive:: Specify an NTP peer
* pidfile directive:: Specify the file where chronyd's pid is written
* 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)
* 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
* 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
@c }}}
@c {{{ comments in config file
@@ -1241,18 +1257,22 @@ allow 1.2
allow 3.4.5
allow 6.7.8/22
allow 6.7.8.9/22
allow 2001:db8::/32
allow 0/0
allow ::/0
allow
@end example
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
command allows any node with an IP 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
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 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),
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
node on the entire Internet.
fifth form, the final byte is ignored). The sixth form is used for IPv6
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,
depending on the ordering of directives in the configuration file. To
@@ -1318,6 +1338,9 @@ firewalls). It is, therefore, not particularly useful. Use of the
@code{allow} and @code{deny} directives together with a network firewall is
more likely to be successful.
For each of IPv4 and IPv6 protocols, only one @code{bindaddress}
directive can be specified.
@c }}}
@c {{{ bindcmdaddress
@node bindcmdaddress directive
@@ -1342,6 +1365,9 @@ interfaces. It is, therefore, not particularly useful. Use of the
@code{cmdallow} and @code{cmddeny} directives together with a network firewall
is more likely to be successful.
For each of IPv4 and IPv6 protocols, only one @code{bindcmdaddress}
directive can be specified.
@c }}}
@c {{{ broadcast directive
@node broadcast directive
@@ -1356,6 +1382,7 @@ The syntax is as follows
@example
broadcast 30 192.168.1.255
broadcast 60 192.168.2.255 12123
broadcast 60 ff02::101
@end example
In the first example, the destination port defaults to 123/udp (the normal NTP
@@ -1525,8 +1552,9 @@ An example of the command is
dumpdir /var/log/chrony
@end example
A source whose IP address is 1.2.3.4 would have its measurement
history saved in the file @file{/var/log/chrony/1.2.3.4.dat}.
A source whose reference id (the IP address for IPv4 sources) is
1.2.3.4 would have its measurement history saved in the file
@file{/var/log/chrony/1.2.3.4.dat}.
@c }}}
@c {{{ dumponexit
@node dumponexit directive
@@ -1729,6 +1757,10 @@ rate, and any slews made, to a file called tracking.log.
@item rtc
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
The files are written to the directory specified by the logdir
@@ -1745,6 +1777,7 @@ log measurements statistics tracking
* statistics log:: The format of the statistics log
* tracking log:: The format of the tracking log
* RTC log:: The format of the RTC log
* refclocks log:: The format of the refclocks log
@end menu
@c }}}
@c {{{ measurements.log
@@ -1771,8 +1804,8 @@ expressed in UTC, not the local time zone.
@item
IP address of server/peer from which measurement comes [158.152.1.76]
@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
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, @code{?} means the remote computer is not currently
synchronised.) [N]
@item
@@ -1958,6 +1991,47 @@ The measurement interval used prior to the measurement being made (in
seconds). [120]
@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
meanings of the columns.
@c }}}
@@ -2012,6 +2086,32 @@ mailonchange root@@localhost 0.5
This would send a mail message to root if a change of more than 0.5
seconds were applied to the system clock.
@c }}}
@c {{{ makestep
@node makestep directive
@subsection makestep
Normally chronyd will cause the system to gradually correct any time
offset, by slowing down or speeding up the clock as required. In
certain situations, the system clock may be so far adrift that this
slewing process would take a very long time to correct the system clock.
This directive forces @code{chronyd} to step system clock if the
adjustment is larger than a threshold value, but only if there were no
more clock updates since @code{chronyd} was started than a specified
limit (a negative value can be used to disable the limit).
This is particularly useful when using reference clocks, because the
@code{initstepslew} directive (@pxref{initstepslew directive}) works
only with NTP sources.
An example of the use of this directive is
@example
makestep 1000 10
@end example
This would step system clock if the adjustment is larger than 1000
seconds, but only in the first ten clock updates.
@c }}}
@c {{{ manual
@node manual directive
@subsection manual
@@ -2066,6 +2166,21 @@ This directive, which takes no arguments, specifies that client accesses
are not to be logged. Normally they are logged, allowing statistics to
be reported using the @code{clients} command in @code{chronyc}.
@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
@node peer directive
@subsection peer
@@ -2101,6 +2216,101 @@ port 11123
This would change the NTP port served by chronyd on the computer to
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. Driver option
@code{:clear} can be appended to the path to use clear events instead.
PPS refclock needs another source (NTP or non-PPS refclock) or local
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 for receiving timestamps, usually
0, 1, 2 or 3. For example:
@example
refclock SHM 1 poll 3 refid GPS1
@end example
A driver option in form @code{:perm=NNN} can be appended to the
segment number to create the segment with permissions other than the
default @code{0600}.
Software that can be used as a source of reference time includes
@code{gpsd} and @code{shmpps}.
@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 lock
This option can be used to lock a PPS refclock to another refclock
whose reference id is specified by this option. In this mode received
pulses are aligned directly to unfiltered samples from the refclock.
By default, pulses are aligned to local clock, but only when it is
well synchronised.
@item offset
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 {{{ rtcdevice
@node rtcdevice directive
@@ -2174,6 +2384,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
specifying the @code{-u} switch to the Linux @file{/sbin/clock} program.
@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
@node server directive
@subsection server
@@ -2183,9 +2424,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.
The @code{server} directive is immediately followed by either the name
of the server, or its IP address in dotted-quad notation. The server
command also supports a number of subfields (which may be defined in any
order):
of the server, or its IP address. The server command also supports a
number of subfields (which may be defined in any order):
@table @code
@item port
@@ -2341,6 +2581,12 @@ This option allows the user to specify the UDP port number which the
target @code{chronyd} is using for its command & monitoring connections.
This defaults to the compiled-in default; there would rarely be a need
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
@c }}}
@c {{{ SS:Security with chronyc
@@ -2377,6 +2623,9 @@ Only the following commands can be used @emph{without} providing a
password:
@itemize @bullet
@item @code{activity}
@item @code{clients}
@item @code{dns}
@item @code{exit}
@item @code{help}
@item @code{password}
@@ -2416,6 +2665,7 @@ interface.
* delete command:: Remove an NTP server or peer
* deny 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
* exit command:: Exit from chronyc
* help command:: Generate help summary
@@ -2452,6 +2702,7 @@ follows:
@example
accheck a.b.c
accheck 1.2.3.4
accheck 2001:db8::1
@end example
This command can be used to examine the effect of a series of
@@ -2526,6 +2777,9 @@ allow 1.2
allow 3.4.5
allow 6.7.8/22
allow 6.7.8.9/22
allow 2001:db8:789a::/48
allow 0/0
allow ::/0
allow
@end example
@@ -2542,7 +2796,7 @@ directive in the configuration file (@pxref{allow directive}).
@node burst command
@subsubsection burst
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
revert to the previous state for each source. This might be either
online, if the source was being periodically measured in the normal way,
@@ -2554,6 +2808,7 @@ The syntax of the burst command is as follows
@example
burst <n-good-measurements>/<max-measurements> [<mask>/<masked-address>]
burst <n-good-measurements>/<max-measurements> [<masked-address>/<masked-bits>]
@end example
The mask and masked-address arguments are optional, in which case
@@ -2575,18 +2830,21 @@ attempt to make, even if the required number of good measurements has
not been obtained.
@item mask
This is a dotted quad argument (e.g. @code{255.255.255.0}) with which
the IP address of each of @code{chronyd}'s sources is to be masked.
This is an IP address with which the IP address of each of @code{chronyd}'s
sources is to be masked.
@item masked-address
This is a dotted quad argument (e.g. @code{1.2.3.0}). If the masked IP
address of a source matches this value then the burst command is applied
to that source.
This is an IP address. If the masked IP address of a source matches this value
then the burst command is applied 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
If no mask or masked address arguments are provided, the default is
@code{0.0.0.0} and @code{0.0.0.0} respectively, which will match every
source.
If no mask or masked address arguments are provided, every source will
be matched.
An example of the two-argument form of the command is
@@ -2598,15 +2856,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
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
burst 2/10 255.255.0.0/1.2.0.0
burst 2/10 2001:db8:789a::/48
@end example
In this 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
are arbitrary.
In the first case, the two out of ten sampling will only be applied to
sources whose IPv4 addresses are of the form @code{1.2.x.y}, where x and y
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 {{{ clients
@node clients command
@@ -2671,6 +2931,7 @@ Examples of use are as follows:
@example
cmdaccheck a.b.c
cmdaccheck 1.2.3.4
cmdaccheck 2001:db8::1
@end example
@c }}}
@c {{{ cmdallow
@@ -2733,6 +2994,7 @@ The syntax is illustrated in the examples below.
@example
delete foo.bar.com
delete 1.2.3.4
delete 2001:db8::1
@end example
There is one parameter, the name or IP address of the server or peer to
@@ -2752,6 +3014,9 @@ deny 1.2
deny 3.4.5
deny 6.7.8/22
deny 6.7.8.9/22
deny 2001:db8:789a::/48
deny 0/0
deny ::/0
deny
@end example
@c }}}
@@ -2761,6 +3026,32 @@ deny
The effect of the allow command is identical to the @code{deny all}
directive in the configuration file (@pxref{deny directive}).
@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
@node dump command
@subsubsection dump
@@ -2824,8 +3115,9 @@ BE WARNED - certain software will be seriously affected by such jumps to
the system time. (That is the reason why chronyd uses slewing
normally.)
The @code{makestep} command is currently only available on the Linux
version of chrony.
The @code{makestep} directive in the configuration file can be used
to step the clock automatically when the adjustment is larger than a
specified threshold, see @ref{makestep directive}.
@c }}}
@c {{{ manual
@node manual command
@@ -2904,12 +3196,14 @@ The following examples illustrate the syntax
@example
maxdelay foo.bar.com 0.3
maxdelay 1.2.3.4 0.0015
maxdelay 2001:db8::1 0.0015
@end example
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
example sets the maximum network delay for a measurement to the host
with IP address @code{1.2.3.4} to 1.5 milliseconds.
and third examples set the maximum network delay for a measurement to
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
discarded.)
@@ -2927,13 +3221,15 @@ The following examples illustrate the syntax
@example
maxdelayratio foo.bar.com 1.5
maxdelayratio 1.2.3.4 2.0
maxdelayratio 2001:db8::1 2.0
@end example
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
amongst the previous measurements that have been retained. The second
example sets the maximum network delay for a measurement to the host
with IP address @code{1.2.3.4} to be double the retained minimum.
and third examples set the maximum network delay for a measurement to
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
will be discarded.
@@ -2952,7 +3248,7 @@ The syntax is as follows
maxpoll <host> <new-maxpoll>
@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
the number of seconds between polls (e.g. specify 6 for 64 second
sampling).
@@ -2989,7 +3285,7 @@ The syntax is as follows
minpoll <host> <new-minpoll>
@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
the number of seconds between polls (e.g. specify 6 for 64 second
sampling).
@@ -3056,24 +3352,29 @@ the @code{offline} command being used, @code{chronyd} would assume that the
source had failed and would attempt to pick another synchronisation
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
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
offline
offline 255.255.255.0/1.2.3.0
offline 2001:db8:789a::/48
@end example
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
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
@example
offline 0.0.0.0/0.0.0.0
offline ::/0
@end example
@c }}}
@c {{{ online
@@ -3240,8 +3541,7 @@ The columns are as follows:
@item M
This indicates the mode of the source. @code{^} means a server,
@code{=} means a peer and @code{#} indicates a locally connected
reference clock@footnote{In the current version this will never be
shown, because @code{chronyd} has no support for reference clocks yet.}.
reference clock.
@item S
This column indicates the state of the sources. @code{*} indicates the
@@ -3254,7 +3554,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.
@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
This shows the stratum of the source, as reported in its most recently
@@ -3279,7 +3580,8 @@ source. This is normally in seconds. The letters @code{m}, @code{h},
@item Last sample
This column shows the offset between the local clock and the source at
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}
(indicating seconds). The number to the left of the square brackets
shows the original measurement, adjusted to allow for any slews applied
@@ -3307,9 +3609,9 @@ An example report is
@example
@group
210 Number of sources = 1
Name/IP Address NP NR Span Frequency Freq Skew Std Dev
========================================================================
abc.def.ghi 11 5 46m -0.001 0.045 25us
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
===============================================================================
abc.def.ghi 11 5 46m -0.001 0.045 1us 25us
@end group
@end example
@@ -3317,8 +3619,8 @@ The columns are as follows
@table @code
@item Name/IP Address
This is the name or dotted-quad IP address of the NTP server (or peer)
to which the rest of the line relates.
This is the name or IP address of the NTP server (or peer) or refid of
the refclock to which the rest of the line relates.
@item NP
This is the number of sample points currently being retained for the
@@ -3347,6 +3649,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
million).
@item Offset
This is the estimated offset of the source.
@item Std Dev
This is the estimated sample standard deviation.
@@ -3362,7 +3667,7 @@ performance. An example of the output is shown below.
Reference ID : 1.2.3.4 (a.b.c)
Stratum : 3
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
Residual freq : 0.004 ppm
Skew : 0.154 ppm
@@ -3374,7 +3679,7 @@ The fields are explained as follows.
@table @code
@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}
it means the computer is not synchronised to any external source and
that you have the `local' mode operating (via the @code{local} command
@@ -3640,8 +3945,8 @@ the system clock is periodically reset to the real-time clock.
@center GNU GENERAL PUBLIC LICENSE
@center Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -3654,7 +3959,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU 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.
When we speak of free software, we are referring to freedom, not
@@ -3918,7 +4223,7 @@ POSSIBILITY OF SUCH DAMAGES.
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
possible use to the public, the best way to achieve this is to make it
@@ -3930,7 +4235,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.
<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
it under the terms of the GNU General Public License as published by
@@ -3942,16 +4247,16 @@ the "copyright" line and a pointer to where the full notice is found.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -3974,7 +4279,7 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
@c }}}
@contents

View File

@@ -39,6 +39,7 @@ struct timex {
#define ADJ_STATUS 0x0010 /* clock status */
#define ADJ_TICK 0x4000 /* tick value */
#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) */

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
chronyc \- command-line interface for chronyd
@@ -31,22 +31,29 @@ specify port-number
.TP
\fB\-n\fR
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
interactively.
.SH VERSION
1.17
1.24
.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"
.BR chronyd(8),
.BR chrony(1)
.I http://chrony.sunsite.dk/
.I http://chrony.tuxfamily.org/
.SH AUTHOR
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
chronyd \- chrony background daemon
@@ -35,6 +35,15 @@ Information messages and warnings will be logged to syslog.
.SH OPTIONS
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
.B \-d
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
computer was on.
.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
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
\fI/etc/chrony.conf\fR
.SH VERSION
Version 1.17
Version 1.24
.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"
\fBchronyd\fR is documented in detail in the documentation supplied with the

1276
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) 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
@@ -19,7 +20,7 @@
*
* 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.,
* 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 "reports.h"
#include "util.h"
#include "logging.h"
/* 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
@@ -52,7 +54,7 @@
#define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_bad;
@@ -68,8 +70,10 @@ typedef struct _Subnet {
/* ================================================== */
/* Table for the class A subnet */
static Subnet top_subnet;
/* Table for the IPv4 class A subnet */
static Subnet top_subnet4;
/* Table for IPv6 */
static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been
allocated. */
@@ -81,13 +85,46 @@ static int n_nodes = 0;
/* Number of entries for which the table has been sized. */
static int max_nodes = 0;
#define NODE_TABLE_INCREMENT 4
/* Flag indicating whether facility is turned on or not */
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
clear_subnet(Subnet *subnet)
{
@@ -117,7 +154,8 @@ clear_node(Node *node)
void
CLG_Initialise(void)
{
clear_subnet(&top_subnet);
clear_subnet(&top_subnet4);
clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) {
active = 0;
} else {
@@ -128,6 +166,9 @@ CLG_Initialise(void)
max_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
create_subnet(Subnet *parent_subnet, int the_entry)
{
parent_subnet->entry[the_entry] = (void *) MallocNew(Subnet);
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;
clear_node(new_node);
alloced += sizeof (Node);
if (n_nodes == max_nodes) {
if (nodes) {
max_nodes += NODE_TABLE_INCREMENT;
assert(max_nodes > 0);
max_nodes *= 2;
nodes = ReallocArray(Node *, max_nodes, nodes);
} else {
if (max_nodes != 0) {
CROAK("max_nodes should be 0");
}
max_nodes = NODE_TABLE_INCREMENT;
assert(max_nodes == 0);
max_nodes = 16;
nodes = MallocArray(Node *, max_nodes);
}
alloced += sizeof (Node *) * (max_nodes - n_nodes);
}
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. */
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;
unsigned long new_bits_left;
shift = 32 - NBITS;
mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
uint32_t this_subnet;
#if 0
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
this_subnet = get_subnet(addr, bits_consumed);
bits_consumed += NBITS;
if (new_bits_left > 0) {
if (bits_consumed < 32 * addr_len) {
if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached)
return NULL;
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 {
if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached)
return NULL;
create_node(subnet, 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 */
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;
unsigned long new_bits_left;
uint32_t this_subnet;
if (bits_left == 0) {
if (bits_consumed >= 32 * addr_len) {
return subnet;
} else {
shift = 32 - NBITS;
mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
this_subnet = get_subnet(addr, bits_consumed);
bits_consumed += 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]) {
return NULL;
} 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
CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
CLG_LogNTPClientAccess (IPAddr *client, time_t now)
{
uint32_t ip6[4];
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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->last_ntp_hit = now;
}
@@ -257,12 +317,28 @@ CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
/* ================================================== */
void
CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
{
uint32_t ip6[4];
Node *node;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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->last_ntp_hit = now;
}
@@ -271,12 +347,28 @@ CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
/* ================================================== */
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;
if (active) {
node = (Node *) find_subnet(&top_subnet, client, 32);
node->ip_addr = client;
switch (client->family) {
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;
switch (type) {
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;
break;
default:
CROAK("Impossible");
assert(0);
break;
}
}
@@ -298,16 +390,32 @@ CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
/* ================================================== */
CLG_Status
CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
{
Subnet *s;
uint32_t ip6[4];
unsigned long i;
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);
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) {
for (i=0; i<256; i++) {
if (s->entry[i]) {
@@ -332,15 +440,26 @@ CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
/* ================================================== */
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;
if (!active) {
return CLG_INACTIVE;
} 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) {
return CLG_EMPTYSUBNET;
} else {

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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 "reports.h"
typedef unsigned long CLG_IP_Addr;
/* Enough to hold flags for 256 hosts in a class C */
typedef uint32_t CLG_Bitmap[8];
extern void CLG_Initialise(void);
extern void CLG_Finalise(void);
extern void CLG_LogNTPClientAccess(CLG_IP_Addr client, time_t now);
extern void CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now);
extern void CLG_LogNTPClientAccess(IPAddr *client, time_t now);
extern void CLG_LogNTPPeerAccess(IPAddr *client, time_t now);
/* When logging command packets, there are several subtypes */
@@ -53,7 +51,7 @@ typedef enum {
CLG_CMD_BAD_PKT /* bad version or packet length */
} 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. */
/* TBD */
@@ -70,10 +68,10 @@ typedef enum {
known. For bits=24, flag which hosts in that subnet are known.
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
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_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'. */
extern void CLG_IterateNTPClients
(void (*fn)(CLG_IP_Addr client, void *arb),
(void (*fn)(IPAddr *client, void *arb),
void *arb,
time_t since);

625
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
* 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
#define GOT_CMDMON_H
#include "addressing.h"
extern void CAM_Initialise(void);
extern void CAM_Finalise(void);
extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
extern int CAM_CheckAccessRestriction(unsigned long ip_addr);
extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int CAM_CheckAccessRestriction(IPAddr *ip_addr);
#endif /* GOT_CMDMON_H */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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;
if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
src->ip_addr = DNS_Name2IPAddress(hostname);
if (src->ip_addr != DNS_Failed_Address) {
if (DNS_Name2IPAddress(hostname, &src->ip_addr, 1)) {
ok = 1;
}
}

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#include "srcparams.h"
#include "addressing.h"
typedef enum {
CPS_Success,
@@ -47,7 +48,7 @@ typedef enum {
} CPS_Status;
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned short port;
SourceParameters params;
} CPS_NTP_Source;

421
conf.c
View File

@@ -7,6 +7,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* 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
@@ -19,7 +20,7 @@
*
* 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.,
* 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 "ntp_sources.h"
#include "ntp_core.h"
#include "refclock.h"
#include "cmdmon.h"
#include "srcparams.h"
#include "logging.h"
@@ -52,10 +54,15 @@
#include "acquire.h"
#include "cmdparse.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 */
@@ -73,6 +80,7 @@ static void parse_peer(const char *);
static void parse_acquisitionport(const char *);
static void parse_port(const char *);
static void parse_server(const char *);
static void parse_refclock(const char *);
static void parse_local(const char *);
static void parse_manual(const char *);
static void parse_initstepslew(const char *);
@@ -83,6 +91,8 @@ static void parse_cmddeny(const char *);
static void parse_cmdport(const char *);
static void parse_rtconutc(const char *);
static void parse_noclientlog(const char *);
static void parse_clientloglimit(const char *);
static void parse_makestep(const char *);
static void parse_logchange(const char *);
static void parse_mailonchange(const char *);
static void parse_bindaddress(const char *);
@@ -92,6 +102,8 @@ static void parse_pidfile(const char *);
static void parse_broadcast(const char *);
static void parse_linux_hz(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 */
@@ -111,6 +123,7 @@ static int do_log_measurements = 0;
static int do_log_statistics = 0;
static int do_log_tracking = 0;
static int do_log_rtc = 0;
static int do_log_refclocks = 0;
static int do_dump_on_exit = 0;
static char *logdir = ".";
static char *dumpdir = ".";
@@ -126,7 +139,7 @@ static int n_init_srcs;
than this, slew instead of stepping */
static int init_slew_threshold = -1;
#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;
@@ -134,6 +147,10 @@ static int enable_manual=0;
incl. daylight saving). */
static int rtc_on_utc = 0;
/* Limit and threshold for clock stepping */
static int make_step_limit = 0;
static double make_step_threshold = 0.0;
/* Flag set if we should log to syslog when a time adjustment
exceeding the threshold is initiated */
static int do_log_change = 0;
@@ -146,13 +163,16 @@ static double mail_change_threshold = 0.0;
memory */
static int no_client_log = 0;
/* IP address (host order) for binding the NTP socket to. 0 means INADDR_ANY
will be used */
static unsigned long bind_address = 0UL;
/* Limit memory allocated for the clients log */
static unsigned long client_log_limit = 524288;
/* 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 */
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
* chronyds being started. */
@@ -168,6 +188,9 @@ static int linux_hz;
static int set_linux_freq_scale = 0;
static double linux_freq_scale;
static int sched_priority = 0;
static int lock_memory = 0;
/* ================================================== */
typedef struct {
@@ -179,6 +202,7 @@ typedef struct {
static const Command commands[] = {
{"server", 6, parse_server},
{"peer", 4, parse_peer},
{"refclock", 8, parse_refclock},
{"acquisitionport", 15, parse_acquisitionport},
{"port", 4, parse_port},
{"driftfile", 9, parse_driftfile},
@@ -200,6 +224,8 @@ static const Command commands[] = {
{"cmdport", 7, parse_cmdport},
{"rtconutc", 8, parse_rtconutc},
{"noclientlog", 11, parse_noclientlog},
{"clientloglimit", 14, parse_clientloglimit},
{"makestep", 8, parse_makestep},
{"logchange", 9, parse_logchange},
{"mailonchange", 12, parse_mailonchange},
{"bindaddress", 11, parse_bindaddress},
@@ -208,7 +234,9 @@ static const Command commands[] = {
{"pidfile", 7, parse_pidfile},
{"broadcast", 9, parse_broadcast},
{"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]));
@@ -224,7 +252,7 @@ typedef enum {
typedef struct {
NTP_Source_Type type;
unsigned long ip_addr;
IPAddr ip_addr;
unsigned short port;
SourceParameters params;
} NTP_Source;
@@ -234,12 +262,17 @@ typedef struct {
static NTP_Source ntp_sources[MAX_NTP_SOURCES];
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 {
struct _AllowDeny *next;
struct _AllowDeny *prev;
unsigned long ip;
IPAddr ip;
int subnet_bits;
int all; /* 1 to override existing more specific defns */
int allow; /* 0 for deny, 1 for allow */
@@ -365,6 +398,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
parse_server(const char *line)
{
@@ -381,6 +432,104 @@ 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, lock_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;
lock_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, "lock", 4)) {
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
break;
lock_ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
} else if (!strncasecmp(cmd, "poll", 4)) {
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;
refclock_sources[i].lock_ref_id = lock_ref_id;
n_refclock_sources++;
}
/* ================================================== */
static void
parse_some_port(const char *line, int *portvar)
{
@@ -516,6 +665,9 @@ parse_log(const char *line)
} else if (!strncmp(line, "rtc", 3)) {
do_log_rtc = 1;
line += 3;
} else if (!strncmp(line, "refclocks", 9)) {
do_log_refclocks = 1;
line += 9;
} else {
break;
}
@@ -571,7 +723,7 @@ parse_initstepslew(const char *line)
char hostname[HOSTNAME_LEN+1];
int n;
int threshold;
unsigned long ip_addr;
IPAddr ip_addr;
n_init_srcs = 0;
p = line;
@@ -584,8 +736,7 @@ parse_initstepslew(const char *line)
}
while (*p) {
if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
ip_addr = DNS_Name2IPAddress(hostname);
if (ip_addr != DNS_Failed_Address) {
if (DNS_Name2IPAddress(hostname, &ip_addr, 1)) {
init_srcs_ip[n_init_srcs] = ip_addr;
++n_init_srcs;
}
@@ -634,6 +785,34 @@ 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
parse_makestep(const char *line)
{
if (sscanf(line, "%lf %d", &make_step_threshold, &make_step_limit) != 2) {
make_step_limit = 0;
LOG(LOGS_WARN, LOGF_Configure,
"Could not read threshold or update limit for stepping clock at line %d\n",
line_number);
}
}
/* ================================================== */
static void
parse_logchange(const char *line)
{
@@ -677,7 +856,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
unsigned long a, b, c, d, n;
int all = 0;
AllowDeny *new_node = NULL;
unsigned long ip_addr;
IPAddr ip_addr;
p = line;
@@ -694,45 +873,54 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
new_node->ip = 0UL;
new_node->ip.family = IPADDR_UNSPEC;
new_node->subnet_bits = 0;
} else {
char *slashpos;
slashpos = strchr(p, '/');
if (slashpos) *slashpos = 0;
n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
if (n >= 1) {
n = 0;
if (UTI_StringToIP(p, &ip_addr) ||
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
switch (n) {
case 1:
new_node->ip = (a<<24);
new_node->subnet_bits = 8;
break;
case 2:
new_node->ip = (a<<24) | (b<<16);
new_node->subnet_bits = 16;
break;
case 3:
new_node->ip = (a<<24) | (b<<16) | (c<<8);
new_node->subnet_bits = 24;
break;
case 4:
new_node->ip = (a<<24) | (b<<16) | (c<<8) | d;
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;
break;
default:
assert(0);
} else {
new_node->ip.family = IPADDR_INET4;
a &= 0xff;
b &= 0xff;
c &= 0xff;
d &= 0xff;
switch (n) {
case 1:
new_node->ip.addr.in4 = (a<<24);
new_node->subnet_bits = 8;
break;
case 2:
new_node->ip.addr.in4 = (a<<24) | (b<<16);
new_node->subnet_bits = 16;
break;
case 3:
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
new_node->subnet_bits = 24;
break;
case 4:
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
new_node->subnet_bits = 32;
break;
default:
assert(0);
}
}
if (slashpos) {
@@ -746,13 +934,15 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
}
} else {
ip_addr = DNS_Name2IPAddress(p);
if (ip_addr != DNS_Failed_Address) {
if (DNS_Name2IPAddress(p, &ip_addr, 1)) {
new_node = MallocNew(AllowDeny);
new_node->allow = allow;
new_node->all = all;
new_node->ip = ip_addr;
new_node->subnet_bits = 32;
if (ip_addr.family == IPADDR_INET6)
new_node->subnet_bits = 128;
else
new_node->subnet_bits = 32;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not read address at line %d", line_number);
}
@@ -805,27 +995,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
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 +1016,17 @@ parse_bindaddress(const char *line)
static void
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 +1043,7 @@ parse_pidfile(const char *line)
typedef struct {
/* Both in host (not necessarily network) order */
unsigned long addr;
IPAddr addr;
unsigned short port;
int interval;
} NTP_Broadcast_Destination;
@@ -866,27 +1059,22 @@ parse_broadcast(const char *line)
{
/* Syntax : broadcast <interval> <broadcast-IP-addr> [<port>] */
int port;
unsigned int a, b, c, d;
int n;
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);
if (n < 5) {
n = sscanf(line, "%d %50s %d", &interval, addr, &port);
if (n < 2 || !UTI_StringToIP(addr, &ip)) {
LOG(LOGS_WARN, LOGF_Configure, "Could not parse broadcast directive at line %d", line_number);
return;
} else if (n == 5) {
} else if (n == 2) {
/* default port */
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);
}
addr = ((unsigned long) a << 24) |
((unsigned long) b << 16) |
((unsigned long) c << 8) |
((unsigned long) d );
if (max_broadcasts == n_broadcasts) {
/* Expand array */
max_broadcasts += 8;
@@ -897,7 +1085,7 @@ parse_broadcast(const char *line)
}
}
broadcasts[n_broadcasts].addr = addr;
broadcasts[n_broadcasts].addr = ip;
broadcasts[n_broadcasts].port = port;
broadcasts[n_broadcasts].interval = interval;
++n_broadcasts;
@@ -948,6 +1136,7 @@ CNF_AddSources(void) {
for (i=0; i<n_ntp_sources; i++) {
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;
switch (ntp_sources[i].type) {
@@ -968,12 +1157,23 @@ CNF_AddSources(void) {
/* ================================================== */
void
CNF_AddRefclocks(void) {
int i;
for (i=0; i<n_refclock_sources; i++) {
RCL_AddRefclock(&refclock_sources[i]);
}
}
/* ================================================== */
void
CNF_AddBroadcasts(void)
{
int i;
for (i=0; i<n_broadcasts; i++) {
BRD_AddDestination(broadcasts[i].addr,
BRD_AddDestination(&broadcasts[i].addr,
broadcasts[i].port,
broadcasts[i].interval);
}
@@ -1051,6 +1251,13 @@ CNF_GetLogRtc(void)
return do_log_rtc;
}
/* ================================================== */
int
CNF_GetLogRefclocks(void)
{
return do_log_refclocks;
}
/* ================================================== */
char *
@@ -1137,6 +1344,15 @@ CNF_GetRTCOnUTC(void)
/* ================================================== */
void
CNF_GetMakeStep(int *limit, double *threshold)
{
*limit = make_step_limit;
*threshold = make_step_threshold;
}
/* ================================================== */
void
CNF_GetLogChange(int *enabled, double *threshold)
{
@@ -1169,14 +1385,14 @@ CNF_SetupAccessRestrictions(void)
int status;
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) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
}
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) {
LOG(LOGS_WARN, LOGF_Configure, "Bad subnet for %08lx", node->ip);
}
@@ -1195,18 +1411,36 @@ CNF_GetNoClientLog(void)
/* ================================================== */
void
CNF_GetBindAddress(unsigned long *addr)
unsigned long
CNF_GetClientLogLimit(void)
{
*addr = bind_address;
return client_log_limit;
}
/* ================================================== */
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 +1469,18 @@ CNF_GetLinuxFreqScale(int *set, double *freq_scale)
*freq_scale = linux_freq_scale ;
}
/* ================================================== */
int
CNF_GetSchedPriority(void)
{
return sched_priority;
}
/* ================================================== */
int
CNF_GetLockMemory(void)
{
return lock_memory;
}

15
conf.h
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#define GOT_CONF_H
#include "addressing.h"
extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename);
extern void CNF_AddSources(void);
extern void CNF_AddBroadcasts(void);
extern void CNF_AddRefclocks(void);
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_GetLogTracking(void);
extern int CNF_GetLogRtc(void);
extern int CNF_GetLogRefclocks(void);
extern char *CNF_GetKeysFile(void);
extern char *CNF_GetRtcFile(void);
extern unsigned long CNF_GetCommandKey(void);
@@ -56,11 +60,13 @@ extern int CNF_GetDumpOnExit(void);
extern int CNF_GetManualEnabled(void);
extern int CNF_GetCommandPort(void);
extern int CNF_GetRTCOnUTC(void);
extern void CNF_GetMakeStep(int *limit, double *threshold);
extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void);
extern void CNF_GetBindAddress(unsigned long *addr);
extern void CNF_GetBindCommandAddress(unsigned long *addr);
extern unsigned long CNF_GetClientLogLimit(void);
extern void CNF_GetBindAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void);
extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
@@ -71,4 +77,7 @@ extern int CNF_AllowLocalReference(int *stratum);
extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void);
#endif /* GOT_CONF_H */

370
configure vendored
View File

@@ -1,7 +1,4 @@
#!/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.
@@ -24,86 +21,47 @@ else
MYCFLAGS="${CFLAGS}"
fi
MYCPPFLAGS="${CPPFLAGS}"
if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
CCWARNFLAGS=""
fi
# ======================================================================
# FUNCTIONS
#{{{ test_for_sqrt
test_for_sqrt () {
# 0 : doesn't need -lm
# 1 : needs -lm
# 2 : doesn't even link with -lm
#{{{ test_code
test_code () {
name=$1
headers=$2
cflags=$3
ldflags=$4
code=$5
cat >docheck.c <<EOF;
#include <math.h>
int main(int argc, char **argv) {
return (int) sqrt((double)argc);
}
EOF
printf "Checking for $name : "
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
${MYCC} ${MYCFLAGS} -o docheck docheck.o >/dev/null 2>&1
if [ $? -eq 0 ]
then
result=0
else
${MYCC} ${MYCFLAGS} -o docheck docheck.o -lm >/dev/null 2>&1
if [ $? -eq 0 ]
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
(
for h in $headers; do
echo "#include <$h>"
done
echo "int main(int argc, char **argv) {"
echo "$code"
echo "return 0; }"
) > docheck.c
${MYCC} ${MYCFLAGS} ${MYCPPFLAGS} $cflags -o docheck docheck.c $ldflags >/dev/null 2>&1
if [ $? -eq 0 ]
then
printf "Yes\n"
result=0
else
printf "No\n"
result=1
fi
rm -f docheck.c docheck.o
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
rm -f docheck.c docheck
return $result
}
#}}}
#{{{ usage
@@ -121,6 +79,8 @@ Configuration:
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`/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 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-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline 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-linuxcaps Disable Linux capabilities support
Fine tuning of the installation directories:
--infodir=DIR info documentation [PREFIX/info]
--mandir=DIR man documentation [PREFIX/man]
--sysconfdir=DIR chrony.conf location [/etc]
--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:
CC C compiler command
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
nonstandard directory <lib dir>
Use these variables to override the choices made by \`configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to <rc@rc0.org.uk>.
EOF
}
@@ -162,37 +138,42 @@ OPERATINGSYSTEM=`uname -s`
VERSION=`uname -r`
MACHINE=`uname -m`
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
EXTRA_LIBS=""
EXTRA_CLI_LIBS=""
EXTRA_OBJECTS=""
EXTRA_DEFS=""
INSTALL_PREFIX=/usr/local
SYSDEFS=""
# Support for readline (on by default)
feat_readline=1
try_readline=1
try_editline=1
feat_rtc=1
feat_linuxcaps=1
try_linuxcaps=0
readline_lib=""
readline_inc=""
ncurses_lib=""
SETINFODIR=""
SETMANDIR=""
feat_ipv6=1
feat_pps=1
try_setsched=0
try_lockmem=0
for option
do
case "$option" in
--prefix=* | --install_prefix=* )
INSTALL_PREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--trace )
EXTRA_DEFS="-DTRACEON"
;;
--disable-readline )
feat_readline=0
;;
--without-readline )
try_readline=0
;;
--without-editline )
try_editline=0
;;
--with-readline-library=* )
readline_lib=-L`echo $option | sed -e 's/^.*=//;'`
;;
@@ -202,15 +183,54 @@ do
--with-ncurses-library=* )
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=* )
SETINFODIR=`echo $option | sed -e 's/^.*=//;'`
;;
--mandir=* )
SETMANDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--docdir=* )
SETDOCDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--disable-rtc)
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 )
usage
exit 0
@@ -220,6 +240,8 @@ do
esac
done
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
case $SYSTEM in
SunOS-sun4* )
case $VERSION in
@@ -245,9 +267,12 @@ case $SYSTEM in
Linux* )
EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o"
if [ $feat_rtc -eq 1 ] ; then
EXTRA_OBJECTS+=" rtc_linux.o"
EXTRA_DEFS+=" -DFEAT_RTC=1"
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
EXTRA_DEFS="$EXTRA_DEFS -DFEAT_RTC=1"
fi
try_linuxcaps=1
try_setsched=1
try_lockmem=1
SYSDEFS="-DLINUX"
echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then
@@ -257,13 +282,13 @@ case $SYSTEM in
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
# be supported with the SunOS 4.x driver files.
EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm"
SYSDEFS="-DSUNOS"
echo "Configuring for BSD/386 (using SunOS driver)"
echo "Configuring for $SYSTEM (using SunOS driver)"
;;
NetBSD-* )
EXTRA_OBJECTS="sys_netbsd.o"
@@ -292,74 +317,165 @@ case $SYSTEM in
;;
esac
printf "Checking if sqrt() needs -lm : "
case `test_for_sqrt`
in
0)
printf "No\n"
MATHCODE='return (int) pow(2.0, log(sqrt((double)argc)));'
if test_code 'math' 'math.h' '' '' "$MATHCODE"; then
LIBS=""
;;
1)
printf "Yes\n"
LIBS="-lm"
;;
*)
printf "\nCan't compile/link a program which uses sqrt(), bailing out\n"
exit 1
;;
esac
printf "Checking for <stdint.h> : "
if [ `test_for_stdint_h` -eq 0 ]; then
printf "Yes\n"
else
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then
LIBS="-lm"
else
printf "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out\n"
exit 1
fi
fi
if test_code '<stdint.h>' 'stdint.h' '' '' ''; then
SYSDEFS="${SYSDEFS} -DHAS_STDINT_H"
else
printf "No\n"
fi
printf "Checking for <inttypes.h> : "
if [ `test_for_inttypes_h` -eq 0 ]; then
printf "Yes\n"
if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then
SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H"
else
printf "No\n"
fi
if [ "x${MYCC}" = "xgcc" ]; then
CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
CCWARNFLAGS=""
if [ $feat_ipv6 = "1" ] && \
test_code 'IPv6 support' 'arpa/inet.h sys/socket.h netinet/in.h' '' '' '
struct sockaddr_in6 n;
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
READLINE_COMPILE=""
READLINE_LINK=""
if [ $feat_readline = "1" ]; then
READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
else
READLINE_COMPILE=""
READLINE_LINK=""
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
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
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
MANDIR=${INSTALL_PREFIX}/man
INFODIR=${INSTALL_PREFIX}/info
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
INFODIR=$SETINFODIR
fi
MANDIR=${DATAROOTDIR}/man
if [ "x$SETMANDIR" != "x" ]; then
MANDIR=$SETMANDIR
fi
DOCDIR=${DATAROOTDIR}/doc/chrony
if [ "x$SETDOCDIR" != "x" ]; then
DOCDIR=$SETDOCDIR
fi
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@CC@%${MYCC}%;\
s%@CFLAGS@%${MYCFLAGS}%;\
s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\
s%@CPPFLAGS@%${CPPFLAGS}%;\
s%@LIBS@%${LIBS}%;\
s%@LDFLAGS@%${LDFLAGS}%;\
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
s%@SYSDEFS@%${SYSDEFS}%;\
s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
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%@INFODIR@%${INFODIR}%;"\
< Makefile.in > Makefile

View File

@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -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
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU 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.
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
modification follow.
GNU GENERAL PUBLIC LICENSE
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
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -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
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -278,8 +278,8 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
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
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.
<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
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
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
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
# 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
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
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# SEE COPYING FOR DETAILS
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# 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
# /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.
#
# Copyright 2002 Richard P. Curnow
@@ -19,7 +18,7 @@
#
# 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.,
# 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
! log measurements statistics tracking
If you have real time clock support enabled (see below), you might want
this line instead:
# If you have real time clock support enabled (see below), you might want
# this line instead:
! log measurements statistics tracking rtc
@@ -209,6 +208,12 @@ this line instead:
! 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
# 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
#######################################################################
### 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>
This is a set of questions and answers to common problems and issues.
<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.
<hr>
<p>
The author can be reached by email
<a href="mailto:rc@rc0.org.uk">
</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)!
The developers can be reached via the chrony-dev mailing list. See
<a href="#question_1.4">question 1.4.</a> for details.
<hr>
<br clear=all>
@@ -38,39 +32,34 @@ mail reader can keep my mail sorted by topic)!
S: Administrative issues
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?
I am aware of packages for Debian, Mandrake and Redhat. I am not personally
involved with how these are built or distributed.
We are aware of packages for Debian, Fedora, Gentoo, Mandriva, Slackware,
and Ubuntu. We are not involved with how these are built or distributed.
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?
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
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
<a href="mailto:chrony-announce-subscribe@sunsite.dk">chrony-announce-subscribe@sunsite.dk</a> respectively.
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-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
developers' mailing list. You can subscribe by sending mail to
<a href="mailto:chrony-dev-subscribe@sunsite.dk">chrony-dev-subscribe@sunsite.dk</a>.
developers' mailing list. You can subscribe by sending mail with the
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?
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.
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
Q: How does chrony compare to xntpd?
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
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
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
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
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.
Q: Are there any plans to support Windows?
I have no personal plans to do this. I have neither the time nor the
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
We have no plans to do this. Anyone is welcome to pick this work up and
contribute it back to the project.
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
- NetTime (nettime.sourceforge.net)
@@ -345,12 +326,10 @@ useful to avoid this situation.
S: Development
Q: Can I get the source via CVS from anywhere?
Yes. See <a href="http://chrony.sunsite.dk/cvs.php">http://chrony.sunsite.dk/cvs.php</a> for information. Currently there is
only anonymous read-only access. I keep the master copy on my own PC, which is
more convenient for me because I don't have to connect to the Internet to do
CVS operations on the files. So for now, there is no read-write access for
other developers. Please email me your patches + documentation instead.
Q: Can I get the source via git from anywhere?
Yes. See the Git link at <a
href="http://chrony.tuxfamily.org/">http://chrony.tuxfamily.org</a> for
information.
S: Linux-specific issues

2923
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
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 */

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. */
/* (__sh__ includes both sh and sh64) */
#if defined(__i386__) || defined(__sh__) || defined(__arm__)||defined(__x86_64__)
/* (__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_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 14
@@ -26,7 +27,7 @@
#define CHRONY_IOC_READ 2U
#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_TYPEBITS 8
#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
* 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
* 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.
*
**********************************************************************

47
local.c
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
@@ -53,7 +53,7 @@ static lcl_SetFrequencyDriver drv_set_freq;
static lcl_AccrueOffsetDriver drv_accrue_offset;
static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
static lcl_OffsetCorrectionDriver drv_offset_convert;
static lcl_ImmediateStepDriver drv_immediate_step;
static lcl_SetLeapDriver drv_set_leap;
/* ================================================== */
@@ -535,14 +535,14 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert,
lcl_ImmediateStepDriver immediate_step)
lcl_SetLeapDriver set_leap)
{
drv_read_freq = read_freq;
drv_set_freq = set_freq;
drv_accrue_offset = accrue_offset;
drv_apply_step_offset = apply_step_offset;
drv_offset_convert = offset_convert;
drv_immediate_step = immediate_step;
drv_set_leap = set_leap;
current_freq_ppm = (*drv_read_freq)();
@@ -555,20 +555,39 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
/* ================================================== */
/* Look at the current difference between the system time and the NTP
time, and make a step to cancel it. */
time, and make a step to cancel it if it's larger than the threshold. */
int
LCL_MakeStep(void)
LCL_MakeStep(double threshold)
{
if (drv_immediate_step) {
(drv_immediate_step)();
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Local, "Made step to system time to apply remaining slew");
#endif
return 1;
}
struct timeval raw;
double correction;
return 0;
LCL_ReadRawTime(&raw);
correction = LCL_GetOffsetCorrection(&raw);
if (fabs(correction) <= threshold)
return 0;
/* Cancel remaining slew and make the step */
LCL_AccumulateOffset(correction);
LCL_ApplyStepOffset(-correction);
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.3f seconds", correction);
return 1;
}
/* ================================================== */
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
* 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.
*
**********************************************************************
@@ -179,6 +179,11 @@ extern void LCL_Finalise(void);
/* Routine to convert the outstanding system clock error to a step and
apply it, e.g. if the system clock has ended up an hour wrong due
to a timezone problem. */
extern int LCL_MakeStep(void);
extern int LCL_MakeStep(double threshold);
/* Routine to schedule a leap second. Leap second will be inserted
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 */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
@@ -56,9 +56,8 @@ typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
raw time to get the corrected time */
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
/* System driver to stop slewing the current offset and to apply is
as an immediate step instead */
typedef void (*lcl_ImmediateStepDriver)(void);
/* System driver to schedule leap second */
typedef void (*lcl_SetLeapDriver)(int leap);
extern void lcl_InvokeDispersionNotifyHandlers(double dispersion);
@@ -68,6 +67,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert,
lcl_ImmediateStepDriver immediate_step_driver);
lcl_SetLeapDriver set_leap);
#endif /* GOT_LOCALP_H */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
@@ -40,6 +40,8 @@ static int initialised = 0;
static int is_detached = 0;
static time_t last_limited = 0;
#ifdef WINNT
static FILE *logfile;
#endif
@@ -214,3 +216,35 @@ LOG_GoDaemon(void)
}
/* ================================================== */
int
LOG_RateLimited(void)
{
time_t now;
now = time(NULL);
if (last_limited + 10 > now && last_limited <= now)
return 1;
last_limited = now;
return 0;
}
/* ================================================== */
/* Force a core dump and exit without doing abort() or assert(0).
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
* 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_Util,
LOGF_Main,
LOGF_ClientLog,
LOGF_Configure,
LOGF_CmdMon,
LOGF_Acquire,
@@ -60,11 +61,13 @@ typedef enum {
LOGF_Logging,
LOGF_Rtc,
LOGF_Regress,
LOGF_Sys,
LOGF_SysLinux,
LOGF_SysSolaris,
LOGF_SysSunOS,
LOGF_SysWinnt,
LOGF_RtcLinux
LOGF_RtcLinux,
LOGF_Refclock
} LOG_Facility;
/* Init function */
@@ -84,6 +87,9 @@ extern void LOG_Position(const char *filename, int line_number, const char *func
extern void LOG_GoDaemon(void);
/* Return zero once per 10 seconds */
extern int LOG_RateLimited(void);
/* Line logging macro. If the compiler is GNU C, we take advantage of
being able to get the function name also. */
#if defined(__GNUC__)
@@ -94,4 +100,13 @@ extern void LOG_GoDaemon(void);
#define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function
#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 */

62
main.c
View File

@@ -7,6 +7,7 @@
**********************************************************************
* 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
* 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
* 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 "version.h"
#include "rtc.h"
#include "refclock.h"
#include "clientlog.h"
#include "broadcast.h"
#include "nameserv.h"
/* ================================================== */
@@ -83,19 +86,20 @@ MAI_CleanupAndExit(void)
SRC_DumpSources();
}
RTC_Finalise();
MNL_Finalise();
ACQ_Finalise();
CAM_Finalise();
KEY_Finalise();
CLG_Finalise();
NIO_Finalise();
NSR_Finalise();
NCR_Finalise();
BRD_Finalise();
SRC_Finalise();
SST_Finalise();
REF_Finalise();
RCL_Finalise();
RTC_Finalise();
CAM_Finalise();
NIO_Finalise();
SYS_Finalise();
SCH_Finalise();
LCL_Finalise();
@@ -113,7 +117,8 @@ static void
signal_cleanup(int x)
{
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();
RTC_StartMeasurements();
RCL_StartRefclocks();
}
/* ================================================== */
@@ -206,9 +212,11 @@ int main
(int argc, char **argv)
{
char *conf_file = NULL;
char *user = NULL;
int debug = 0;
int do_init_rtc = 0;
int other_pid;
int lock_memory = 0, sched_priority = 0;
LOG_Initialise();
@@ -218,8 +226,22 @@ int main
if (!strcmp("-f", *argv)) {
++argv, --argc;
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)) {
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)) {
do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
@@ -228,8 +250,12 @@ int main
exit(0);
} else if (!strcmp("-d", *argv)) {
debug = 1;
} else if (!strcmp("-4", *argv)) {
DNS_SetAddressFamily(IPADDR_INET4);
} else if (!strcmp("-6", *argv)) {
DNS_SetAddressFamily(IPADDR_INET6);
} else {
LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv);
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
}
}
@@ -269,19 +295,37 @@ int main
LCL_Initialise();
SCH_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();
SST_Initialise();
SRC_Initialise();
BRD_Initialise();
NCR_Initialise();
NSR_Initialise();
NIO_Initialise();
CLG_Initialise();
KEY_Initialise();
CAM_Initialise();
ACQ_Initialise();
MNL_Initialise();
RTC_Initialise();
/* From now on, it is safe to do finalisation on exit */
initialised = 1;

2
main.h
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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;
}
system ("git-tag -s $version");
system ("git tag -s $version");
die "git-tag failed" if ($? != 0);
if (-d "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);
chdir "RELEASES";

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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++) {
report[i].when = samples[i].when.tv_sec;
report[i].when = samples[i].when;
report[i].slewed_offset = samples[i].offset;
report[i].orig_offset = samples[i].orig_offset;
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
* 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
* 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
* 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
* 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) 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
@@ -19,7 +20,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
@@ -32,60 +33,159 @@
#include "sysincl.h"
#include "nameserv.h"
#include "util.h"
#include <resolv.h>
/* ================================================== */
unsigned long
DNS_Name2IPAddress(const char *name)
#define MAXRETRIES 10
static unsigned int retries = 0;
static int address_family = IPADDR_UNSPEC;
void
DNS_SetAddressFamily(int family)
{
struct hostent *host;
unsigned char *address0;
unsigned long result;
host = gethostbyname(name);
if (host == NULL) {
result = DNS_Failed_Address;
} else {
address0 = host->h_addr_list[0];
result = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
}
return result;
address_family = family;
}
/* ================================================== */
const char *
DNS_IPAddress2Name(unsigned long ip_addr)
int
DNS_Name2IPAddress(const char *name, IPAddr *addr, int retry)
{
struct hostent *host;
static char buffer[16];
unsigned int a, b, c, d;
unsigned long addr;
#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
addr = htonl(ip_addr);
if (addr == 0UL) {
/* Catch this as a special case that will never resolve to
anything */
strcpy(buffer, "0.0.0.0");
return buffer;
} else {
host = gethostbyaddr((const char *) &addr, sizeof(ip_addr), AF_INET);
if (!host) {
a = (ip_addr >> 24) & 0xff;
b = (ip_addr >> 16) & 0xff;
c = (ip_addr >> 8) & 0xff;
d = (ip_addr) & 0xff;
snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", a, b, c, d);
return buffer;
} else {
return host->h_name;
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);
if (host == NULL) {
if (retry && h_errno == TRY_AGAIN && retries < MAXRETRIES) {
sleep(2 << retries);
retries++;
res_init();
goto try_again;
}
} else {
addr->family = IPADDR_INET4;
address0 = host->h_addr_list[0];
addr->addr.in4 = ((((unsigned long)address0[0])<<24) |
(((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
return 1;
}
return 0;
#endif
}
/* ================================================== */
int
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len)
{
char *result = NULL;
#ifdef HAVE_IPV6
struct sockaddr_in in4;
struct sockaddr_in6 in6;
char hbuf[NI_MAXHOST];
switch (ip_addr->family) {
case IPADDR_INET4:
memset(&in4, 0, sizeof (in4));
#ifdef SIN6_LEN
in4.sin_len = sizeof (in4);
#endif
in4.sin_family = AF_INET;
in4.sin_addr.s_addr = htonl(ip_addr->addr.in4);
if (!getnameinfo((const struct sockaddr *)&in4, sizeof (in4), hbuf, sizeof (hbuf), NULL, 0, 0))
result = hbuf;
break;
case IPADDR_INET6:
memset(&in6, 0, sizeof (in6));
#ifdef SIN6_LEN
in6.sin6_len = sizeof (in6);
#endif
in6.sin6_family = AF_INET6;
memcpy(&in6.sin6_addr.s6_addr, ip_addr->addr.in6, sizeof (in6.sin6_addr.s6_addr));
if (!getnameinfo((const struct sockaddr *)&in6, sizeof (in6), hbuf, sizeof (hbuf), NULL, 0, 0))
result = hbuf;
break;
}
#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);
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6);
break;
#endif
default:
host = NULL;
}
if (host)
result = host->h_name;
#endif
if (result == NULL)
result = UTI_IPToString(ip_addr);
if (snprintf(name, len, "%s", result) >= len)
return 0;
return 1;
}
/* ================================================== */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
#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 int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
#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
* 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) 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
@@ -19,7 +20,7 @@
*
* 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.,
* 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->remote_orig.hi = 0;
result->remote_orig.lo = 0;
result->score = 0;
if (params->online) {
@@ -316,10 +320,14 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
result->local_poll = params->minpoll;
/* 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_usec = 0;
result->local_tx.tv_sec = 0;
result->local_tx.tv_usec = 0;
result->local_ntp_tx.hi = 0;
result->local_ntp_tx.lo = 0;
return result;
@@ -621,7 +629,7 @@ transmit_timeout(void *arg)
#ifdef TRACEON
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
/* Check whether we need to 'warm up' the link to the other end by
@@ -809,8 +817,12 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
int valid_data;
int valid_header;
/* Kiss-of-Death packets */
int kod_rate = 0;
int valid_kod;
/* 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
convention here is that positive means local clock FAST of
@@ -1015,6 +1027,14 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
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_header = test5 && test6 && test7 && test8;
@@ -1026,8 +1046,8 @@ receive_packet(NTP_Packet *message, struct timeval *now, NCR_Instance inst, int
message->lvm, message->stratum, message->poll, message->precision);
LOG(LOGS_INFO, LOGF_NtpCore, "Root delay=%08lx (%f), dispersion=%08lx (%f)",
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]",
UTI_IPToDottedQuad(ntohl(message->reference_id)),
LOG(LOGS_INFO, LOGF_NtpCore, "Ref id=[%lx], ref_time=%08lx.%08lx [%s]",
ntohl(message->reference_id),
message->reference_ts.hi, message->reference_ts.lo,
UTI_TimestampToString(&message->reference_ts));
LOG(LOGS_INFO, LOGF_NtpCore, "Originate=%08lx.%08lx [%s]",
@@ -1049,9 +1069,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",
test5, test6, test7, test8, valid_header);
LOG(LOGS_INFO, LOGF_NtpCore, "kod_rate=%d valid_kod=%d", kod_rate, valid_kod);
#endif
if (valid_header) {
if (valid_header && valid_data) {
inst->tx_count = 0;
SRC_SetReachable(inst->source);
}
@@ -1216,6 +1238,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) {
/* Get rid of old timeout and start a new one */
@@ -1236,7 +1271,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",
UTI_TimeToLogForm(sample_time.tv_sec),
UTI_IPToDottedQuad(inst->remote_addr.ip_addr),
UTI_IPToString(&inst->remote_addr.ip_addr),
sync_stats[pkt_leap],
message->stratum,
test1, test2, test3, test4,
@@ -1325,9 +1360,9 @@ process_known
one of the secondaries to flywheel it. The behaviour coded here
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) {
auth_key_id = ntohl(message->auth_keyid);
@@ -1358,9 +1393,9 @@ process_known
&inst->local_ntp_tx,
&inst->remote_addr);
} else {
} else if (!LOG_RateLimited()) {
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);
}
@@ -1371,7 +1406,7 @@ process_known
switch(inst->mode) {
case MODE_ACTIVE:
/* 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);
break;
case MODE_PASSIVE:
@@ -1381,7 +1416,7 @@ process_known
case MODE_CLIENT:
/* This is where we have the remote configured as a server and he has
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);
break;
case MODE_SERVER:
@@ -1402,7 +1437,7 @@ process_known
switch(inst->mode) {
case MODE_ACTIVE:
/* 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);
break;
case MODE_PASSIVE:
@@ -1430,7 +1465,7 @@ process_known
case MODE_ACTIVE:
/* This would arise if we have the remote configured as a peer and
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);
break;
case MODE_PASSIVE:
@@ -1492,19 +1527,19 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
NTP_Mode my_mode;
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;
if (his_mode == MODE_CLIENT) {
/* We are 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) {
/* We are symmetric passive, even though we don't ever lock to him */
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 {
my_mode = MODE_UNDEFINED;
@@ -1526,9 +1561,9 @@ NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Ad
remote_addr);
}
} else {
} else if (!LOG_RateLimited()) {
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);
}
@@ -1562,19 +1597,19 @@ NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Addr
int valid_key, valid_auth;
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;
if (his_mode == MODE_CLIENT) {
/* We are 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) {
/* We are symmetric passive, even though we don't ever lock to him */
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 {
my_mode = MODE_UNDEFINED;
@@ -1646,7 +1681,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
case MD_OFFLINE:
if (!inst->timer_running) {
/* 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->score = (ZONE_WIDTH >> 1);
inst->opmode = MD_ONLINE;
@@ -1670,7 +1705,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
switch (inst->opmode) {
case MD_ONLINE:
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);
inst->timer_running = 0;
inst->opmode = MD_OFFLINE;
@@ -1693,7 +1728,7 @@ void
NCR_ModifyMinpoll(NCR_Instance inst, int 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 +1737,7 @@ void
NCR_ModifyMaxpoll(NCR_Instance inst, int 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 +1747,7 @@ NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay)
{
inst->max_delay = new_max_delay;
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 +1757,7 @@ NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio)
{
inst->max_delay_ratio = new_max_delay_ratio;
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 +1839,7 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *no
/* ================================================== */
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;
@@ -1834,7 +1869,7 @@ NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int
/* ================================================== */
int
NCR_CheckAccessRestriction(unsigned long ip_addr)
NCR_CheckAccessRestriction(IPAddr *ip_addr)
{
return ADF_IsAllowed(access_auth_table, ip_addr);
}
@@ -1880,3 +1915,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
* 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 int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(unsigned long ip_addr);
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
extern void NCR_CycleLogFile(void);
extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
int *burst_online, int *burst_offline);
extern NTP_Remote_Address *NCR_GetRemoteAddress(NCR_Instance instance);
#endif /* GOT_NTP_CORE_H */

367
ntp_io.c
View File

@@ -7,6 +7,8 @@
**********************************************************************
* 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
* 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
* 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>
/* The file descriptor for the socket */
static int sock_fd;
union sockaddr_in46 {
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 */
static int initialised=0;
@@ -50,6 +63,7 @@ static int initialised=0;
/* ================================================== */
/* Forward prototypes */
static int prepare_socket(int family);
static void read_from_socket(void *anything);
/* ================================================== */
@@ -81,30 +95,30 @@ do_size_checks(void)
/* ================================================== */
void
NIO_Initialise(void)
static int
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 long bind_address;
IPAddr bind_address;
int on_off = 1;
assert(!initialised);
initialised = 1;
do_size_checks();
port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */
#if 0
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sock_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
#else
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
sock_fd = socket(family, SOCK_DGRAM, 0);
#endif
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 */
@@ -119,28 +133,80 @@ NIO_Initialise(void)
/* 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 */
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_number);
memset(&my_addr, 0, sizeof (my_addr));
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) {
my_addr.sin_addr.s_addr = htonl(bind_address);
} else {
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
CNF_GetBindAddress(IPADDR_INET4, &bind_address);
if (bind_address.family == IPADDR_INET4)
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
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#endif
if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno));
if (bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
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 */
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd);
#if 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");
}
#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;
}
@@ -160,11 +249,18 @@ NIO_Initialise(void)
void
NIO_Finalise(void)
{
if (sock_fd >= 0) {
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
if (sock_fd4 >= 0) {
SCH_RemoveInputFileHandler(sock_fd4);
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;
return;
}
@@ -180,24 +276,33 @@ read_from_socket(void *anything)
/* This should only be called when there is something
to read, otherwise it will block. */
int status;
int status, sock_fd;
ReceiveBuffer message;
int message_length;
struct sockaddr_in where_from;
socklen_t from_length;
union sockaddr_in46 where_from;
unsigned int flags = 0;
struct timeval now;
NTP_Remote_Address remote_addr;
double local_clock_err;
char cmsgbuf[256];
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
assert(initialised);
from_length = sizeof(where_from);
message_length = sizeof(message);
SCH_GetFileReadyTime(&now);
LCL_ReadCookedTime(&now, &local_clock_err);
status = recvfrom(sock_fd, (char *)&message, message_length, flags,
(struct sockaddr *)&where_from, &from_length);
iov.iov_base = message.arbitrary;
iov.iov_len = sizeof(message);
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
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). */
if (status > 0) {
remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
remote_addr.port = ntohs(where_from.sin_port);
memset(&remote_addr, 0, sizeof (remote_addr));
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) {
@@ -228,27 +378,103 @@ read_from_socket(void *anything)
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_RateLimited()) {
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 */
void
NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{
struct sockaddr_in remote;
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;
send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE, remote_addr);
}
/* ================================================== */
@@ -257,21 +483,7 @@ NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
void
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{
struct sockaddr_in remote;
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;
send_packet((void *) packet, sizeof(NTP_Packet), remote_addr);
}
/* ================================================== */
@@ -283,15 +495,10 @@ void
NIO_SendEcho(NTP_Remote_Address *remote_addr)
{
unsigned long magic_message = 0xbe7ab1e7UL;
struct sockaddr_in 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));
NTP_Remote_Address 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
* 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
* 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
particular sources */
typedef struct {
NTP_Remote_Address remote_addr; /* The address of this source */
int in_use; /* Whether this slot in the table is in use */
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
means this slot in table is in use */
NCR_Instance data; /* Data for the protocol engine for this source */
} SourceRecord;
@@ -83,7 +83,7 @@ NSR_Initialise(void)
{
int i;
for (i=0; i<N_RECORDS; i++) {
records[i].in_use = 0;
records[i].remote_addr = NULL;
}
n_sources = 0;
initialised = 1;
@@ -120,23 +120,42 @@ static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{
unsigned long hash;
unsigned long ip = remote_addr->ip_addr;
unsigned short port = remote_addr->port;
unsigned long ip;
unsigned short port;
uint8_t *ip6;
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 */
hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff;
while ((records[hash].in_use) &&
(records[hash].remote_addr.ip_addr != ip)) {
while (records[hash].remote_addr &&
UTI_CompareIPs(&records[hash].remote_addr->ip_addr,
&remote_addr->ip_addr, NULL)) {
hash++;
if (hash == 256) hash = 0;
}
if (records[hash].in_use) {
if (records[hash].remote_addr.port == port) {
if (records[hash].remote_addr) {
if (records[hash].remote_addr->port == port) {
*found = 2;
} else {
*found = 1;
@@ -162,7 +181,7 @@ NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised);
#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
/* 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 {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else {
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].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success;
}
}
@@ -193,7 +214,7 @@ NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
assert(initialised);
#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
/* 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 {
if (n_sources == MAX_SOURCES) {
return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else {
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].remote_addr = NCR_GetRemoteAddress(records[slot].data);
return NSR_Success;
}
}
@@ -231,7 +254,7 @@ NSR_RemoveSource(NTP_Remote_Address *remote_addr)
return NSR_NoSuchSource;
} else {
n_sources--;
records[slot].in_use = 0;
records[slot].remote_addr = NULL;
NCR_DestroyInstance(records[slot].data);
return NSR_Success;
}
@@ -249,7 +272,7 @@ NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address
#if 0
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));
#endif
@@ -293,10 +316,10 @@ slew_sources(struct timeval *raw,
int i;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
if (records[i].remote_addr) {
#if 0
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
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
@@ -308,17 +331,16 @@ slew_sources(struct timeval *raw,
/* ================================================== */
int
NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (records[i].remote_addr) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOnline(records[i].data);
}
@@ -331,17 +353,16 @@ NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
/* ================================================== */
int
NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (records[i].remote_addr) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1;
NCR_TakeSourceOffline(records[i].data);
}
@@ -354,11 +375,11 @@ NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
/* ================================================== */
int
NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@@ -373,11 +394,11 @@ NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
/* ================================================== */
int
NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@@ -392,11 +413,11 @@ NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
/* ================================================== */
int
NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@@ -411,11 +432,11 @@ NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
/* ================================================== */
int
NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = address;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
@@ -431,17 +452,16 @@ NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
unsigned long mask, unsigned long address)
IPAddr *mask, IPAddr *address)
{
int i;
int any;
unsigned long ip;
any = 0;
for (i=0; i<N_RECORDS; i++) {
if (records[i].in_use) {
ip = records[i].remote_addr.ip_addr;
if ((ip & mask) == address) {
if (records[i].remote_addr) {
if (address->family == IPADDR_UNSPEC ||
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) {
any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
}
@@ -486,7 +506,7 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
report->burst_offline = 0;
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,
&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
* 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_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_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;
/* 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
match a particular subnet should be set online again. Returns a
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
match a particular subnet should be set offline. Returns a flag
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);

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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.
*
**********************************************************************

717
refclock.c Normal file
View File

@@ -0,0 +1,717 @@
/*
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;
int last;
struct FilterSample *samples;
};
struct RCL_Instance_Record {
RefclockDriver *driver;
void *data;
char *driver_parameter;
int driver_parameter_length;
int driver_poll;
int driver_polled;
int poll;
int missed_samples;
int leap_status;
int pps_rate;
struct MedianFilter filter;
unsigned long ref_id;
unsigned long lock_ref;
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_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset);
static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
static 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_parameter_length = 0;
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->lock_ref = params->lock_ref_id;
inst->offset = params->offset;
inst->delay = params->delay;
inst->timeout_id = -1;
inst->source = NULL;
if (inst->driver_parameter) {
int i;
inst->driver_parameter_length = strlen(inst->driver_parameter);
for (i = 0; i < inst->driver_parameter_length; i++)
if (inst->driver_parameter[i] == ':')
inst->driver_parameter[i] = '\0';
}
if (pps_source) {
if (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, j;
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 (inst->lock_ref) {
/* Replace lock refid with index to refclocks */
for (j = 0; j < n_sources && refclocks[j].ref_id != inst->lock_ref; j++)
;
inst->lock_ref = (j < n_sources) ? j : -1;
} else
inst->lock_ref = -1;
}
if (n_sources > 0)
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;
}
char *
RCL_GetDriverOption(RCL_Instance instance, char *name)
{
char *s, *e;
int n;
s = instance->driver_parameter;
e = s + instance->driver_parameter_length;
n = strlen(name);
while (1) {
s += strlen(s) + 1;
if (s >= e)
break;
if (!strncmp(name, s, n)) {
if (s[n] == '=')
return s + n + 1;
if (s[n] == '\0')
return s + n;
}
}
return NULL;
}
int
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);
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 (instance->lock_ref != -1) {
struct timeval ref_sample_time;
double sample_diff, ref_offset, shift;
if (!filter_get_last_sample(&refclocks[instance->lock_ref].filter,
&ref_sample_time, &ref_offset))
return 0;
UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
if (fabs(sample_diff) >= 2.0 / rate)
return 0;
/* Align the offset to the reference sample */
if ((ref_offset - offset) >= 0.0)
shift = (long)((ref_offset - offset) * rate + 0.5) / (double)rate;
else
shift = (long)((ref_offset - offset) * rate - 0.5) / (double)rate;
offset += shift;
if (fabs(ref_offset - offset) >= 0.2 / rate)
return 0;
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
second, offset, ref_offset - offset, sample_diff);
#endif
} else {
/* Ignore the pulse if we are not well synchronized */
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
distance = fabs(root_delay) / 2 + root_dispersion;
if (!is_synchronised || distance >= 0.5 / rate) {
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse dropped second=%.9f sync=%d dist=%.9f",
second, is_synchronised, distance);
#endif
/* Drop also all stored samples */
filter_reset(&instance->filter);
return 0;
}
}
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f",
second, 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->last = -1;
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;
filter->last = filter->index;
if (filter->used < filter->length)
filter->used++;
filter->samples[filter->index].sample_time = *sample_time;
filter->samples[filter->index].offset = offset;
}
static int
filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset)
{
if (filter->last < 0)
return 0;
*sample_time = filter->samples[filter->last].sample_time;
*offset = filter->samples[filter->last].offset;
return 1;
}
static int
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
}
}

71
refclock.h Normal file
View File

@@ -0,0 +1,71 @@
/*
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;
unsigned long lock_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 char *RCL_GetDriverOption(RCL_Instance instance, char *name);
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
#endif

163
refclock_pps.c Normal file
View File

@@ -0,0 +1,163 @@
/*
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;
path = RCL_GetDriverParameter(instance);
edge_clear = RCL_GetDriverOption(instance, "clear") ? 1 : 0;
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

121
refclock_shm.c Normal file
View File

@@ -0,0 +1,121 @@
/*
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, perm;
char *s;
struct shmTime *shm;
param = atoi(RCL_GetDriverParameter(instance));
s = RCL_GetDriverOption(instance, "perm");
perm = s ? strtol(s, NULL, 8) & 0777 : 0600;
id = shmget(SHMKEY + param, sizeof (struct shmTime), IPC_CREAT | perm);
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) 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
@@ -19,7 +20,7 @@
*
* 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.,
* 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 local_stratum;
static NTP_Leap our_leap_status;
static int our_leap_sec;
static int our_stratum;
static unsigned long our_ref_id;
static IPAddr our_ref_ip;
struct timeval our_ref_time; /* Stored relative to reference, NOT local time */
static double our_offset;
static double our_skew;
@@ -58,6 +61,10 @@ static double max_update_skew;
/* Flag indicating that we are initialised */
static int initialised = 0;
/* Threshold and update limit for stepping clock */
static int make_step_limit;
static double make_step_threshold;
/* Flag and threshold for logging clock changes to syslog */
static int do_log_change;
static double log_change_threshold;
@@ -84,9 +91,6 @@ static unsigned long logwrites = 0;
/* ================================================== */
/* Day number of 1 Jan 1970 */
#define MJD_1970 40587
/* Reference ID supplied when we are locally referenced */
#define LOCAL_REFERENCE_ID 0x7f7f0101UL
@@ -102,7 +106,8 @@ REF_Initialise(void)
double our_frequency_ppm;
are_we_synchronised = 0;
our_leap_status = LEAP_Normal;
our_leap_status = LEAP_Unsynchronised;
our_leap_sec = 0;
initialised = 1;
our_root_dispersion = 1.0;
our_root_delay = 1.0;
@@ -160,6 +165,7 @@ REF_Initialise(void)
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
CNF_GetLogChange(&do_log_change, &log_change_threshold);
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
@@ -176,6 +182,10 @@ REF_Initialise(void)
void
REF_Finalise(void)
{
if (our_leap_sec) {
LCL_SetLeap(0);
}
if (logfile) {
fclose(logfile);
}
@@ -238,7 +248,9 @@ update_drift_file(double freq_ppm, double skew)
/* Clone the file attributes from the existing file if there is one. */
if (!stat(drift_file,&buf)) {
chown(temp_drift_file,buf.st_uid,buf.st_gid);
if (chown(temp_drift_file,buf.st_uid,buf.st_gid)) {
LOG(LOGS_WARN, LOGF_Reference, "Could not change ownership of temporary driftfile %s.tmp", drift_file);
}
chmod(temp_drift_file,buf.st_mode&0777);
}
@@ -311,11 +323,83 @@ maybe_log_offset(double offset)
/* ================================================== */
static void
maybe_make_step()
{
if (make_step_limit == 0) {
return;
} else if (make_step_limit > 0) {
make_step_limit--;
}
LCL_MakeStep(make_step_threshold);
}
/* ================================================== */
static void
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;
}
/* ================================================== */
static void
write_log(struct timeval *ref_time, char *ref, int stratum, double freq, double skew, double offset)
{
if (logfile) {
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"=======================================================================\n"
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset\n"
"=======================================================================\n");
}
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(ref_time->tv_sec), ref, stratum, freq, skew, offset);
fflush(logfile);
}
}
/* ================================================== */
void
REF_SetReference(int stratum,
NTP_Leap leap,
unsigned long ref_id,
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
double frequency,
@@ -335,6 +419,12 @@ REF_SetReference(int stratum,
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
processing, there is a remote chance that the skew argument is a
'not a number'. If such a quantity gets propagated into the
@@ -356,13 +446,18 @@ REF_SetReference(int stratum,
are_we_synchronised = 1;
our_stratum = stratum + 1;
our_leap_status = leap;
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_offset = offset;
our_root_delay = root_delay;
our_root_dispersion = root_dispersion;
update_leap_status(leap);
/* Eliminate updates that are based on totally unreliable frequency
information */
@@ -410,27 +505,16 @@ REF_SetReference(int stratum,
our_residual_freq = frequency;
}
maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
if (logfile) {
if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"=======================================================================\n"
" Date (UTC) Time IP Address St Freq ppm Skew ppm Offset\n"
"=======================================================================\n");
}
fprintf(logfile, "%s %-15s %2d %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(ref_time->tv_sec),
UTI_IPToDottedQuad(our_ref_id),
write_log(ref_time,
our_ref_ip.family != IPADDR_UNSPEC ? UTI_IPToString(&our_ref_ip) : UTI_RefidToString(our_ref_id),
our_stratum,
abs_freq_ppm,
1.0e6*our_skew,
our_offset);
fflush(logfile);
}
if (drift_file) {
update_drift_file(abs_freq_ppm, our_skew);
@@ -454,7 +538,6 @@ REF_SetManualReference
double skew
)
{
int millisecond;
double abs_freq_ppm;
/* We are not synchronised to an external source, as such. This is
@@ -467,23 +550,17 @@ REF_SetManualReference
maybe_log_offset(offset);
LCL_AccumulateFrequencyAndOffset(frequency, offset);
maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
if (logfile) {
millisecond = ref_time->tv_usec / 1000;
fprintf(logfile, "%5s %-15s %2d %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(ref_time->tv_sec),
write_log(ref_time,
"127.127.1.1",
our_stratum,
abs_freq_ppm,
1.0e6*our_skew,
our_offset);
fflush(logfile);
}
if (drift_file) {
update_drift_file(abs_freq_ppm, our_skew);
}
@@ -495,28 +572,23 @@ void
REF_SetUnsynchronised(void)
{
/* Variables required for logging to statistics log */
int millisecond;
struct timeval now;
double local_clock_err;
assert(initialised);
if (logfile) {
LCL_ReadCookedTime(&now, &local_clock_err);
LCL_ReadCookedTime(&now, &local_clock_err);
millisecond = now.tv_usec / 1000;
fprintf(logfile, "%s %-15s 0 %10.3f %10.3f %10.3e\n",
UTI_TimeToLogForm(now.tv_sec),
write_log(&now,
"0.0.0.0",
0,
LCL_ReadAbsoluteFrequency(),
1.0e6*our_skew,
0.0);
fflush(logfile);
}
are_we_synchronised = 0;
update_leap_status(LEAP_Unsynchronised);
}
/* ================================================== */
@@ -636,6 +708,14 @@ REF_DisableLocal(void)
/* ================================================== */
int
REF_IsLocalActive(void)
{
return !are_we_synchronised && enable_local_stratum;
}
/* ================================================== */
void
REF_GetTrackingReport(RPT_TrackingReport *rep)
{
@@ -654,9 +734,10 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed;
rep->ref_id = our_ref_id;
rep->ip_addr = our_ref_ip;
rep->stratum = our_stratum;
rep->ref_time = our_ref_time;
UTI_DoubleToTimeval(correction, &rep->current_correction);
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 1.0e6 * our_residual_freq;
rep->skew_ppm = 1.0e6 * our_skew;
@@ -666,9 +747,10 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
} else if (enable_local_stratum) {
rep->ref_id = LOCAL_REFERENCE_ID;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = local_stratum;
rep->ref_time = now_cooked;
UTI_DoubleToTimeval(correction, &rep->current_correction);
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_ppm = 0.0;
rep->skew_ppm = 0.0;
@@ -678,10 +760,11 @@ REF_GetTrackingReport(RPT_TrackingReport *rep)
} else {
rep->ref_id = 0UL;
rep->ip_addr.family = IPADDR_UNSPEC;
rep->stratum = 0;
rep->ref_time.tv_sec = 0;
rep->ref_time.tv_usec = 0;
UTI_DoubleToTimeval(correction, &rep->current_correction);
rep->current_correction = correction;
rep->freq_ppm = LCL_ReadAbsoluteFrequency();
rep->resid_freq_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
* 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,
NTP_Leap leap,
unsigned long ref_id,
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
double frequency,
@@ -139,6 +140,7 @@ extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
extern void REF_EnableLocal(int stratum);
extern void REF_DisableLocal(void);
extern int REF_IsLocalActive(void);
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
* 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;
r = v;
do {
while (x[l] < piv) l++;
while (x[l] < piv && l < v) l++;
while (x[r] > piv) r--;
if (r <= l) break;
EXCH(x[l], x[r]);

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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
#include "sysincl.h"
#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
int stratum;
int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_OTHER} state;
unsigned long latest_meas_ago; /* seconds */
long orig_latest_meas; /* microseconds (us) */
long latest_meas; /* us */
unsigned long latest_meas_err; /* us */
long est_offset; /* us */
unsigned long est_offset_err; /* us */
long resid_freq; /* ppm * 1000 */
unsigned long resid_skew; /* ppm * 1000 */
double orig_latest_meas; /* seconds */
double latest_meas; /* seconds */
double latest_meas_err; /* seconds */
} RPT_SourceReport ;
typedef struct {
unsigned long ref_id;
IPAddr ip_addr;
unsigned long stratum;
struct timeval ref_time;
struct timeval current_correction;
double current_correction;
double freq_ppm;
double resid_freq_ppm;
double skew_ppm;
@@ -65,17 +63,20 @@ typedef struct {
} RPT_TrackingReport;
typedef struct {
unsigned long ip_addr;
unsigned long ref_id;
IPAddr ip_addr;
unsigned long n_samples;
unsigned long n_runs;
unsigned long span_seconds;
double resid_freq_ppm;
double skew_ppm;
double sd_us;
double sd;
double est_offset;
double est_offset_err;
} RPT_SourcestatsReport;
typedef struct {
unsigned long ref_time;
struct timeval ref_time;
unsigned short n_samples;
unsigned short n_runs;
unsigned long span_seconds;
@@ -94,7 +95,7 @@ typedef struct {
} RPT_ClientAccess_Report;
typedef struct {
unsigned long ip_addr;
IPAddr ip_addr;
unsigned long client_hits;
unsigned long peer_hits;
unsigned long cmd_hits_auth;
@@ -105,7 +106,7 @@ typedef struct {
} RPT_ClientAccessByIndex_Report;
typedef struct {
time_t when;
struct timeval when;
double slewed_offset;
double orig_offset;
double residual;

2
rtc.c
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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
* 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 SCH_TimeoutID timeout_id;
static int skip_interrupts;
/* ================================================== */
/* Maximum number of samples held */
@@ -509,7 +511,9 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
/* Clone the file attributes from the existing file if there is one. */
if (!stat(coefs_file_name,&buf)) {
chown(temp_coefs_file_name,buf.st_uid,buf.st_gid);
if (chown(temp_coefs_file_name,buf.st_uid,buf.st_gid)) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not change ownership of temporary RTC file %s.tmp", coefs_file_name);
}
chmod(temp_coefs_file_name,buf.st_mode&0777);
}
@@ -627,16 +631,11 @@ RTC_Linux_Initialise(void)
direc = CNF_GetLogDir();
if (!mkdir_and_parents(direc)) {
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not create directory %s", direc);
logfile = NULL;
} else {
logfilename = MallocArray(char, 2 + strlen(direc) + strlen(RTC_LOG));
strcpy(logfilename, direc);
strcat(logfilename, "/");
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 +665,7 @@ RTC_Linux_Finalise(void)
if (logfile) {
fclose(logfile);
}
Free(logfilename);
}
/* ================================================== */
@@ -682,6 +681,7 @@ switch_interrupts(int onoff)
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno));
return;
}
skip_interrupts = 1;
} else {
status = ioctl(fd, RTC_UIE_OFF, 0);
if (status < 0) {
@@ -837,7 +837,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;
if (((logwrites++) % 32) == 0) {
@@ -869,12 +879,10 @@ read_from_device(void *any)
struct rtc_time rtc_raw;
struct tm rtc_tm;
time_t rtc_t;
double read_err;
int error = 0;
status = read(fd, &data, sizeof(data));
if (operating_mode == OM_NORMAL)
status = read(fd, &data, sizeof(data));
if (status < 0) {
/* This looks like a bad error : the file descriptor was indicating it was
* ready to read but we couldn't read anything. Give up. */
@@ -891,13 +899,19 @@ read_from_device(void *any)
return;
}
if (skip_interrupts > 0) {
/* Wait for the next interrupt, this one may be bogus */
skip_interrupts--;
return;
}
if ((data & RTC_UIE) == RTC_UIE) {
/* Update interrupt detected */
/* Read RTC time, sandwiched between two polls of the system clock
so we can bound any error. */
LCL_ReadCookedTime(&sys_time, &read_err);
SCH_GetFileReadyTime(&sys_time);
status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status < 0) {
@@ -1104,7 +1118,8 @@ RTC_Linux_TimePreInit(void)
int
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_runs = n_runs;
if (n_samples > 1) {
@@ -1169,12 +1184,9 @@ RTC_Linux_Trim(void)
void
RTC_Linux_CycleLogFile(void)
{
if (logfile && logfilename) {
if (logfile) {
fclose(logfile);
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not reopen logfile %s", logfilename);
}
logfile = NULL;
logwrites = 0;
}
}

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************

29
sched.c
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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];
/* Last timestamp when a file descriptor became readable */
static struct timeval last_fdready;
/* ================================================== */
/* 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
static TimerQueueEntry *
@@ -429,7 +440,7 @@ dispatch_timeouts(struct timeval *now) {
TimerQueueEntry *ptr;
int n_done = 0;
while ((n_timer_queue_entries > 0) &&
if ((n_timer_queue_entries > 0) &&
(UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
ptr = timer_queue.next;
@@ -510,10 +521,11 @@ handle_slew(struct timeval *raw,
void
SCH_MainLoop(void)
{
fd_set rd, wr, ex;
fd_set rd;
int status;
struct timeval tv, *ptv;
struct timeval now;
double err;
if (!initialised) {
CROAK("Should be initialised");
@@ -524,11 +536,6 @@ SCH_MainLoop(void)
/* Copy current set of read file descriptors */
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
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
@@ -555,13 +562,15 @@ SCH_MainLoop(void)
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) {
CROAK("Status < 0 after select");
if (!need_to_exit)
CROAK("Status < 0 after select");
} else if (status > 0) {
/* A file descriptor is ready to read */
LCL_ReadCookedTime(&last_fdready, &err);
dispatch_filehandlers(status, &rd);
} else {

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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);
/* 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 */
extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);

128
sources.c
View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
(i.e. its IP address, NOT the
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
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 */
SRC_Status status;
/* Type of the source */
SRC_Type type;
struct SelectInfo sel_info;
};
@@ -126,6 +130,8 @@ static int selected_source_index; /* Which source index is currently
static void
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
double doffset, int is_step_change, void *anything);
static char *
source_to_string(SRC_Instance inst);
/* ================================================== */
/* Initialisation function */
@@ -155,7 +161,7 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of
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;
@@ -164,7 +170,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
}
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) {
/* Reallocate memory */
@@ -184,8 +190,10 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
result->index = n_sources;
result->leap_status = LEAP_Normal;
result->ref_id = ref_id;
result->ip_addr = addr;
result->reachable = 0;
result->status = SRC_BAD_STATS;
result->type = type;
n_sources++;
@@ -280,7 +288,7 @@ void SRC_AccumulateSample
#ifdef TRACEON
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
/* 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;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s", UTI_IPToDottedQuad(inst->ref_id));
LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
#endif
/* Don't do selection at this point, though - that will come about
@@ -316,7 +324,7 @@ SRC_UnsetReachable(SRC_Instance inst)
inst->reachable = 0;
#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)":"");
#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
of sources we are holding.
@@ -418,7 +442,7 @@ SRC_SelectSource(unsigned long match_addr)
#if 0
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->lo_limit, si->hi_limit);
#endif
@@ -491,7 +515,7 @@ SRC_SelectSource(unsigned long match_addr)
for (i=0; i<n_endpoints; i++) {
#if 0
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
switch(sort_list[i].tag) {
case LOW:
@@ -565,12 +589,12 @@ SRC_SelectSource(unsigned long match_addr)
sel_sources[n_sel_sources++] = i;
#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
} else {
sources[i]->status = SRC_FALSETICKER;
#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
}
}
@@ -603,7 +627,7 @@ SRC_SelectSource(unsigned long match_addr)
sel_sources[i] = INVALID_SOURCE;
sources[index]->status = SRC_JITTERY;
#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
}
}
@@ -632,33 +656,36 @@ SRC_SelectSource(unsigned long match_addr)
if (stratum < min_stratum) min_stratum = stratum;
}
/* Find the best source with minimum stratum */
min_distance_index = INVALID_SOURCE;
for (i=0; i<n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->sel_info.stratum == min_stratum) {
if ((min_distance_index == INVALID_SOURCE) ||
(sources[index]->sel_info.root_distance < min_distance)) {
min_distance = sources[index]->sel_info.root_distance;
min_distance_index = index;
}
}
}
#if 0
LOG(LOGS_INFO, LOGF_Sources, "min_stratum=%d", min_stratum);
#endif
/* Does the current source have this stratum and is it still a
survivor? */
/* 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.stratum > min_stratum) ||
(sources[selected_source_index]->sel_info.root_distance > 10 * min_distance)) {
/* We have to elect a new synchronisation source */
min_distance_index = INVALID_SOURCE;
for (i=0; i<n_sel_sources; i++) {
index = sel_sources[i];
if (sources[index]->sel_info.stratum == min_stratum) {
if ((min_distance_index == INVALID_SOURCE) ||
(sources[index]->sel_info.root_distance < min_distance)) {
min_distance = sources[index]->sel_info.root_distance;
min_distance_index = index;
}
}
}
selected_source_index = min_distance_index;
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
@@ -687,11 +714,29 @@ SRC_SelectSource(unsigned long match_addr)
total_root_dispersion = (src_accrued_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) ||
(match_addr == sources[selected_source_index]->ref_id)) {
REF_SetReference(min_stratum, leap_status,
sources[selected_source_index]->ref_id,
sources[selected_source_index]->ip_addr,
&now,
src_offset,
src_frequency,
@@ -873,7 +918,16 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
return 0;
} else {
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) {
case SRC_SYNC:
report->state = RPT_SYNC;
@@ -902,7 +956,7 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now)
/* ================================================== */
int
SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report, struct timeval *now)
{
SRC_Instance src;
@@ -910,14 +964,28 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
return 0;
} else {
src = sources[index];
report->ip_addr = src->ref_id;
SST_DoSourcestatsReport(src->stats, report);
report->ref_id = src->ref_id;
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;
}
}
/* ================================================== */
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 result = SRC_Skew_Nochange;

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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 */
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
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.
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_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 {
SRC_Skew_Decrease,

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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 {
/* 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;
IPAddr *ip_addr;
/* Number of samples currently stored. sample[n_samples-1] is the
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 */
SST_Stats
SST_CreateInstance(unsigned long refid)
SST_CreateInstance(unsigned long refid, IPAddr *addr)
{
SST_Stats inst;
inst = MallocNew(struct SST_Stats_Record);
inst->refid = refid;
inst->ip_addr = addr;
inst->n_samples = 0;
inst->estimated_frequency = 0;
inst->skew = 2000.0e-6;
inst->skew_dirn = SST_Skew_Nochange;
inst->estimated_offset = 0.0;
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->nruns = 0;
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",
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),
inst->estimated_offset,
inst->estimated_offset_sd,
@@ -721,8 +725,12 @@ SST_PredictOffset(SST_Stats inst, struct timeval *when)
if (inst->n_samples < 3) {
/* We don't have any useful statistics, and presumably the poll
interval is minimal. We can't do any useful prediction other
than use the latest sample */
return inst->offsets[inst->n_samples - 1];
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];
} else {
return 0.0;
}
} else {
UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
return inst->estimated_offset + elapsed * inst->estimated_frequency;
@@ -837,47 +845,24 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
void
SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now)
{
int n, nb;
double est_offset, est_err, elapsed, sample_elapsed;
int n;
struct timeval ago;
if (inst->n_samples > 0) {
n = inst->n_samples - 1;
report->orig_latest_meas = (long)(0.5 + 1.0e6 * inst->orig_offsets[n]);
report->latest_meas = (long)(0.5 + 1.0e6 * inst->offsets[n]);
report->latest_meas_err = (unsigned long)(0.5 + 1.0e6 * (0.5*inst->root_delays[n] + inst->root_dispersions[n]));
report->orig_latest_meas = inst->orig_offsets[n];
report->latest_meas = inst->offsets[n];
report->latest_meas_err = 0.5*inst->root_delays[n] + inst->root_dispersions[n];
report->stratum = inst->strata[n];
UTI_DiffTimevals(&ago, now, &inst->sample_times[n]);
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 {
report->latest_meas_ago = 86400 * 365 * 10;
report->orig_latest_meas = 0;
report->latest_meas = 0;
report->latest_meas_err = 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
SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report)
SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now)
{
double dspan;
int n;
double elapsed, sample_elapsed;
int n, nb;
report->n_samples = inst->n_samples;
report->n_runs = inst->nruns;
@@ -904,13 +890,28 @@ SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report)
n = inst->n_samples - 1;
UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[n], &inst->sample_times[0]);
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 {
report->span_seconds = 0;
report->est_offset = 0;
report->est_offset_err = 0;
}
report->resid_freq_ppm = 1.0e6 * inst->estimated_frequency;
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
* 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);
/* 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. */
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_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report);
extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now);
typedef enum {
SST_Skew_Decrease,

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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
* 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 "logging.h"
#if defined (LINUX)
#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
* 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 */
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 */

View File

@@ -7,6 +7,8 @@
**********************************************************************
* 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
* 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
* 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 <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 "sys_linux.h"
#include "sched.h"
@@ -84,10 +105,11 @@ static int version_major;
static int version_minor;
static int version_patchlevel;
/* Flag indicating whether adjtimex() with txc.modes equal to zero
returns the remaining time adjustment or not. If not we have to read
the outstanding adjustment by setting it to zero, examining the return
value and setting the outstanding adjustment back again. */
/* Flag indicating whether adjtimex() returns the remaining time adjustment
or not. If not we have to read the outstanding adjustment by setting it to
zero, examining the return value and setting the outstanding adjustment back
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;
@@ -106,10 +128,24 @@ our_round(double x) {
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 */
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
run at the moment */
static int fast_slewing;
@@ -233,16 +269,28 @@ initiate_slew(void)
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) {
/* Use adjtime to do the shift */
offset = (long)(0.5 + 1.0e6*(-offset_register));
offset = our_lround(1.0e6 * -offset_register);
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in initiate_slew");
offset_register += offset * 1e-6;
if (offset != 0) {
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in initiate_slew");
}
slow_slewing = 1;
}
offset_register = 0.0;
} else {
/* If the system clock has a high drift rate, the combination of
@@ -305,7 +353,9 @@ initiate_slew(void)
fast_slewing = 1;
slew_start_tv = T0a;
/* Set up timeout for end of slew */
/* Set up timeout for end of slew, limit to one week */
if (dseconds > 3600 * 24 * 7)
dseconds = 3600 * 24 * 7;
UTI_AddDoubleToTimeval(&T0a, dseconds, &end_of_slew);
slew_timeout_id = SCH_AddTimeout(&end_of_slew, handle_end_of_slew, NULL);
@@ -353,19 +403,9 @@ abort_slew(void)
static void
accrue_offset(double offset)
{
long toffset;
/* Add the new offset to the register */
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) {
initiate_slew();
} /* Otherwise, when the fast slew completes, any other stuff
@@ -511,28 +551,47 @@ get_offset_correction(struct timeval *raw,
double fast_slew_duration;
double fast_slew_achieved;
double fast_slew_remaining;
long offset;
long offset, toffset;
if (have_readonly_adjtime) {
if (TMX_GetOffsetLeft(&offset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
}
adjtime_left = (double)offset / 1.0e6;
} else {
if (!slow_slewing) {
offset = 0;
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in get_offset_correction");
} 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");
}
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);
}
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 (offset == 0) {
/* adjtime slew has finished */
slow_slewing = 0;
}
}
adjtime_left = (double)offset / 1.0e6;
if (fast_slewing) {
UTI_DiffTimevalsToDouble(&fast_slew_duration, raw, &slew_start_tv);
fast_slew_achieved = delta_total_tick * fast_slew_duration /
@@ -550,34 +609,14 @@ get_offset_correction(struct timeval *raw,
/* ================================================== */
static void
immediate_step(void)
set_leap(int leap)
{
struct timeval old_time, new_time;
struct timezone tz;
long offset;
if (fast_slewing) {
abort_slew();
if (TMX_SetLeap(leap) < 0) {
LOG_FATAL(LOGF_SysLinux, "adjtimex() failed in set_leap");
}
offset = 0;
if (TMX_ApplyOffset(&offset) < 0) {
CROAK("adjtimex() failed in immediate_step");
}
offset_register -= (double) offset / 1.0e6;
if (gettimeofday(&old_time, &tz) < 0) {
CROAK("gettimeofday() failed in immediate_step");
}
UTI_AddDoubleToTimeval(&old_time, -offset_register, &new_time);
if (settimeofday(&new_time, &tz) < 0) {
CROAK("settimeofday() failed in immediate_step");
}
offset_register = 0.0;
LOG(LOGS_INFO, LOGF_SysLinux, "System clock status set to %s leap second",
leap ? (leap > 0 ? "insert" : "delete") : "not insert/delete");
return;
}
@@ -762,13 +801,19 @@ get_version_specific_details(void)
case 4:
case 5:
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
otherwise :-) */
case 7:
case 8:
/* These seem to be like 2.0.32 */
freq_scale = (hz==100) ? (128.0 / 128.125) : basic_freq_scale;
have_readonly_adjtime = 0;
/* These don't need scaling */
freq_scale = 1.0;
have_readonly_adjtime = 2;
break;
default:
LOG_FATAL(LOGF_SysLinux, "Kernel version not supported yet, sorry.");
@@ -805,7 +850,7 @@ SYS_Linux_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset,
get_offset_correction, immediate_step);
get_offset_correction, set_leap);
}
/* ================================================== */
@@ -831,6 +876,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 */
/* vim:ts=8

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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_DropRoot(char *user);
extern void SYS_Linux_MemLockAll(int LockAll);
extern void SYS_Linux_SetScheduler(int SchedPriority);
#endif /* GOT_SYS_LINUX_H */

View File

@@ -20,7 +20,7 @@
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
@@ -285,7 +285,7 @@ SYS_NetBSD_Initialise(void)
kvm_t *kt;
FILE *fp;
kt = kvm_open(NULL, NULL, NULL, O_RDWR, NULL);
kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
if (!kt) {
CROAK("Cannot open kvm\n");
}
@@ -299,7 +299,8 @@ SYS_NetBSD_Initialise(void)
}
if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {
CROAK("Cannot read from _bigadj\n");
/* kernel doesn't have the symbol, use one second instead */
kern_bigadj = 1000000;
}
kvm_close(kt);
@@ -308,7 +309,8 @@ SYS_NetBSD_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */);
get_offset_correction,
NULL /* set_leap */);
}

View File

@@ -20,7 +20,7 @@
*
* 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.,
* 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
* 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,
accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */);
get_offset_correction,
NULL /* set_leap */);
/* Turn off the kernel switch that keeps the system clock in step
with the non-volatile clock */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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,
(char *)(&(on_off ? default_tickadj : our_tickadj)),
(char *)(on_off ? &default_tickadj : &our_tickadj),
sizeof(unsigned long)) < 0) {
LOG(LOGS_ERR, LOGF_SysSunOS, "Cannot write to _tickadj");
kvm_close(kt);
@@ -395,7 +395,8 @@ SYS_SunOS_Initialise(void)
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
accrue_offset, apply_step_offset,
get_offset_correction, NULL /* immediate_step */);
get_offset_correction,
NULL /* set_leap */);
/* Turn off the kernel switch that keeps the system clock in step
with the non-volatile clock */

View File

@@ -19,7 +19,7 @@
*
* 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.,
* 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
* 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
#ifdef HAVE_IPV6
/* For inet_ntop() */
#include <arpa/inet.h>
#endif
#if defined (SOLARIS) || defined(SUNOS)
/* Only needed on these platforms, and doesn't exist on some Linux
versions. */

349
util.c
View File

@@ -7,6 +7,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
* 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
@@ -19,7 +20,7 @@
*
* 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.,
* 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 "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) {
return +1;
} else {
if (a->tv_sec != b->tv_sec) {
CROAK("a->tv_sec != b->tv_sec");
}
if (a->tv_usec < b->tv_usec) {
return -1;
} else if (a->tv_usec > b->tv_usec) {
return +1;
} else {
if (a->tv_usec != b->tv_usec) {
CROAK("a->tv_usec != b->tv_usec");
}
return 0;
}
}
CROAK("Impossible"); /* Shouldn't be able to fall through. */
}
/* ================================================== */
@@ -87,15 +81,17 @@ UTI_CompareTimevals(struct timeval *a, struct timeval *b)
INLINE_STATIC void
UTI_NormaliseTimeval(struct timeval *x)
{
while (x->tv_usec >= 1000000) {
++x->tv_sec;
x->tv_usec -= 1000000;
/* Reduce tv_usec to within +-1000000 of zero. JGH */
if ((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_usec += 1000000;
}
}
}
@@ -110,17 +106,9 @@ UTI_DiffTimevals(struct timeval *result,
result->tv_usec = a->tv_usec - b->tv_usec;
/* Correct microseconds field to bring it into the range
[0,1000000) */
(0,1000000) */
while (result->tv_usec < 0) {
result->tv_usec += 1000000;
--result->tv_sec;
}
while (result->tv_usec > 999999) {
result->tv_usec -= 1000000;
++result->tv_sec;
}
UTI_NormaliseTimeval(result); /* JGH */
return;
}
@@ -191,7 +179,7 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
}
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_usec = earlier->tv_usec + tvhalf.tv_usec;
@@ -199,17 +187,7 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
/* Bring into range */
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,189 @@ UTI_TimestampToString(NTP_int64 *ts)
/* ================================================== */
char *
UTI_IPToDottedQuad(unsigned long ip)
UTI_RefidToString(unsigned long ref_id)
{
unsigned long a, b, c, d;
char *result;
a = (ip>>24) & 0xff;
b = (ip>>16) & 0xff;
c = (ip>> 8) & 0xff;
d = (ip>> 0) & 0xff;
unsigned int i, j, c;
char buf[5], *result;
for (i = j = 0; i < 4; i++) {
c = (ref_id >> (24 - i * 8)) & 0xff;
if (isprint(c))
buf[j++] = c;
}
buf[j] = '\0';
result = NEXT_BUFFER;
snprintf(result, BUFFER_LENGTH, "%ld.%ld.%ld.%ld", a, b, c, d);
snprintf(result, BUFFER_LENGTH, "%s", buf);
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;
b = (ip>>16) & 0xff;
c = (ip>> 8) & 0xff;
d = (ip>> 0) & 0xff;
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;
}
/* ================================================== */
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 *
UTI_TimeToLogForm(time_t t)
{
@@ -346,19 +492,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
croak(const char *file, int line, const char *msg)
void
UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
{
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 */
uint32_t sec_low, sec_high;
dest->tv_usec = ntohl(src->tv_nsec) / 1000;
sec_high = ntohl(src->tv_sec_high);
sec_low = ntohl(src->tv_sec_low);
/* 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
* 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 "addressing.h"
#include "ntp.h"
#include "candm.h"
/* Convert a timeval into a floating point number of seconds */
extern void UTI_TimevalToDouble(struct timeval *a, double *b);
@@ -72,8 +74,17 @@ extern char *UTI_TimevalToString(struct timeval *tv);
diagnostic display */
extern char *UTI_TimestampToString(NTP_int64 *ts);
/* Convert an IP address to dotted quad notation, for diagnostics */
extern char *UTI_IPToDottedQuad(unsigned long ip);
/* Convert ref_id into a temporary string, for diagnostics */
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);
@@ -85,14 +96,11 @@ extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *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__)
#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
extern double UTI_FloatNetworkToHost(Float x);
extern Float UTI_FloatHostToNetwork(double x);
#if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static

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