mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 18:35:06 -05:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe2dbfb6cb | ||
|
|
032ac800aa | ||
|
|
5e86eeacfb | ||
|
|
75b7d33fb7 | ||
|
|
a6e532442b | ||
|
|
a123a12f59 | ||
|
|
f261251a9b | ||
|
|
a0e1154bfb | ||
|
|
e261278a5c | ||
|
|
dbb550e6db | ||
|
|
27a9b0e7b1 | ||
|
|
8a00758cf5 | ||
|
|
15e154c09d | ||
|
|
52d0c9a057 | ||
|
|
4593471ad5 | ||
|
|
a3288d4284 | ||
|
|
22f0da4da6 | ||
|
|
baa977a3ed | ||
|
|
b4b2491015 | ||
|
|
902ed3c694 | ||
|
|
4a9205b341 | ||
|
|
8a4313c32b | ||
|
|
b32432c232 | ||
|
|
feb86e336a | ||
|
|
7817bef866 | ||
|
|
2dd9f3373b | ||
|
|
5b1a8705cf | ||
|
|
b49470117d | ||
|
|
84f8463f2a | ||
|
|
78f37e726a | ||
|
|
9d83369348 | ||
|
|
365834535e | ||
|
|
63ae72e009 | ||
|
|
4599e2b508 | ||
|
|
395c33208c | ||
|
|
ff423304ed | ||
|
|
00a77fca52 | ||
|
|
49bd8cfab3 | ||
|
|
6031b35a7a | ||
|
|
1f6e508a3d | ||
|
|
fb538c3947 | ||
|
|
6af87bd8f6 | ||
|
|
e248a57d00 | ||
|
|
41580fe589 | ||
|
|
1c128b0076 | ||
|
|
5a3d85b4ff | ||
|
|
0f9892fe7a | ||
|
|
19651dc767 | ||
|
|
e63c51c6c0 | ||
|
|
d1c7e1bb6c | ||
|
|
1a8514a1a8 | ||
|
|
7c53aca486 | ||
|
|
e9ae3d0a0b | ||
|
|
159a9519e8 | ||
|
|
5939fcb2eb | ||
|
|
0601540d41 | ||
|
|
b83861c7c2 | ||
|
|
4d6156b549 | ||
|
|
7eae35e15e | ||
|
|
a94380673b | ||
|
|
dce9607d6e | ||
|
|
e3234465e2 | ||
|
|
032838b1b0 | ||
|
|
dd5405a281 | ||
|
|
6d242a33f5 | ||
|
|
3bae6c3202 | ||
|
|
618f372e13 | ||
|
|
8f72155b43 | ||
|
|
bbb6c5d422 | ||
|
|
62fe343990 | ||
|
|
4097ab29c7 | ||
|
|
9c9530c688 | ||
|
|
0a86a8dd0b | ||
|
|
e08870c63c | ||
|
|
6b38523c9c | ||
|
|
77e79e8359 | ||
|
|
e88af337cd | ||
|
|
707b623ea8 | ||
|
|
9716a2ed7e | ||
|
|
fe2cfe1fae | ||
|
|
c6e2eaf7a9 | ||
|
|
a822bcfd67 | ||
|
|
6640993f20 | ||
|
|
f39dc68f84 | ||
|
|
27cfc02468 | ||
|
|
8e23110aec | ||
|
|
f7e08d0c30 | ||
|
|
f2f592fa0d | ||
|
|
465e580a39 | ||
|
|
b4069a4c3b | ||
|
|
352f03d487 | ||
|
|
8cd9e68246 | ||
|
|
5b4e07d658 | ||
|
|
48b6c2aa6b | ||
|
|
1570f97ee2 | ||
|
|
fbd20c429e | ||
|
|
a7892a1a15 | ||
|
|
8265ff2890 | ||
|
|
183d56fd40 | ||
|
|
d06f02be1c | ||
|
|
5a2b38378c | ||
|
|
19f3a6bca8 | ||
|
|
dd4fb511a5 | ||
|
|
3a9e13445f | ||
|
|
67c0f1c08c | ||
|
|
8de55124a8 | ||
|
|
0666d04ab2 | ||
|
|
d87cddd6a5 | ||
|
|
84cbeeadd1 | ||
|
|
eefb5c7552 | ||
|
|
8c0f3f4042 | ||
|
|
735811b2b9 | ||
|
|
923c58485f | ||
|
|
032d1db883 | ||
|
|
75330fdff5 | ||
|
|
ac30bb06ef | ||
|
|
ef3669fe1b | ||
|
|
9416a24f03 | ||
|
|
8b81bfe41d | ||
|
|
96759116e2 | ||
|
|
4aae133c4d | ||
|
|
35e662d810 | ||
|
|
cdc22df903 | ||
|
|
8f9c237010 | ||
|
|
0148ecaea0 | ||
|
|
fd2641bcb9 | ||
|
|
be42b4eeea | ||
|
|
8336f14680 | ||
|
|
bc0aaa9217 | ||
|
|
71aa36aa6e | ||
|
|
2f2446c7dc |
30
COPYING
30
COPYING
@@ -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
22
INSTALL
@@ -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
|
||||
|
||||
90
Makefile.in
90
Makefile.in
@@ -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
37
NEWS
@@ -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
89
README
@@ -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
174
acquire.c
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
28
addressing.h
28
addressing.h
@@ -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 */
|
||||
|
||||
|
||||
212
addrfilt.c
212
addrfilt.c
@@ -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);
|
||||
|
||||
|
||||
14
addrfilt.h
14
addrfilt.h
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
160
candm.h
@@ -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 {
|
||||
|
||||
8
chrony.1
8
chrony.1
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
539
chrony.texi
539
chrony.texi
@@ -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
|
||||
|
||||
@@ -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) */
|
||||
|
||||
|
||||
17
chronyc.1
17
chronyc.1
@@ -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>
|
||||
|
||||
25
chronyd.8
25
chronyd.8
@@ -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
|
||||
|
||||
235
clientlog.c
235
clientlog.c
@@ -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 {
|
||||
|
||||
16
clientlog.h
16
clientlog.h
@@ -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);
|
||||
|
||||
|
||||
8
cmdmon.h
8
cmdmon.h
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
421
conf.c
@@ -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
15
conf.h
@@ -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
370
configure
vendored
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
67
faq.txt
@@ -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 "chrony" 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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
2
keys.c
@@ -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
2
keys.h
@@ -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
47
local.c
@@ -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;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
9
local.h
9
local.h
@@ -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 */
|
||||
|
||||
9
localp.h
9
localp.h
@@ -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 */
|
||||
|
||||
36
logging.c
36
logging.c
@@ -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 */
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
19
logging.h
19
logging.h
@@ -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
62
main.c
@@ -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
2
main.h
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
4
manual.c
4
manual.c
@@ -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;
|
||||
|
||||
2
manual.h
2
manual.h
@@ -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
memory.h
2
memory.h
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
190
nameserv.c
190
nameserv.c
@@ -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;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
11
nameserv.h
11
nameserv.h
@@ -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
2
ntp.h
@@ -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
ntp_core.c
107
ntp_core.c
@@ -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;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -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
367
ntp_io.c
@@ -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);
|
||||
}
|
||||
|
||||
2
ntp_io.h
2
ntp_io.h
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
108
ntp_sources.c
108
ntp_sources.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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
717
refclock.c
Normal 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
71
refclock.h
Normal 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
163
refclock_pps.c
Normal 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, ¶ms) < 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, ¶ms) < 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
121
refclock_shm.c
Normal 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
132
refclock_sock.c
Normal 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
|
||||
};
|
||||
171
reference.c
171
reference.c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
reports.h
31
reports.h
@@ -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
2
rtc.c
@@ -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
2
rtc.h
@@ -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
rtc_linux.c
50
rtc_linux.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
29
sched.c
@@ -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 {
|
||||
|
||||
6
sched.h
6
sched.h
@@ -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
128
sources.c
@@ -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;
|
||||
|
||||
13
sources.h
13
sources.h
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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
39
sys.c
@@ -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
8
sys.h
@@ -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 */
|
||||
|
||||
277
sys_linux.c
277
sys_linux.c
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
10
sys_netbsd.c
10
sys_netbsd.c
@@ -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 */);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
|
||||
@@ -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
349
util.c
@@ -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
28
util.h
@@ -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
Reference in New Issue
Block a user