Compare commits

..

4 Commits

Author SHA1 Message Date
Miroslav Lichvar
d99c4736c2 Update NEWS 2010-02-03 15:13:13 +01:00
Miroslav Lichvar
2f63cf4485 Add option to limit clientlog memory 2010-01-15 12:51:31 +01:00
Miroslav Lichvar
0b710499f9 Limit rate of syslog messages
Error messages caused by incoming packets need to be rate limited
to avoid filling up disk space.
2010-01-15 12:51:26 +01:00
Miroslav Lichvar
7864c7a70c Don't reply to invalid chronyc packets 2010-01-14 14:43:37 +01:00
152 changed files with 10421 additions and 20348 deletions

17
.gitignore vendored
View File

@@ -1,21 +1,6 @@
.deps
.vimrc
*.o
*.swp *.swp
RELEASES *.o
Makefile Makefile
chrony.conf.5
chrony.info
chrony.html
chrony.texi
chrony.txt
chronyc chronyc
chronyc.1
chronyd chronyd
chronyd.8
config.h
config.log
tags
version.h version.h
/test/simulation/clknetsim
/test/simulation/tmp

30
COPYING
View File

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

89
INSTALL Normal file
View File

@@ -0,0 +1,89 @@
The software is distributed as source code which has to be compiled.
PARTS OF THE SOFTWARE ARE HIGHLY SYSTEM-SPECIFIC AND NON-PORTABLE.
UNLESS YOU ARE RUNNING A SUPPORTED SYSTEM, BE PREPARED FOR SOME
PROGRAMMING!
After unpacking the source code, change directory into it, and type
./configure
This is a shell script that automatically determines the system type.
There is a single optional parameter, --prefix which indicates the
directory tree where the software should be installed. For example,
./configure --prefix=/opt/free
will install the chronyd daemon into /opt/free/sbin and the chronyc
control program into /opt/free/bin. The default value for the prefix
is /usr/local.
The configure script assumes you want to use gcc as your compiler.
If you want to use a different compiler, you can configure this way:
CC=cc CFLAGS=-O ./configure --prefix=/opt/free
for Bourne-family shells, or
setenv CC cc
setenv CFLAGS -O
./configure --prefix=/opt/free
for C-family shells.
If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, the files `options.h' and `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.
Now type
make
to build the programs.
If you want to build the manual in plain text, HTML and info versions, type
make docs
Once the programs have been successfully compiled, they need to be
installed in their target locations. This step normally needs to be
performed by the superuser, and requires the following command to be
entered.
make install
This will install the binaries, plain text manual and manpages.
To install the HTML and info versions of the manual as well, enter the command
make install-docs
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
argument is the location of the file called 'dir'. This will typically be
/usr/info/dir. So the typical command line would be
install-info /usr/local/info/chrony.info /usr/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
network environment in which the computer operates. Typical scenarios
are described in the manual. The simplest case is for a computer with
a permanent Internet connection - suppose you want to use the NTP
server ntp1.foobar.com as your time reference. You would create an
/etc/chrony.conf file containing
server ntp1.foobar.com
driftfile /etc/chrony.drift
and then run /usr/local/sbin/chronyd.

View File

@@ -1,5 +1,9 @@
################################################## ##################################################
# #
# $Header: /cvs/src/chrony/Makefile.in,v 1.48 2003/09/19 22:48:26 richard Exp $
#
# =======================================================================
#
# chronyd/chronyc - Programs for keeping computer clocks accurate. # chronyd/chronyc - Programs for keeping computer clocks accurate.
# #
# Copyright (C) Richard P. Curnow 1997-2003 # Copyright (C) Richard P. Curnow 1997-2003
@@ -15,152 +19,145 @@
# #
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
# #
# ======================================================================= # =======================================================================
# #
# Makefile template # Makefile template
SYSCONFDIR=@SYSCONFDIR@ INSTALL_PREFIX=@INSTALL_PREFIX@
BINDIR=@BINDIR@
SBINDIR=@SBINDIR@
MANDIR=@MANDIR@ MANDIR=@MANDIR@
INFODIR=@INFODIR@ INFODIR=@INFODIR@
DOCDIR=@DOCDIR@
LOCALSTATEDIR=@LOCALSTATEDIR@
CHRONYVARDIR=@CHRONYVARDIR@
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@ CCWARNFLAGS = @CCWARNFLAGS@
CPPFLAGS = @CPPFLAGS@ OPTFLAGS = @CFLAGS@ @EXTRA_DEFS@
DESTDIR= DESTDIR=
HASH_OBJ = @HASH_OBJ@
OBJS = util.o sched.o regress.o local.o \ OBJS = util.o sched.o regress.o local.o \
sys.o main.o ntp_io.o ntp_core.o ntp_sources.o \ sys.o main.o ntp_io.o ntp_core.o ntp_sources.o \
sources.o sourcestats.o reference.o \ sources.o sourcestats.o reference.o \
logging.o conf.o cmdmon.o keys.o \ logging.o conf.o cmdmon.o md5.o keys.o \
nameserv.o nameserv_async.o manual.o addrfilt.o \ nameserv.o acquire.o manual.o addrfilt.o \
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \ cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
broadcast.o refclock.o refclock_phc.o refclock_pps.o \ broadcast.o
refclock_shm.o refclock_sock.o tempcomp.o $(HASH_OBJ)
EXTRA_OBJS=@EXTRA_OBJECTS@ EXTRA_OBJS=@EXTRA_OBJECTS@
CLI_OBJS = client.o nameserv.o getdate.o cmdparse.o \ CLI_OBJS = client.o md5.o nameserv.o getdate.o cmdparse.o \
pktlength.o util.o $(HASH_OBJ) pktlength.o
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS) SRCS = $(patsubst %.o,%.c,$(OBJS))
EXTRA_SRCS = $(patsubst %.o,%.c,$(EXTRA_OBJS))
CLI_SRCS = $(patsubst %.o,%.c,$(CLI_OBJS))
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
EXTRA_LIBS=@EXTRA_LIBS@ EXTRA_LIBS=@EXTRA_LIBS@
EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@ EXTRA_CLI_LIBS=@EXTRA_CLI_LIBS@
DEFS=@SYSDEFS@
CFLAGS = $(CCWARNFLAGS) $(OPTFLAGS)
# Until we have a main procedure we can link, just build object files # Until we have a main procedure we can link, just build object files
# to test compilation # to test compilation
all : chronyd chronyc all : chronyd chronyc
chronyd : $(OBJS) $(EXTRA_OBJS) chronyd : $(OBJS) $(EXTRA_OBJS)
$(CC) $(CFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LIBS) $(EXTRA_LIBS)
chronyc : $(CLI_OBJS) chronyc : $(CLI_OBJS)
$(CC) $(CFLAGS) -o chronyc $(CLI_OBJS) $(LDFLAGS) $(LIBS) $(EXTRA_CLI_LIBS) $(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
client.o : client.c client.o : client.c
$(CC) $(CFLAGS) $(CPPFLAGS) @READLINE_COMPILE@ -c $< $(CC) $(CFLAGS) $(DEFS) @READLINE_COMPILE@ -c $<
$(HASH_OBJ) : $(patsubst %.o,%.c,$(HASH_OBJ)) .depend :
$(CC) $(CFLAGS) $(CPPFLAGS) @HASH_COMPILE@ -c $< gcc -MM $(SRCS) $(EXTRA_SRCS) > .depend
distclean : clean distclean :
-rm -f Makefile -rm -f *.o *.s chronyc chronyd core options.h Makefile *~
-rm -f chrony.conf.5 chrony.texi chronyc.1 chronyd.8
clean : clean :
-rm -f *.o *.s chronyc chronyd core *~ chrony.info chrony.html chrony.txt -rm -f *.o *.s chronyc chronyd core *~
-rm -rf .deps
getdate.c : version.h : version.txt
bison -o getdate.c getdate.y ./mkversion
# This can be used to force regeneration of getdate.c
getdate :
bison -o getdate.c getdate.y
# For install, don't use the install command, because its switches # For install, don't use the install command, because its switches
# seem to vary between systems. # seem to vary between systems.
install: chronyd chronyc chrony.txt install: chronyd chronyc
[ -d $(DESTDIR)$(SYSCONFDIR) ] || mkdir -p $(DESTDIR)$(SYSCONFDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX) ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)
[ -d $(DESTDIR)$(SBINDIR) ] || mkdir -p $(DESTDIR)$(SBINDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX)/sbin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/sbin
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX)/bin ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/bin
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc
[ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1 [ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5 [ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8 [ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony
[ -d $(DESTDIR)$(CHRONYVARDIR) ] || mkdir -p $(DESTDIR)$(CHRONYVARDIR) if [ -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd ; fi
if [ -f $(DESTDIR)$(SBINDIR)/chronyd ]; then rm -f $(DESTDIR)$(SBINDIR)/chronyd ; fi if [ -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ]; then rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc ; fi
if [ -f $(DESTDIR)$(BINDIR)/chronyc ]; then rm -f $(DESTDIR)$(BINDIR)/chronyc ; fi cp chronyd $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd
cp chronyd $(DESTDIR)$(SBINDIR)/chronyd chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/sbin/chronyd
chmod 755 $(DESTDIR)$(SBINDIR)/chronyd cp chronyc $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc
cp chronyc $(DESTDIR)$(BINDIR)/chronyc chmod 555 $(DESTDIR)$(INSTALL_PREFIX)/bin/chronyc
chmod 755 $(DESTDIR)$(BINDIR)/chronyc cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt cp COPYING $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING
cp COPYING $(DESTDIR)$(DOCDIR)/COPYING chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/COPYING
chmod 644 $(DESTDIR)$(DOCDIR)/COPYING cp README $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README
cp README $(DESTDIR)$(DOCDIR)/README chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/README
chmod 644 $(DESTDIR)$(DOCDIR)/README
cp chrony.1 $(DESTDIR)$(MANDIR)/man1 cp chrony.1 $(DESTDIR)$(MANDIR)/man1
chmod 644 $(DESTDIR)$(MANDIR)/man1/chrony.1 chmod 444 $(DESTDIR)$(MANDIR)/man1/chrony.1
cp chronyc.1 $(DESTDIR)$(MANDIR)/man1 cp chronyc.1 $(DESTDIR)$(MANDIR)/man1
chmod 644 $(DESTDIR)$(MANDIR)/man1/chronyc.1 chmod 444 $(DESTDIR)$(MANDIR)/man1/chronyc.1
cp chronyd.8 $(DESTDIR)$(MANDIR)/man8 cp chronyd.8 $(DESTDIR)$(MANDIR)/man8
chmod 644 $(DESTDIR)$(MANDIR)/man8/chronyd.8 chmod 444 $(DESTDIR)$(MANDIR)/man8/chronyd.8
cp chrony.conf.5 $(DESTDIR)$(MANDIR)/man5 cp chrony.conf.5 $(DESTDIR)$(MANDIR)/man5
chmod 644 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5 chmod 444 $(DESTDIR)$(MANDIR)/man5/chrony.conf.5
%.o : %.c %.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< $(CC) $(CFLAGS) $(DEFS) -c $<
%.s : %.c %.s : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -S $< $(CC) $(CFLAGS) $(DEFS) -S $<
check : chronyd chronyc main.o logging.o client.o : version.h
cd test/simulation && ./run
# makeinfo v4 required to generate plain text and html
MAKEINFO:=makeinfo
install-docs : docs install-docs : docs
[ -d $(DESTDIR)$(DOCDIR) ] || mkdir -p $(DESTDIR)$(DOCDIR) [ -d $(DESTDIR)$(INSTALL_PREFIX)/doc ] || mkdir -p $(DESTDIR)$(INSTALL_PREFIX)/doc
cp chrony.txt $(DESTDIR)$(DOCDIR)/chrony.txt cp chrony.txt $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.txt chown root $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
cp chrony.html $(DESTDIR)$(DOCDIR)/chrony.html chmod 444 $(DESTDIR)$(INSTALL_PREFIX)/doc/chrony/chrony.txt
chmod 644 $(DESTDIR)$(DOCDIR)/chrony.html 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)$(INFODIR) ] || mkdir -p $(DESTDIR)$(INFODIR) [ -d $(DESTDIR)$(INFODIR) ] || mkdir -p $(DESTDIR)$(INFODIR)
cp chrony.info* $(DESTDIR)$(INFODIR) cp chrony.info* $(DESTDIR)$(INFODIR)
chmod 644 $(DESTDIR)$(INFODIR)/chrony.info* chown root $(DESTDIR)$(INFODIR)/chrony.info*
chmod 444 $(DESTDIR)$(INFODIR)/chrony.info*
docs : chrony.txt chrony.html chrony.info docs : chrony.txt chrony.html chrony.info
chrony.txt : chrony.texi chrony.txt : chrony.texi
makeinfo --no-headers --number-sections -o chrony.txt chrony.texi $(MAKEINFO) --no-headers --number-sections -o chrony.txt chrony.texi
chrony.html : chrony.texi chrony.html : chrony.texi
command -v texi2html > /dev/null 2>&1 && texi2html chrony.texi || \ $(MAKEINFO) --no-split --html --number-sections -o chrony.html chrony.texi
makeinfo --no-split --html --number-sections -o chrony.html chrony.texi
chrony.info : chrony.texi chrony.info : chrony.texi
makeinfo chrony.texi $(MAKEINFO) chrony.texi
.deps: # This is only relevant if you're maintaining the website!
@mkdir .deps faq.php : faq.txt faqgen.pl
perl faqgen.pl < faq.txt > faq.php
.deps/%.d: %.c | .deps
@$(CC) -MM $(CPPFLAGS) -MT '$(<:%.c=%.o) $@' $< -o $@
-include $(ALL_OBJS:%.o=.deps/%.d)

232
NEWS
View File

@@ -1,242 +1,12 @@
New in version 1.31.2 New in version 1.23.1
===================== =====================
Security fixes
--------------
* Restrict authentication of NTP server/peer to specified key (CVE-2016-1567)
New in version 1.31.1
=====================
Security fixes
--------------
* Protect authenticated symmetric NTP associations against DoS attacks
(CVE-2015-1853)
* Fix access configuration with subnet size indivisible by 4 (CVE-2015-1821)
* Fix initialization of reply slots for authenticated commands (CVE-2015-1822)
New in version 1.31
===================
Enhancements
------------
* Support operation in other NTP eras (next era begins in 2036),
NTP time is mapped to [-50, +86] years around build date by default
* Restore time from driftfile with -s when RTC is missing/unsupported
* Close connected client sockets when not waiting for reply
* Use one client socket with random port when acquisitionport is 0
* Use NTP packets instead of UDP echo for presend
* Don't adjust polling interval when sending fails
* Allow binding to addresses that don't exist yet
* Ignore measurements around leap second
* Improve detection of unexpected time jumps
* Include example of logrotate configuration, systemd services and
NetworkManager dispatcher script
Bug fixes
---------
* Reconnect client sockets for each request to follow changes
in network configuration automatically
* Restart timer when polling interval is changed on reset
New in version 1.30
===================
Enhancements
------------
* Add asynchronous name resolving with POSIX threads
* Add PTP hardware clock (PHC) refclock driver
* Add new generic clock driver to slew by adjusting frequency only
(without kernel PLL or adjtime) and use it on Linux
* Add rtcautotrim directive to trim RTC automatically
* Add hwclockfile directive to share RTC LOCAL/UTC setting with hwclock
* Add maxslewrate directive to set maximum allowed slew rate
* Add maxdispersion option for refclocks
* Add -q/-Q options to set clock/print offset once and exit
* Allow directives to be specified on chronyd command line
* Replace frequency scaling in Linux driver with retaining of tick
* Try to detect unexpected forward time jumps and reset state
* Exit with non-zero code when maxchange limit is reached
* Improve makestep to not start and stop slew unnecessarily
* Change default corrtimeratio to 3.0 to improve frequency accuracy
* Announce leap second only on last day of June and December
* Use separate connected client sockets for each NTP server
* Remove separate NTP implementation used for initstepslew
* Limit maximum minpoll set by KoD RATE to default maxpoll
* Don't send NTP requests with unknown key
* Print warning when source is added with unknown key
* Take leap second in PPS refclock from locked source
* Make reading of RTC for initial trim more reliable
* Don't create cmdmon sockets when cmdport is 0
* Add configure option to set default user to drop root privileges
* Add configure option to compile with debug messages
* Print debug messages when -d is used more than once
* Change format of messages written to terminal with -d
* Write fatal messages also to stderr with -n
* Use IP_RECVERR socket option in chronyc to not wait unnecessarily
* Shorten default chronyc timeout for localhost
* Change default hostname in chronyc from localhost to 127.0.0.1
* Print error message on invalid syntax with all chronyc commands
* Include simulation test suite using clknetsim
Bug fixes
---------
* Fix crash when selecting with multiple preferred sources
* Fix frequency calculation with large frequency offsets
* Fix code writing drift and RTC files to compile correctly
* Fix -4/-6 options in chronyc to not reset hostname set by -h
* Fix refclock sample validation with sub-second polling interval
* Set stratum correctly with non-PPS SOCK refclock and local stratum
* Modify dispersion accounting in refclocks to prevent PPS getting
stuck with large dispersion and not accepting new samples
New in version 1.29.1
=====================
Security fixes
--------------
* Modify chronyc protocol to prevent amplification attacks (CVE-2014-0021)
(incompatible with previous protocol version, chronyc supports both)
New in version 1.29
===================
Security fixes
--------------
* Fix crash when processing crafted commands (CVE-2012-4502)
(possible with IP addresses allowed by cmdallow and localhost)
* Don't send uninitialized data in SUBNETS_ACCESSED and CLIENT_ACCESSES
replies (CVE-2012-4503) (not used by chronyc)
Other changes
-------------
* Drop support for SUBNETS_ACCESSED and CLIENT_ACCESSES commands
New in version 1.28
===================
* Combine sources to improve accuracy
* Make config and command parser strict
* Add -a option to chronyc to authenticate automatically
* Add -R option to ignore initstepslew and makestep directives
* Add generatecommandkey, minsamples, maxsamples and user directives
* Improve compatibility with NTPv1 and NTPv2 clients
* Create sockets only in selected family with -4/-6 option
* Treat address bind errors as non-fatal
* Extend tracking log
* Accept float values as initstepslew threshold
* Allow hostnames in offline, online and burst commands
* Fix and improve peer polling
* Fix crash in config parsing with too many servers
* Fix crash with duplicated initstepslew address
* Fix delta calculation with extreme frequency offsets
* Set local stratum correctly
* Remove unnecessary adjtimex calls
* Set paths in documentation by configure
* Update chrony.spec
New in version 1.27
===================
* Support for stronger keys via NSS or libtomcrypt library
* Support reading leap second data from tz database
* Support for precise clock stepping on Linux
* Support for nanoseconds in SHM refclock
* Make offset corrections smoother on Linux
* Make transmit timestamps random below clock precision
* Add corrtimeratio and maxchange directives
* Extend tracking, sources and activity reports
* Wait in foreground process until daemon is fully initialized
* Fix crash with slow name resolving
* Fix iburst with jittery sources
* Fix offset stored in rtc data right after trimrtc
* Fix crash and hang with RTC or manual samples
* Don't use readonly adjtime on Linux kernels before 2.6.28
* Changed chronyc protocol, incompatible with older versions
New in version 1.26
===================
* Add compatibility with Linux 3.0 and later
* Use proper source address in NTP replies on multihomed IPv6 hosts
* Accept NTP packets with versions 4, 3 and 2
* Cope with unexpected backward time jumps
* Don't reset kernel frequency on start without drift file
* Retry on permanent DNS error by default
* Add waitsync command
New in version 1.25
===================
* Improve accuracy with NTP sources
* Improve accuracy with reference clocks
* Improve polling interval adjustment
* Improve stability with temporary asymmetric delays
* Improve source selection
* Improve initial synchronisation
* Add delayed server name resolving
* Add temperature compensation
* Add nanosecond slewing to Linux driver
* Add fallback drifts
* Add iburst, minstratum, maxdelaydevratio, polltarget,
prefer, noselect options
* Add rtcsync directive to enable Linux 11-minute mode
* Add reselectdist, stratumweight, logbanner, maxclockerror,
include directives
* Add -n option to not detach daemon from terminal
* Fix pidfile directive
* Fix name resolving with disabled IPv6 support
* Fix reloading sample histories with reference clocks
* Fix crash with auto_offline option
* Fix online command on auto_offline sources
* Fix file descriptor leaks
* Increase burst polling interval and stop on KoD RATE
* Set maxupdateskew to 1000 ppm by default
* Require password for clients command
* Update drift file at most once per hour
* Use system headers for Linux RTC support
* Reduce default chronyc timeout and make it configurable
* Avoid large values in chronyc sources and sourcestats output
* Add reselect command to force reselecting best source
* Add -m option to allow multiple commands on command line
New in version 1.24
===================
Security fixes Security fixes
-------------- --------------
* Don't reply to invalid cmdmon packets (CVE-2010-0292) * Don't reply to invalid cmdmon packets (CVE-2010-0292)
* Limit client log memory size (CVE-2010-0293) * Limit client log memory size (CVE-2010-0293)
* Limit rate of syslog messages (CVE-2010-0294) * 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 New in version 1.23
=================== ===================

118
README
View File

@@ -2,7 +2,6 @@ This is the README for chrony.
What is chrony? What is chrony?
=============== ===============
Chrony is a pair of programs for maintaining the accuracy of computer Chrony is a pair of programs for maintaining the accuracy of computer
clocks. clocks.
@@ -11,7 +10,7 @@ time. This does most of the work.
chronyc is a command-line interface program which can be used to chronyc is a command-line interface program which can be used to
monitor chronyd's performance and to change various operating monitor chronyd's performance and to change various operating
parameters whilst it is running. parateters whilst it is running.
chronyd's main function is to obtain measurements of the true (UTC) chronyd's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock time from one of several sources, and correct the system clock
@@ -19,19 +18,19 @@ accordingly. It also works out the rate at which the system clock
gains or loses time and uses this information to keep it accurate gains or loses time and uses this information to keep it accurate
between measurements from the reference. between measurements from the reference.
The reference time can be derived from Network Time Protocol (NTP) The reference time can be derived from either Network Time Protocol
servers, reference clocks, or wristwatch-and-keyboard (via chronyc). (NTP) servers (preferred), or wristwatch-and-keyboard (via chronyc).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
http://www.ntp.org. http://www.eecis.udel.edu/~ntp.
It is designed so that it can work on computers which only have It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet or laptops. Of course, it use a dial-up account to access the Internet. Of course, it will work
will work well on computers with permanent connections too. on computers with permanent connections too.
In addition, on Linux it can monitor the system's real time clock In addition, the Linux 2.0.x (for x >= 32), 2.2.x and 2.3.x versions
performance, so the system can maintain accurate time even across can monitor the system's real time clock performance, so the system
reboots. can maintain accurate time even across reboots.
Typical accuracies available between 2 machines are Typical accuracies available between 2 machines are
@@ -39,8 +38,6 @@ On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next) session to the next)
With a good reference clock the accuracy can reach one microsecond.
chronyd can also operate as an RFC1305-compatible NTP server and peer. chronyd can also operate as an RFC1305-compatible NTP server and peer.
@@ -49,7 +46,9 @@ What will chrony run on?
Chrony can be successfully built and run on Chrony can be successfully built and run on
1. Linux 2.2.x, 2.3.x, 2.4.x, 2.6.x, 3.x 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.
2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms) 2. Solaris 2.5/2.5.1/2.6/2.7/2.8 (various platforms)
@@ -62,7 +61,7 @@ Chrony can be successfully built and run on
Any other system will require a porting exercise. You would need to Any other system will require a porting exercise. You would need to
start from one of the existing system-specific drivers and look into start from one of the existing system-specific drivers and look into
the quirks of certain system calls and the kernel on your target the quirks of certain system calls and the kernel on your target
system. system. (This is described in the manual).
How do I set it up? How do I set it up?
=================== ===================
@@ -70,7 +69,8 @@ How do I set it up?
The file INSTALL gives instructions. On supported systems the The file INSTALL gives instructions. On supported systems the
compilation process should be automatic. compilation process should be automatic.
You will need an ANSI C compiler -- gcc is recommended. You will need an ANSI C compiler -- gcc is recommended. Versions
2.7.2/2.7.2.2 are known to work.
The manual (in texinfo and text formats) describes how to set the The manual (in texinfo and text formats) describes how to set the
software up for the less straightforward cases. software up for the less straightforward cases.
@@ -84,18 +84,29 @@ ready-formatted plain text (chrony.txt) in the distribution.
There is also information available on the chrony web pages, accessible There is also information available on the chrony web pages, accessible
through the URL through the URL
http://chrony.tuxfamily.org/ http://chrony.sunsite.dk/
What can chrony not do?
=======================
Compared to the `reference' RFC1305 implementation xntpd, chronyd does
not support hardware reference clocks, leap seconds or broadcast
modes.
Where are new versions announced? Where are new versions announced?
================================= =================================
There is a low volume mailing list where new versions and other There is a low volume mailing list where new versions and other
important news relating to chrony is announced. You can join this list important news relating to chrony is announced. You can join this list
by sending mail with the subject "subscribe" to by sending mail to
chrony-announce-request@chrony.tuxfamily.org chrony-announce-subscribe@sunsite.dk
These messages will be copied to chrony-users (see below). 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.
How can I get support for chrony? How can I get support for chrony?
and where can I discuss new features, possible bugs etc? and where can I discuss new features, possible bugs etc?
@@ -106,27 +117,36 @@ mentioned above. chrony-users is a users' discussion list, e.g. for
general questions and answers about using chrony. chrony-dev is a more general questions and answers about using chrony. chrony-dev is a more
technical list, e.g. for discussing how new features should be technical list, e.g. for discussing how new features should be
implemented, exchange of information between developers etc. To implemented, exchange of information between developers etc. To
subscribe to either of these lists, send a message with the subject subscribe to either of these lists, send an empty message to
"subscribe" to
chrony-users-request@chrony.tuxfamily.org chrony-users-subscribe@sunsite.dk
or or
chrony-dev-request@chrony.tuxfamily.org chrony-dev-subscribe@sunsite.dk
as applicable. as applicable.
Note that due to family commitments (a 3 year-old and a 1 year-old), I
no longer have the time to give to supporting chrony that I once had.
Therefore, the chrony-users list should be your main route for support,
rather than mailing me directly. Even if it's me that responds to your
question on the list, at least *ALL* subscribers then benefit from
seeing the discussion, rather than me taking up lots of time on
supporting people on a one-to-one basis. If you do mail me directly,
don't be surprised if I cc: the response to the mailing list.
Author But how can I contact the author if I need to?
====== ==============================================
Richard P. Curnow <rc@rc0.org.uk> 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:
- you include the word 'chrony' in the subject line (so my mail reader
can sort my mail by topic)
Maintainers - 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
Miroslav Lichvar <mlichvar@redhat.com> slowly ...).
Acknowledgements Acknowledgements
================ ================
@@ -134,9 +154,6 @@ Acknowledgements
The following people have provided patches and other major contributions The following people have provided patches and other major contributions
to the program : to the program :
Benny Lyne Amorsen <benny@amorsen.dk>
Patch to add minstratum option
Andrew Bishop <amb@gedanken.demon.co.uk> Andrew Bishop <amb@gedanken.demon.co.uk>
Fixes for bugs in logging when in daemon mode Fixes for bugs in logging when in daemon mode
Fixes for compiler warnings Fixes for compiler warnings
@@ -178,18 +195,10 @@ Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
Port to NetBSD Port to NetBSD
John Hasler <john@dhh.gt.org> John Hasler <john@dhh.gt.org>
Project and website at tuxfamily.org
Changes to support 64 bit machines (i.e. those where Changes to support 64 bit machines (i.e. those where
sizeof(unsigned long) > 4) sizeof(unsigned long) > 4)
Bug fix to initstepslew directive Bug fix to initstepslew directive
Fix to remove potential buffer overrun errors. Fix to remove potential buffer overrun errors.
Memory locking and real-time scheduler support
Fix fault where chronyd enters an endless loop
Tjalling Hattink <t.hattink@fugro.nl>
Fix scheduler to allow stepping clock from timeout handler
Patch to take leap second in PPS refclock from locked source
Patch to make reading of RTC for initial trim more reliable
Liam Hatton <me@liamhatton.com> Liam Hatton <me@liamhatton.com>
Advice on configuring for Linux on PPC Advice on configuring for Linux on PPC
@@ -197,27 +206,12 @@ Liam Hatton <me@liamhatton.com>
Jachym Holecek <jakym@volny.cz> Jachym Holecek <jakym@volny.cz>
Patch to make Linux real time clock work with devfs Patch to make Linux real time clock work with devfs
Håkan Johansson <f96hajo@chalmers.se>
Patch to avoid large values in sources and sourcestats output
Jim Knoble <jmknoble@pobox.com> Jim Knoble <jmknoble@pobox.com>
Fixes for compiler warnings Fixes for compiler warnings
Antti Jrvinen <costello@iki.fi> Antti Jrvinen <costello@iki.fi>
Advice on configuring for BSD/386 Advice on configuring for BSD/386
Miroslav Lichvar <mlichvar@redhat.com>
Reference clock support
IPv6 support
Linux capabilities support
Leap second support
Improved source selection
Improved sample history trimming
Improved polling interval adjustment
Improved stability with temporary asymmetric delays
Temperature compensation
Many other bug fixes and improvements
Victor Moroz <vim@prv.adlum.ru> Victor Moroz <vim@prv.adlum.ru>
Patch to support Linux with HZ!=100 Patch to support Linux with HZ!=100
@@ -230,9 +224,6 @@ Frank Otto <sandwichmacher@web.de>
Andreas Piesk <apiesk@virbus.de> Andreas Piesk <apiesk@virbus.de>
Patch to make chronyc use the readline library if available Patch to make chronyc use the readline library if available
Timo Teras <timo.teras@iki.fi>
Patch to reply correctly on multihomed hosts
Wolfgang Weisselberg <weissel@netcologne.de> Wolfgang Weisselberg <weissel@netcologne.de>
Entries in contrib directory Entries in contrib directory
@@ -248,3 +239,10 @@ Doug Woodward <dougw@whistler.com>
Many other people have contributed bug reports and suggestions. I'm Many other people have contributed bug reports and suggestions. I'm
sorry I can't identify all of you individually. sorry I can't identify all of you individually.
Version control information
===========================
$Header: /cvs/src/chrony/README,v 1.30 2003/09/21 23:11:06 richard Exp $
vim:tw=72

688
acquire.c Normal file
View File

@@ -0,0 +1,688 @@
/*
$Header: /cvs/src/chrony/acquire.c,v 1.24 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
**********************************************************************
=======================================================================
Processing to perform the equivalent of what ntpdate does. That is,
make a rapid-fire set of measurements to a designated set of
sources, and step or slew the local clock to bring it into line with
the result.
This is kept completely separate of the main chronyd processing, by
using a separate socket for sending/receiving the measurement
packets. That way, ntp_core.c can be kept completely independent of
this functionality.
A few of the finer points of how to construct valid RFC1305 packets
and validate responses for this case have been cribbed from the
ntpdate source.
*/
#include "sysincl.h"
#include "acquire.h"
#include "memory.h"
#include "sched.h"
#include "local.h"
#include "logging.h"
#include "ntp.h"
#include "util.h"
#include "main.h"
#include "conf.h"
/* ================================================== */
/* Interval between firing off the first sample to successive sources */
#define INTER_SOURCE_START (0.2)
#define MAX_SAMPLES 8
#define MAX_DEAD_PROBES 4
#define N_GOOD_SAMPLES 4
#define RETRANSMISSION_TIMEOUT (1.0)
typedef struct { unsigned long ip_addr;
int sanity; /* Flag indicating whether source
looks sane or not */
int n_dead_probes; /* Number of probes sent to the server
since a good one */
int n_samples; /* Number of samples accumulated */
int n_total_samples; /* Total number of samples received
including useless ones */
double offsets[MAX_SAMPLES]; /* In seconds, positive means local
clock is fast of reference */
double root_distances[MAX_SAMPLES]; /* in seconds */
double inter_lo; /* Low end of estimated range of offset */
double inter_hi; /* High end of estimated range of offset */
NTP_int64 last_tx; /* Transmit timestamp in last packet
transmitted to source. */
int timer_running;
SCH_TimeoutID timeout_id;
} SourceRecord;
static SourceRecord *sources;
static int n_sources;
static int n_started_sources;
static int n_completed_sources;
static int init_slew_threshold = -1;
static int sock_fd = -1;
/* ================================================== */
static void (*saved_after_hook)(void *) = NULL;
static void *saved_after_hook_anything = NULL;
/* ================================================== */
typedef struct {
double offset;
enum {LO, HIGH} type;
int index;
} Endpoint;
typedef struct {
double lo;
double hi;
} Interval;
/* ================================================== */
static void read_from_socket(void *anything);
static void transmit_timeout(void *x);
static void wind_up_acquisition(void);
static void start_source_timeout_handler(void *not_used);
/* ================================================== */
static SCH_TimeoutID source_start_timeout_id;
/* ================================================== */
void
ACQ_Initialise(void)
{
return;
}
/* ================================================== */
void
ACQ_Finalise(void)
{
return;
}
/* ================================================== */
static void
initialise_io(void)
{
unsigned short port_number = CNF_GetAcquisitionPort();
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
LOG_FATAL(LOGF_Acquire, "Could not open socket : %s", strerror(errno));
}
if (port_number == 0) {
/* 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) {
LOG(LOGS_ERR, LOGF_Acquire, "Could not bind socket : %s\n", strerror(errno));
/* but keep running */
}
}
SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
}
/* ================================================== */
static void
finalise_io(void)
{
if (sock_fd >= 0) {
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
}
return;
}
/* ================================================== */
static void
probe_source(SourceRecord *src)
{
NTP_Packet pkt;
int version = 3;
NTP_Mode my_mode = MODE_CLIENT;
struct timeval cooked;
double local_time_err;
struct sockaddr_in his_addr;
#if 0
printf("Sending probe to %08lx sent=%d samples=%d\n", src->ip_addr, src->n_probes_sent, src->n_samples);
#endif
pkt.lvm = (((LEAP_Unsynchronised << 6) & 0xc0) |
((version << 3) & 0x38) |
((my_mode) & 0x7));
pkt.stratum = 0;
pkt.poll = 4;
pkt.precision = -6; /* as ntpdate */
pkt.root_delay = double_to_int32(1.0); /* 1 second */
pkt.root_dispersion = double_to_int32(1.0); /* likewise */
pkt.reference_id = 0UL;
pkt.reference_ts.hi = 0; /* Set to 0 */
pkt.reference_ts.lo = 0; /* Set to 0 */
pkt.originate_ts.hi = 0; /* Set to 0 */
pkt.originate_ts.lo = 0; /* Set to 0 */
pkt.receive_ts.hi = 0; /* Set to 0 */
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;
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) {
LOG(LOGS_WARN, LOGF_Acquire, "Could not send to %s : %s",
UTI_IPToDottedQuad(src->ip_addr),
strerror(errno));
}
src->last_tx = pkt.transmit_ts;
++(src->n_dead_probes);
src->timer_running = 1;
src->timeout_id = SCH_AddTimeoutByDelay(RETRANSMISSION_TIMEOUT, transmit_timeout, (void *) src);
return;
}
/* ================================================== */
static void
transmit_timeout(void *x)
{
SourceRecord *src = (SourceRecord *) x;
src->timer_running = 0;
#if 0
printf("Timeout expired for server %08lx\n", src->ip_addr);
#endif
if (src->n_dead_probes < MAX_DEAD_PROBES) {
probe_source(src);
} else {
/* Source has croaked or is taking too long to respond */
++n_completed_sources;
if (n_completed_sources == n_sources) {
wind_up_acquisition();
}
}
}
/* ================================================== */
#define MAX_STRATUM 15
static void
process_receive(NTP_Packet *msg, SourceRecord *src, struct timeval *now)
{
unsigned long lvm;
int leap, version, mode;
double root_delay, root_dispersion;
double total_root_delay, total_root_dispersion, total_root_distance;
struct timeval local_orig, local_average, remote_rx, remote_tx, remote_average;
double remote_interval, local_interval;
double delta, theta, epsilon;
int n;
/* Most of the checks are from ntpdate */
/* Need to do something about authentication */
lvm = msg->lvm;
leap = (lvm >> 6) & 0x3;
version = (lvm >> 3) & 0x7;
mode = lvm & 0x7;
if ((leap == LEAP_Unsynchronised) ||
(version != 3) ||
(mode != MODE_SERVER && mode != MODE_PASSIVE)) {
return;
}
if (msg->stratum > MAX_STRATUM) {
return;
}
/* Check whether server is responding to our last request */
if ((msg->originate_ts.hi != src->last_tx.hi) ||
(msg->originate_ts.lo != src->last_tx.lo)) {
return;
}
/* Check that the server is sane */
if (((msg->originate_ts.hi == 0) && (msg->originate_ts.lo == 0)) ||
((msg->receive_ts.hi == 0) && (msg->receive_ts.lo) == 0)) {
return;
}
root_delay = int32_to_double(msg->root_delay);
root_dispersion = int32_to_double(msg->root_dispersion);
UTI_Int64ToTimeval(&src->last_tx, &local_orig);
UTI_Int64ToTimeval(&msg->receive_ts, &remote_rx);
UTI_Int64ToTimeval(&msg->transmit_ts, &remote_tx);
UTI_AverageDiffTimevals(&remote_rx, &remote_tx, &remote_average, &remote_interval);
UTI_AverageDiffTimevals(&local_orig, now, &local_average, &local_interval);
delta = local_interval - remote_interval;
/* Defined as positive if we are fast. Note this sign convention is
opposite to that used in ntp_core.c */
UTI_DiffTimevalsToDouble(&theta, &local_average, &remote_average);
/* Could work out epsilon - leave till later */
epsilon = 0.0;
total_root_delay = fabs(delta) + root_delay;
total_root_dispersion = epsilon + root_dispersion;
total_root_distance = 0.5 * fabs(total_root_delay) + total_root_dispersion;
n = src->n_samples;
#if 0
printf("Sample %d theta=%.6f delta=%.6f root_del=%.6f root_disp=%.6f root_dist=%.6f\n",
n, theta, delta, total_root_delay, total_root_dispersion, total_root_distance);
#endif
src->offsets[n] = theta;
src->root_distances[n] = total_root_distance;
++(src->n_samples);
}
/* ================================================== */
static void
read_from_socket(void *anything)
{
int status;
ReceiveBuffer msg;
struct sockaddr_in his_addr;
socklen_t his_addr_len;
int flags;
int message_length;
unsigned long remote_ip;
int i, ok;
struct timeval now;
double local_time_err;
SourceRecord *src;
flags = 0;
message_length = sizeof(msg);
his_addr_len = sizeof(his_addr);
/* Get timestamp */
LCL_ReadCookedTime(&now, &local_time_err);
status = recvfrom (sock_fd, (char *)&msg, message_length, flags,
(struct sockaddr *) &his_addr, &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);
#if 0
printf("Got message from %08lx\n", remote_ip);
#endif
/* Find matching host */
ok = 0;
for (i=0; i<n_sources; i++) {
if (remote_ip == sources[i].ip_addr) {
ok = 1;
break;
}
}
if (ok) {
src = sources + i;
++src->n_total_samples;
src->n_dead_probes = 0; /* reset this when we actually receive something */
/* If we got into this function, we know the retransmission timeout has not
expired for the source */
if (src->timer_running) {
SCH_RemoveTimeout(src->timeout_id);
src->timer_running = 0;
}
process_receive(&msg.ntp_pkt, src, &now);
/* Check if server done and requeue timeout */
if ((src->n_samples >= N_GOOD_SAMPLES) ||
(src->n_total_samples >= MAX_SAMPLES)) {
++n_completed_sources;
#if 0
printf("Source %08lx completed\n", src->ip_addr);
#endif
if (n_completed_sources == n_sources) {
wind_up_acquisition();
}
} else {
/* Send the next probe */
probe_source(src);
}
}
}
/* ================================================== */
static void
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);
#endif
n_started_sources++;
if (n_started_sources < n_sources) {
source_start_timeout_id = SCH_AddTimeoutByDelay(INTER_SOURCE_START, start_source_timeout_handler, NULL);
}
}
/* ================================================== */
static int
endpoint_compare(const void *a, const void *b)
{
const Endpoint *aa = (const Endpoint *) a;
const Endpoint *bb = (const Endpoint *) b;
if (aa->offset < bb->offset) {
return -1;
} else if (aa->offset > bb->offset) {
return +1;
} else {
return 0;
}
}
/* ================================================== */
static void
process_measurements(void)
{
SourceRecord *s;
Endpoint *eps;
int i, j;
int n_sane_sources;
double lo, hi;
double inter_lo, inter_hi;
int depth;
int best_depth;
int n_at_best_depth;
Interval *intervals;
double estimated_offset;
int index1, index2;
n_sane_sources = 0;
/* First, get a consistent interval for each source. Those for
which this is not possible are considered to be insane. */
for (i=0; i<n_sources; i++) {
s = sources + i;
/* If we got no measurements, the source is insane */
if (s->n_samples == 0) {
s->sanity = 0;
} else {
s->sanity = 1; /* so far ... */
lo = s->offsets[0] - s->root_distances[0];
hi = s->offsets[0] + s->root_distances[0];
inter_lo = lo;
inter_hi = hi;
for (j=1; j<s->n_samples; j++) {
lo = s->offsets[j] - s->root_distances[j];
hi = s->offsets[j] + s->root_distances[j];
if ((inter_hi <= lo) || (inter_lo >= hi)) {
/* Oh dear, we won't get an interval for this source */
s->sanity = 0;
break;
} else {
inter_lo = (lo < inter_lo) ? inter_lo : lo;
inter_hi = (hi > inter_hi) ? inter_hi : hi;
}
}
if (s->sanity) {
s->inter_lo = inter_lo;
s->inter_hi = inter_hi;
}
}
if (s->sanity) {
++n_sane_sources;
}
}
/* Now build the endpoint list, similar to the RFC1305 clock
selection algorithm. */
eps = MallocArray(Endpoint, 2*n_sane_sources);
intervals = MallocArray(Interval, n_sane_sources);
j = 0;
for (i=0; i<n_sources; i++) {
s = sources + i;
if (s->sanity) {
eps[j].offset = s->inter_lo;
eps[j].type = LO;
eps[j].index = i;
eps[j+1].offset = s->inter_hi;
eps[j+1].type = HIGH;
eps[j+1].index = i;
j += 2;
}
}
qsort(eps, 2*n_sane_sources, sizeof(Endpoint), endpoint_compare);
/* Now do depth searching algorithm */
n_at_best_depth = best_depth = depth = 0;
for (i=0; i<2*n_sane_sources; i++) {
#if 0
fprintf(stderr, "Endpoint type %s source index %d [ip=%08lx] offset=%.6f\n",
(eps[i].type == LO) ? "LO" : "HIGH",
eps[i].index,
sources[eps[i].index].ip_addr,
eps[i].offset);
#endif
switch (eps[i].type) {
case LO:
depth++;
if (depth > best_depth) {
best_depth = depth;
n_at_best_depth = 0;
intervals[0].lo = eps[i].offset;
} else if (depth == best_depth) {
intervals[n_at_best_depth].lo = eps[i].offset;
} else {
/* Nothing to do */
}
break;
case HIGH:
if (depth == best_depth) {
intervals[n_at_best_depth].hi = eps[i].offset;
n_at_best_depth++;
}
depth--;
break;
}
}
if (best_depth > 0) {
if ((n_at_best_depth % 2) == 1) {
index1 = (n_at_best_depth - 1) / 2;
estimated_offset = 0.5 * (intervals[index1].lo + intervals[index1].hi);
} else {
index2 = (n_at_best_depth / 2);
index1 = index2 - 1;
estimated_offset = 0.5 * (intervals[index1].lo + intervals[index2].hi);
}
/* Apply a step change to the system clock. As per sign
convention in local.c and its children, a positive offset means
the system clock is fast of the reference, i.e. it needs to be
stepped backwards. */
if (fabs(estimated_offset) > (double) init_slew_threshold) {
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (step)",
fabs(estimated_offset),
(estimated_offset >= 0) ? "fast" : "slow");
LCL_ApplyStepOffset(estimated_offset);
} else {
LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
fabs(estimated_offset),
(estimated_offset >= 0) ? "fast" : "slow");
LCL_AccumulateOffset(estimated_offset);
}
} else {
LOG(LOGS_WARN, LOGF_Acquire, "No intersecting endpoints found");
}
Free(intervals);
Free(eps);
}
/* ================================================== */
static void
wind_up_acquisition(void)
{
/* Now process measurements */
process_measurements();
Free(sources);
finalise_io();
if (saved_after_hook) {
(saved_after_hook)(saved_after_hook_anything);
}
}
/* ================================================== */
static void
start_source_timeout_handler(void *not_used)
{
start_next_source();
}
/* ================================================== */
void
ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int threshold, void (*after_hook)(void *), void *anything)
{
int i;
saved_after_hook = after_hook;
saved_after_hook_anything = anything;
init_slew_threshold = threshold;
n_started_sources = 0;
n_completed_sources = 0;
n_sources = n;
sources = MallocArray(SourceRecord, n);
for (i=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;
}
initialise_io();
/* Start sampling first source */
start_next_source();
return;
}
/* ================================================== */

View File

@@ -1,8 +1,12 @@
/* /*
$Header: /cvs/src/chrony/acquire.h,v 1.9 2002/02/28 23:27:07 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Miroslav Lichvar 2012 * Copyright (C) Richard P. Curnow 1997-2002
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -15,50 +19,29 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
======================================================================= =======================================================================
Routines implementing crypto hashing using internal MD5 implementation. Header file for acquisition module
*/ */
#include "config.h" #ifndef GOT_ACQUIRE_H
#include "sysincl.h" #define GOT_ACQUIRE_H
#include "hash.h"
#include "memory.h"
#include "md5.c" typedef struct ACQ_SourceRecord *ACQ_Source;
static MD5_CTX ctx; extern void ACQ_Initialise(void);
int extern void ACQ_Finalise(void);
HSH_GetHashId(const char *name)
{
/* only MD5 is supported */
if (strcmp(name, "MD5"))
return -1;
return 0; extern void ACQ_StartAcquisition(int n, unsigned long *ip_addrs, int init_slew_threshold,
} void (*after_hook)(void *), void *anything);
unsigned int extern void ACQ_AccumulateSample(ACQ_Source acq_source, double offset, double root_distance);
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
if (out_len < 16)
return 0;
MD5Init(&ctx); extern void ACQ_MissedSample(ACQ_Source acq_source);
MD5Update(&ctx, in1, in1_len);
if (in2)
MD5Update(&ctx, in2, in2_len);
MD5Final(&ctx);
memcpy(out, ctx.digest, 16); #endif /* GOT_ACQUIRE_H */
return 16;
}

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/addressing.h,v 1.7 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,32 +31,16 @@
#ifndef GOT_ADDRESSING_H #ifndef GOT_ADDRESSING_H
#define GOT_ADDRESSING_H #define GOT_ADDRESSING_H
#include "sysincl.h" /* This type is used to represent an IPv4 address and port
number. Both parts are in HOST order, NOT network order. */
/* This type is used to represent an IPv4 address or IPv6 address.
All parts are in HOST order, NOT network order. */
#define IPADDR_UNSPEC 0
#define IPADDR_INET4 1
#define IPADDR_INET6 2
typedef struct { typedef struct {
union { unsigned long ip_addr;
uint32_t in4;
uint8_t in6[16];
} addr;
uint16_t family;
} IPAddr;
typedef struct {
IPAddr ip_addr;
unsigned short port; unsigned short port;
} NTP_Remote_Address; } NTP_Remote_Address;
typedef struct { #if 0
IPAddr ip_addr; unsigned long NTP_IP_Address;
int sock_fd; #endif
} NTP_Local_Address;
#endif /* GOT_ADDRESSING_H */ #endif /* GOT_ADDRESSING_H */

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/addrfilt.c,v 1.8 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005 * Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,8 +31,6 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "addrfilt.h" #include "addrfilt.h"
@@ -50,35 +51,23 @@ typedef struct _TableNode {
} TableNode; } TableNode;
struct ADF_AuthTableInst { struct ADF_AuthTableInst {
TableNode base4; /* IPv4 node */ TableNode base;
TableNode base6; /* IPv6 node */
}; };
/* ================================================== */ /* ================================================== */
static void inline static unsigned long
split_ip6(IPAddr *ip, uint32_t *dst) get_subnet(unsigned long addr)
{ {
int i; return (addr >> (32-NBITS)) & ((1UL<<NBITS) - 1);
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 inline static unsigned long
get_subnet(uint32_t *addr, unsigned int where) get_residual(unsigned long addr)
{ {
int off; return (addr << NBITS);
off = where / 32;
where %= 32;
return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
} }
/* ================================================== */ /* ================================================== */
@@ -90,10 +79,8 @@ ADF_CreateTable(void)
result = MallocNew(struct ADF_AuthTableInst); result = MallocNew(struct ADF_AuthTableInst);
/* Default is that nothing is allowed */ /* Default is that nothing is allowed */
result->base4.state = DENY; result->base.state = DENY;
result->base4.extended = NULL; result->base.extended = NULL;
result->base6.state = DENY;
result->base6.extended = NULL;
return result; return result;
} }
@@ -116,6 +103,8 @@ close_node(TableNode *node)
Free(node->extended); Free(node->extended);
node->extended = NULL; node->extended = NULL;
} }
return;
} }
@@ -139,28 +128,29 @@ open_node(TableNode *node)
child_node->extended = NULL; child_node->extended = NULL;
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */
static ADF_Status static ADF_Status
set_subnet(TableNode *start_node, set_subnet(TableNode *start_node,
uint32_t *ip, unsigned long ip,
int ip_len,
int subnet_bits, int subnet_bits,
State new_state, State new_state,
int delete_children) int delete_children)
{ {
int bits_to_go, bits_consumed; int bits_to_go;
uint32_t subnet; unsigned long residual;
unsigned long subnet;
TableNode *node; TableNode *node;
bits_consumed = 0;
bits_to_go = subnet_bits; bits_to_go = subnet_bits;
residual = ip;
node = start_node; node = start_node;
if ((subnet_bits < 0) || if ((subnet_bits < 0) ||
(subnet_bits > 32 * ip_len)) { (subnet_bits > 32)) {
return ADF_BADSUBNET; return ADF_BADSUBNET;
@@ -169,13 +159,13 @@ set_subnet(TableNode *start_node,
if ((bits_to_go & (NBITS-1)) == 0) { if ((bits_to_go & (NBITS-1)) == 0) {
while (bits_to_go > 0) { while (bits_to_go > 0) {
subnet = get_subnet(ip, bits_consumed); subnet = get_subnet(residual);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
if (delete_children) { if (delete_children) {
@@ -188,21 +178,18 @@ set_subnet(TableNode *start_node,
TableNode *this_node; TableNode *this_node;
while (bits_to_go >= NBITS) { while (bits_to_go >= NBITS) {
subnet = get_subnet(ip, bits_consumed); subnet = get_subnet(residual);
residual = get_residual(residual);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_to_go -= NBITS; bits_to_go -= NBITS;
bits_consumed += NBITS;
} }
/* How many subnet entries to set : 1->8, 2->4, 3->2 */ /* How many subnet entries to set : 1->8, 2->4, 3->2 */
N = 1 << (NBITS-bits_to_go); N = 1 << (NBITS-bits_to_go);
subnet = get_subnet(residual);
subnet = get_subnet(ip, bits_consumed) & ~(N - 1);
assert(subnet + N <= TABLE_SIZE);
if (!(node->extended)) { if (!(node->extended)) {
open_node(node); open_node(node);
} }
@@ -223,41 +210,12 @@ set_subnet(TableNode *start_node,
/* ================================================== */ /* ================================================== */
static ADF_Status
set_subnet_(ADF_AuthTable table,
IPAddr *ip_addr,
int subnet_bits,
State new_state,
int delete_children)
{
uint32_t ip6[4];
switch (ip_addr->family) {
case IPADDR_INET4:
return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children);
case IPADDR_INET6:
split_ip6(ip_addr, ip6);
return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children);
case IPADDR_UNSPEC:
/* Apply to both, subnet_bits has to be 0 */
if (subnet_bits != 0)
return ADF_BADSUBNET;
memset(ip6, 0, sizeof (ip6));
if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS &&
set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS)
return ADF_SUCCESS;
break;
}
return ADF_BADSUBNET;
}
ADF_Status ADF_Status
ADF_Allow(ADF_AuthTable table, ADF_Allow(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet_(table, ip, subnet_bits, ALLOW, 0); return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 0);
} }
/* ================================================== */ /* ================================================== */
@@ -265,30 +223,30 @@ ADF_Allow(ADF_AuthTable table,
ADF_Status ADF_Status
ADF_AllowAll(ADF_AuthTable table, ADF_AllowAll(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet_(table, ip, subnet_bits, ALLOW, 1); return set_subnet(&(table->base), ip, subnet_bits, ALLOW, 1);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_Deny(ADF_AuthTable table, ADF_Deny(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet_(table, ip, subnet_bits, DENY, 0); return set_subnet(&(table->base), ip, subnet_bits, DENY, 0);
} }
/* ================================================== */ /* ================================================== */
ADF_Status ADF_Status
ADF_DenyAll(ADF_AuthTable table, ADF_DenyAll(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits) int subnet_bits)
{ {
return set_subnet_(table, ip, subnet_bits, DENY, 1); return set_subnet(&(table->base), ip, subnet_bits, DENY, 1);
} }
/* ================================================== */ /* ================================================== */
@@ -296,33 +254,32 @@ ADF_DenyAll(ADF_AuthTable table,
void void
ADF_DestroyTable(ADF_AuthTable table) ADF_DestroyTable(ADF_AuthTable table)
{ {
close_node(&table->base4); close_node(&(table->base));
close_node(&table->base6);
Free(table); Free(table);
} }
/* ================================================== */ /* ================================================== */
static int static int
check_ip_in_node(TableNode *start_node, uint32_t *ip) check_ip_in_node(TableNode *start_node, unsigned long ip)
{ {
uint32_t subnet; unsigned long residual, subnet;
int bits_consumed = 0;
int result = 0; int result = 0;
int finished = 0; int finished = 0;
TableNode *node; TableNode *node;
State state=DENY; State state=DENY;
node = start_node; node = start_node;
residual = ip;
do { do {
if (node->state != AS_PARENT) { if (node->state != AS_PARENT) {
state = node->state; state = node->state;
} }
if (node->extended) { if (node->extended) {
subnet = get_subnet(ip, bits_consumed); subnet = get_subnet(residual);
residual = get_residual(residual);
node = &(node->extended[subnet]); node = &(node->extended[subnet]);
bits_consumed += NBITS;
} else { } else {
/* Make decision on this node */ /* Make decision on this node */
finished = 1; finished = 1;
@@ -349,120 +306,65 @@ check_ip_in_node(TableNode *start_node, uint32_t *ip)
int int
ADF_IsAllowed(ADF_AuthTable table, ADF_IsAllowed(ADF_AuthTable table,
IPAddr *ip_addr) unsigned long ip)
{ {
uint32_t ip6[4];
switch (ip_addr->family) { return check_ip_in_node(&(table->base), ip);
case IPADDR_INET4:
return check_ip_in_node(&table->base4, &ip_addr->addr.in4);
case IPADDR_INET6:
split_ip6(ip_addr, ip6);
return check_ip_in_node(&table->base6, ip6);
}
return 0;
} }
/* ================================================== */ /* ================================================== */
#if defined TEST #if defined TEST
static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits) static void print_node(TableNode *node, unsigned long addr, int shift, int subnet_bits)
{ {
uint32_t new_addr[4]; unsigned long new_addr;
int i; int i;
TableNode *sub_node; TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' '); for (i=0; i<subnet_bits; i++) putchar(' ');
if (ip_len == 1) printf("%d.%d.%d.%d/%d : %s\n",
printf("%d.%d.%d.%d", ((addr >> 24) & 255),
((addr[0] >> 24) & 255), ((addr >> 16) & 255),
((addr[0] >> 16) & 255), ((addr >> 8) & 255),
((addr[0] >> 8) & 255), ((addr ) & 255),
((addr[0] ) & 255));
else {
for (i=0; i<4; i++) {
if (addr[i])
printf("%d.%d.%d.%d",
((addr[i] >> 24) & 255),
((addr[i] >> 16) & 255),
((addr[i] >> 8) & 255),
((addr[i] ) & 255));
putchar(i < 3 ? ':' : '\0');
}
}
printf("/%d : %s\n",
subnet_bits, subnet_bits,
(node->state == ALLOW) ? "allow" : (node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent"); (node->state == DENY) ? "deny" : "as parent");
if (node->extended) { if (node->extended) {
for (i=0; i<16; i++) { for (i=0; i<16; i++) {
sub_node = &(node->extended[i]); sub_node = &((*(node->extended))[i]);
new_addr[0] = addr[0]; new_addr = addr | ((unsigned long) i << shift);
new_addr[1] = addr[1]; print_node(sub_node, new_addr, shift - 4, subnet_bits + 4);
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;
} }
static void print_table(ADF_AuthTable table) static void print_table(ADF_AuthTable table)
{ {
uint32_t addr[4]; unsigned long addr = 0;
int shift = 28;
int subnet_bits = 0;
memset(addr, 0, sizeof (addr)); print_node(&table->base, addr, shift, subnet_bits);
printf("IPv4 table:\n"); return;
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);
} }
/* ================================================== */ /* ================================================== */
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
IPAddr ip;
ADF_AuthTable table; ADF_AuthTable table;
table = ADF_CreateTable(); table = ADF_CreateTable();
ip.family = IPADDR_INET4; ADF_Allow(table, 0x7e800000, 9);
ADF_Deny(table, 0x7ecc0000, 14);
ip.addr.in4 = 0x7e800000; /* ADF_Deny(table, 0x7f000001, 32); */
ADF_Allow(table, &ip, 9); /* ADF_Allow(table, 0x7f000000, 8); */
ip.addr.in4 = 0x7ecc0000;
ADF_Deny(table, &ip, 14);
#if 0
ip.addr.in4 = 0x7f000001;
ADF_Deny(table, &ip, 32);
ip.addr.in4 = 0x7f000000;
ADF_Allow(table, &ip, 8);
#endif
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.family = IPADDR_INET6;
memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
ADF_Deny(table, &ip, 66);
ADF_Allow(table, &ip, 59);
memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
ADF_Deny(table, &ip, 128);
ip.addr.in6[15] ^= 3;
ADF_Allow(table, &ip, 127);
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
print_table(table); print_table(table);

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/addrfilt.h,v 1.6 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,8 +31,6 @@
#ifndef GOT_ADDRFILT_H #ifndef GOT_ADDRFILT_H
#define GOT_ADDRFILT_H #define GOT_ADDRFILT_H
#include "addressing.h"
typedef struct ADF_AuthTableInst *ADF_AuthTable; typedef struct ADF_AuthTableInst *ADF_AuthTable;
typedef enum { typedef enum {
@@ -43,25 +45,25 @@ extern ADF_AuthTable ADF_CreateTable(void);
/* Allow anything in the supplied subnet, EXCEPT for any more specific /* Allow anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Allow(ADF_AuthTable table, extern ADF_Status ADF_Allow(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits); int subnet_bits);
/* Allow anything in the supplied subnet, overwriting existing /* Allow anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_AllowAll(ADF_AuthTable table, extern ADF_Status ADF_AllowAll(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, EXCEPT for any more specific /* Deny anything in the supplied subnet, EXCEPT for any more specific
subnets that are already defined */ subnets that are already defined */
extern ADF_Status ADF_Deny(ADF_AuthTable table, extern ADF_Status ADF_Deny(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits); int subnet_bits);
/* Deny anything in the supplied subnet, overwriting existing /* Deny anything in the supplied subnet, overwriting existing
definitions for any more specific subnets */ definitions for any more specific subnets */
extern ADF_Status ADF_DenyAll(ADF_AuthTable table, extern ADF_Status ADF_DenyAll(ADF_AuthTable table,
IPAddr *ip, unsigned long ip,
int subnet_bits); int subnet_bits);
/* Clear up the table */ /* Clear up the table */
@@ -70,6 +72,6 @@ extern void ADF_DestroyTable(ADF_AuthTable table);
/* Check whether a given IP address is allowed by the rules in /* Check whether a given IP address is allowed by the rules in
the table */ the table */
extern int ADF_IsAllowed(ADF_AuthTable table, extern int ADF_IsAllowed(ADF_AuthTable table,
IPAddr *ip); unsigned long ip);
#endif /* GOT_ADDRFILT_H */ #endif /* GOT_ADDRFILT_H */

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/broadcast.c,v 1.3 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -24,8 +28,6 @@
Deal with broadcast server functions. Deal with broadcast server functions.
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "memory.h" #include "memory.h"
@@ -40,7 +42,6 @@
typedef struct { typedef struct {
NTP_Remote_Address addr; NTP_Remote_Address addr;
NTP_Local_Address local_addr;
int interval; int interval;
} Destination; } Destination;
static Destination *destinations = 0; static Destination *destinations = 0;
@@ -50,6 +51,7 @@ static int max_destinations = 0;
void void
BRD_Initialise(void) BRD_Initialise(void)
{ {
return; /* Nothing to do */
} }
/* ================================================== */ /* ================================================== */
@@ -57,6 +59,7 @@ BRD_Initialise(void)
void void
BRD_Finalise(void) BRD_Finalise(void)
{ {
return; /* Nothing to do */
} }
/* ================================================== */ /* ================================================== */
@@ -72,14 +75,15 @@ timeout_handler(void *arbitrary)
int leap; int leap;
int are_we_synchronised, our_stratum; int are_we_synchronised, our_stratum;
NTP_Leap leap_status; NTP_Leap leap_status;
uint32_t our_ref_id, ts_fuzz; unsigned long our_ref_id;
struct timeval our_ref_time; struct timeval our_ref_time;
double our_root_delay, our_root_dispersion; double our_root_delay, our_root_dispersion;
double local_time_err;
struct timeval local_transmit; struct timeval local_transmit;
version = 3; version = 3;
LCL_ReadCookedTime(&local_transmit, NULL); LCL_ReadCookedTime(&local_transmit, &local_time_err);
REF_GetReferenceParams(&local_transmit, REF_GetReferenceParams(&local_transmit,
&are_we_synchronised, &leap_status, &are_we_synchronised, &leap_status,
&our_stratum, &our_stratum,
@@ -90,7 +94,7 @@ timeout_handler(void *arbitrary)
if (are_we_synchronised) { if (are_we_synchronised) {
leap = (int) leap_status; leap = (int) leap_status;
} else { } else {
leap = LEAP_Unsynchronised; leap = 3;
} }
message.lvm = ((leap << 6) &0xc0) | ((version << 3) & 0x38) | (MODE_BROADCAST & 0x07); message.lvm = ((leap << 6) &0xc0) | ((version << 3) & 0x38) | (MODE_BROADCAST & 0x07);
@@ -100,26 +104,25 @@ timeout_handler(void *arbitrary)
/* If we're sending a client mode packet and we aren't synchronized yet, /* If we're sending a client mode packet and we aren't synchronized yet,
we might have to set up artificial values for some of these parameters */ we might have to set up artificial values for some of these parameters */
message.root_delay = UTI_DoubleToInt32(our_root_delay); message.root_delay = double_to_int32(our_root_delay);
message.root_dispersion = UTI_DoubleToInt32(our_root_dispersion); message.root_dispersion = double_to_int32(our_root_dispersion);
message.reference_id = htonl((NTP_int32) our_ref_id); message.reference_id = htonl((NTP_int32) our_ref_id);
/* Now fill in timestamps */ /* Now fill in timestamps */
UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, 0); UTI_TimevalToInt64(&our_ref_time, &message.reference_ts);
message.originate_ts.hi = 0UL; message.originate_ts.hi = 0UL;
message.originate_ts.lo = 0UL; message.originate_ts.lo = 0UL;
message.receive_ts.hi = 0UL; message.receive_ts.hi = 0UL;
message.receive_ts.lo = 0UL; message.receive_ts.lo = 0UL;
ts_fuzz = UTI_GetNTPTsFuzz(message.precision); LCL_ReadCookedTime(&local_transmit, &local_time_err);
LCL_ReadCookedTime(&local_transmit, NULL); UTI_TimevalToInt64(&local_transmit, &message.transmit_ts);
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz); NIO_SendNormalPacket(&message, &d->addr);
NIO_SendNormalPacket(&message, &d->addr, &d->local_addr);
/* Requeue timeout. Don't care if interval drifts gradually, so just do it /* Requeue timeout. Don't care if interval drifts gradually, so just do it
* at the end. */ * at the end. */
SCH_AddTimeoutInClass((double) d->interval, 1.0, 0.02, SCH_AddTimeoutInClass((double) d->interval, 1.0,
SCH_NtpBroadcastClass, SCH_NtpBroadcastClass,
timeout_handler, (void *) d); timeout_handler, (void *) d);
@@ -129,7 +132,7 @@ timeout_handler(void *arbitrary)
/* ================================================== */ /* ================================================== */
void void
BRD_AddDestination(IPAddr *addr, unsigned short port, int interval) BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
{ {
if (max_destinations == n_destinations) { if (max_destinations == n_destinations) {
/* Expand array */ /* Expand array */
@@ -141,14 +144,11 @@ BRD_AddDestination(IPAddr *addr, unsigned short port, int interval)
} }
} }
destinations[n_destinations].addr.ip_addr = *addr; destinations[n_destinations].addr.ip_addr = addr;
destinations[n_destinations].addr.port = port; destinations[n_destinations].addr.port = port;
destinations[n_destinations].local_addr.ip_addr.family = IPADDR_UNSPEC;
destinations[n_destinations].local_addr.sock_fd =
NIO_GetServerSocket(&destinations[n_destinations].addr);
destinations[n_destinations].interval = interval; destinations[n_destinations].interval = interval;
SCH_AddTimeoutInClass((double) interval, 1.0, 0.0, SCH_AddTimeoutInClass((double) interval, 1.0,
SCH_NtpBroadcastClass, SCH_NtpBroadcastClass,
timeout_handler, (void *)(destinations + n_destinations)); timeout_handler, (void *)(destinations + n_destinations));

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/broadcast.h,v 1.2 2002/02/28 23:27:08 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,11 +31,9 @@
#ifndef GOT_BROADCAST_H #ifndef GOT_BROADCAST_H
#define GOT_BROADCAST_H #define GOT_BROADCAST_H
#include "addressing.h"
extern void BRD_Initialise(void); extern void BRD_Initialise(void);
extern void BRD_Finalise(void); extern void BRD_Finalise(void);
extern void BRD_AddDestination(IPAddr *addr, unsigned short port, int interval); extern void BRD_AddDestination(unsigned long addr, unsigned short port, int interval);
#endif /* GOT_BROADCAST_H */ #endif /* GOT_BROADCAST_H */

290
candm.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/candm.h,v 1.40 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -30,8 +34,6 @@
#define GOT_CANDM_H #define GOT_CANDM_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#include "hash.h"
/* This is the default port to use for CANDM, if no alternative is /* This is the default port to use for CANDM, if no alternative is
defined */ defined */
@@ -83,66 +85,44 @@
#define REQ_MANUAL_DELETE 42 #define REQ_MANUAL_DELETE 42
#define REQ_MAKESTEP 43 #define REQ_MAKESTEP 43
#define REQ_ACTIVITY 44 #define REQ_ACTIVITY 44
#define REQ_MODIFY_MINSTRATUM 45 #define N_REQUEST_TYPES 45
#define REQ_MODIFY_POLLTARGET 46
#define REQ_MODIFY_MAXDELAYDEVRATIO 47
#define REQ_RESELECT 48
#define REQ_RESELECTDISTANCE 49
#define N_REQUEST_TYPES 50
/* Special utoken value used to log on with first exchange being the /* Special utoken value used to log on with first exchange being the
password. (This time value has long since gone by) */ password. (This time value has long since gone by) */
#define SPECIAL_UTOKEN 0x10101010 #define SPECIAL_UTOKEN 0x10101010
/* Structure used to exchange timevals independent on size of time_t */
typedef struct {
uint32_t tv_sec_high;
uint32_t tv_sec_low;
uint32_t tv_nsec;
} Timeval;
/* This is used in tv_sec_high for 32-bit timestamps */
#define TV_NOHIGHSEC 0x7fffffff
/* 32-bit floating-point format consisting of 7-bit signed exponent
and 25-bit signed coefficient without hidden bit.
The result is calculated as: 2^(exp - 25) * coef */
typedef struct {
int32_t f;
} Float;
/* The EOR (end of record) fields are used by the offsetof operator in /* The EOR (end of record) fields are used by the offsetof operator in
pktlength.c, to get the number of bytes that ought to be pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */ transmitted for each packet type. */
typedef struct { typedef struct {
IPAddr mask; uint32_t mask;
IPAddr address; uint32_t address;
int32_t EOR; int32_t EOR;
} REQ_Online; } REQ_Online;
typedef struct { typedef struct {
IPAddr mask; uint32_t mask;
IPAddr address; uint32_t address;
int32_t EOR; int32_t EOR;
} REQ_Offline; } REQ_Offline;
typedef struct { typedef struct {
IPAddr mask; uint32_t mask;
IPAddr address; uint32_t address;
int32_t n_good_samples; int32_t n_good_samples;
int32_t n_total_samples; int32_t n_total_samples;
int32_t EOR; int32_t EOR;
} REQ_Burst; } REQ_Burst;
typedef struct { typedef struct {
IPAddr address; uint32_t address;
int32_t new_minpoll; int32_t new_minpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Minpoll; } REQ_Modify_Minpoll;
typedef struct { typedef struct {
IPAddr address; uint32_t address;
int32_t new_maxpoll; int32_t new_maxpoll;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxpoll; } REQ_Modify_Maxpoll;
@@ -153,47 +133,29 @@ typedef struct {
} REQ_Dump; } REQ_Dump;
typedef struct { typedef struct {
IPAddr address; uint32_t address;
Float new_max_delay; int32_t new_max_delay;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelay; } REQ_Modify_Maxdelay;
typedef struct { typedef struct {
IPAddr address; uint32_t address;
Float new_max_delay_ratio; int32_t new_max_delay_ratio;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelayratio; } REQ_Modify_Maxdelayratio;
typedef struct { typedef struct {
IPAddr address; int32_t new_max_update_skew;
Float new_max_delay_dev_ratio;
int32_t EOR;
} REQ_Modify_Maxdelaydevratio;
typedef struct {
IPAddr address;
int32_t new_min_stratum;
int32_t EOR;
} REQ_Modify_Minstratum;
typedef struct {
IPAddr address;
int32_t new_poll_target;
int32_t EOR;
} REQ_Modify_Polltarget;
typedef struct {
Float new_max_update_skew;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxupdateskew; } REQ_Modify_Maxupdateskew;
typedef struct { typedef struct {
Timeval ts; struct timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Logon; } REQ_Logon;
typedef struct { typedef struct {
Timeval ts; struct timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Settime; } REQ_Settime;
@@ -222,38 +184,32 @@ typedef struct {
} REQ_Rekey; } REQ_Rekey;
typedef struct { typedef struct {
IPAddr ip; uint32_t ip;
int32_t subnet_bits; int32_t subnet_bits;
int32_t EOR; int32_t EOR;
} REQ_Allow_Deny; } REQ_Allow_Deny;
typedef struct { typedef struct {
IPAddr ip; uint32_t ip;
int32_t EOR; int32_t EOR;
} REQ_Ac_Check; } REQ_Ac_Check;
/* Flags used in NTP source requests */
#define REQ_ADDSRC_ONLINE 0x1
#define REQ_ADDSRC_AUTOOFFLINE 0x2
#define REQ_ADDSRC_IBURST 0x4
#define REQ_ADDSRC_PREFER 0x8
#define REQ_ADDSRC_NOSELECT 0x10
typedef struct { typedef struct {
IPAddr ip_addr; uint32_t ip_addr;
uint32_t port; uint32_t port;
int32_t minpoll; int32_t minpoll;
int32_t maxpoll; int32_t maxpoll;
int32_t presend_minpoll; int32_t presend_minpoll;
int32_t online;
int32_t auto_offline;
uint32_t authkey; uint32_t authkey;
Float max_delay; int32_t max_delay;
Float max_delay_ratio; int32_t max_delay_ratio;
uint32_t flags;
int32_t EOR; int32_t EOR;
} REQ_NTP_Source; } REQ_NTP_Source;
typedef struct { typedef struct {
IPAddr ip_addr; uint32_t ip_addr;
int32_t EOR; int32_t EOR;
} REQ_Del_Source; } REQ_Del_Source;
@@ -262,7 +218,7 @@ typedef struct {
} REQ_WriteRtc; } REQ_WriteRtc;
typedef struct { typedef struct {
Float dfreq; int32_t dfreq;
int32_t EOR; int32_t EOR;
} REQ_Dfreq; } REQ_Dfreq;
@@ -294,13 +250,25 @@ typedef struct {
} REQ_CycleLogs; } REQ_CycleLogs;
typedef struct { typedef struct {
IPAddr ip; uint32_t ip;
uint32_t bits_specd; uint32_t bits_specd;
} REQ_SubnetsAccessed_Subnet; } REQ_SubnetsAccessed_Subnet;
#define MAX_SUBNETS_ACCESSED 8
typedef struct {
uint32_t n_subnets;
REQ_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
} REQ_SubnetsAccessed;
/* This is based on the response size rather than the /* This is based on the response size rather than the
request size */ request size */
#define MAX_CLIENT_ACCESSES 8 #define MAX_CLIENT_ACCESSES 16
typedef struct {
uint32_t n_clients;
uint32_t client_ips[MAX_CLIENT_ACCESSES];
} REQ_ClientAccesses;
typedef struct { typedef struct {
uint32_t first_index; uint32_t first_index;
@@ -325,15 +293,6 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_Activity; } REQ_Activity;
typedef struct {
int32_t EOR;
} REQ_Reselect;
typedef struct {
Float distance;
int32_t EOR;
} REQ_ReselectDistance;
/* ================================================== */ /* ================================================== */
#define PKT_TYPE_CMD_REQUEST 1 #define PKT_TYPE_CMD_REQUEST 1
@@ -351,33 +310,9 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline) Version 3 : NTP_Source message lengthened (auto_offline)
Version 4 : IPv6 addressing added, 64-bit time values, sourcestats
and tracking reports extended, added flags to NTP source request,
trimmed source report, replaced fixed-point format with floating-point
and used also instead of integer microseconds, new commands: modify stratum,
modify polltarget, modify maxdelaydevratio, reselect, reselectdistance
Version 5 : auth data moved to the end of the packet to allow hashes with
different sizes, extended sources, tracking and activity reports, dropped
subnets accessed and client accesses
Version 6 : added padding to requests to prevent amplification attack,
changed maximum number of samples in manual list to 16
*/ */
#define PROTO_VERSION_NUMBER 6 #define PROTO_VERSION_NUMBER 3
/* The oldest protocol versions that are compatible enough with the current
version to report a version mismatch for the server and the client */
#define PROTO_VERSION_MISMATCH_COMPAT_SERVER 5
#define PROTO_VERSION_MISMATCH_COMPAT_CLIENT 4
/* The first protocol version using padding in requests */
#define PROTO_VERSION_PADDING 6
/* The maximum length of padding in request packet, currently
defined by CLIENT_ACCESSES_BY_INDEX and MANUAL_LIST */
#define MAX_PADDING_LENGTH 396
/* ================================================== */ /* ================================================== */
@@ -393,6 +328,7 @@ typedef struct {
uint32_t sequence; /* Client's sequence number */ uint32_t sequence; /* Client's sequence number */
uint32_t utoken; /* Unique token per incarnation of daemon */ uint32_t utoken; /* Unique token per incarnation of daemon */
uint32_t token; /* Command token (to prevent replay attack) */ uint32_t token; /* Command token (to prevent replay attack) */
uint32_t auth[4]; /* MD5 authentication of the packet */
union { union {
REQ_Online online; REQ_Online online;
@@ -403,9 +339,6 @@ typedef struct {
REQ_Dump dump; REQ_Dump dump;
REQ_Modify_Maxdelay modify_maxdelay; REQ_Modify_Maxdelay modify_maxdelay;
REQ_Modify_Maxdelayratio modify_maxdelayratio; REQ_Modify_Maxdelayratio modify_maxdelayratio;
REQ_Modify_Maxdelaydevratio modify_maxdelaydevratio;
REQ_Modify_Minstratum modify_minstratum;
REQ_Modify_Polltarget modify_polltarget;
REQ_Modify_Maxupdateskew modify_maxupdateskew; REQ_Modify_Maxupdateskew modify_maxupdateskew;
REQ_Logon logon; REQ_Logon logon;
REQ_Settime settime; REQ_Settime settime;
@@ -426,24 +359,15 @@ typedef struct {
REQ_RTCReport rtcreport; REQ_RTCReport rtcreport;
REQ_TrimRTC trimrtc; REQ_TrimRTC trimrtc;
REQ_CycleLogs cyclelogs; REQ_CycleLogs cyclelogs;
REQ_SubnetsAccessed subnets_accessed;
REQ_ClientAccesses client_accesses;
REQ_ClientAccessesByIndex client_accesses_by_index; REQ_ClientAccessesByIndex client_accesses_by_index;
REQ_ManualList manual_list; REQ_ManualList manual_list;
REQ_ManualDelete manual_delete; REQ_ManualDelete manual_delete;
REQ_MakeStep make_step; REQ_MakeStep make_step;
REQ_Activity activity; REQ_Activity activity;
REQ_Reselect reselect;
REQ_ReselectDistance reselect_distance;
} data; /* Command specific parameters */ } data; /* Command specific parameters */
/* The following fields only set the maximum size of the packet.
There are no holes between them and the actual data. */
/* Padding used to prevent traffic amplification */
uint8_t padding[MAX_PADDING_LENGTH];
/* Authentication data */
uint8_t auth[MAX_HASH_LENGTH];
} CMD_Request; } CMD_Request;
/* ================================================== */ /* ================================================== */
@@ -453,6 +377,13 @@ typedef struct {
#define PERMIT_LOCAL 1 #define PERMIT_LOCAL 1
#define PERMIT_AUTH 2 #define PERMIT_AUTH 2
/* ================================================== */
/* These conversion utilities are used to convert between the internal
and the 'wire' representation of real quantities */
#define WIRE2REAL(x) ((double) ((int32_t) ntohl(x)) / 65536.0)
#define REAL2WIRE(x) (htonl((int32_t)(0.5 + 65536.0 * (x))))
/* ================================================== */ /* ================================================== */
/* Reply codes */ /* Reply codes */
@@ -481,7 +412,6 @@ typedef struct {
#define STT_BADSUBNET 7 #define STT_BADSUBNET 7
#define STT_ACCESSALLOWED 8 #define STT_ACCESSALLOWED 8
#define STT_ACCESSDENIED 9 #define STT_ACCESSDENIED 9
/* Deprecated */
#define STT_NOHOSTACCESS 10 #define STT_NOHOSTACCESS 10
#define STT_SOURCEALREADYKNOWN 11 #define STT_SOURCEALREADYKNOWN 11
#define STT_TOOMANYSOURCES 12 #define STT_TOOMANYSOURCES 12
@@ -489,9 +419,6 @@ typedef struct {
#define STT_BADRTCFILE 14 #define STT_BADRTCFILE 14
#define STT_INACTIVE 15 #define STT_INACTIVE 15
#define STT_BADSAMPLE 16 #define STT_BADSAMPLE 16
#define STT_INVALIDAF 17
#define STT_BADPKTVERSION 18
#define STT_BADPKTLENGTH 19
typedef struct { typedef struct {
int32_t EOR; int32_t EOR;
@@ -510,84 +437,81 @@ typedef struct {
#define RPY_SD_ST_UNREACH 1 #define RPY_SD_ST_UNREACH 1
#define RPY_SD_ST_FALSETICKER 2 #define RPY_SD_ST_FALSETICKER 2
#define RPY_SD_ST_JITTERY 3 #define RPY_SD_ST_JITTERY 3
#define RPY_SD_ST_CANDIDATE 4 #define RPY_SD_ST_OTHER 4
#define RPY_SD_ST_OUTLIER 5
#define RPY_SD_FLAG_NOSELECT 0x1
#define RPY_SD_FLAG_PREFER 0x2
typedef struct { typedef struct {
IPAddr ip_addr; uint32_t ip_addr;
int16_t poll; uint16_t poll;
uint16_t stratum; uint16_t stratum;
uint16_t state; uint16_t state;
uint16_t mode; uint16_t mode;
uint16_t flags;
uint16_t reachability;
uint32_t since_sample; uint32_t since_sample;
Float orig_latest_meas; int32_t orig_latest_meas;
Float latest_meas; int32_t latest_meas;
Float latest_meas_err; uint32_t latest_meas_err;
int32_t est_offset;
uint32_t est_offset_err;
int32_t resid_freq;
uint32_t resid_skew;
int32_t EOR; int32_t EOR;
} RPY_Source_Data; } RPY_Source_Data;
typedef struct { typedef struct {
uint32_t ref_id; uint32_t ref_id;
IPAddr ip_addr; uint32_t stratum;
uint16_t stratum; uint32_t ref_time_s;
uint16_t leap_status; uint32_t ref_time_us;
Timeval ref_time; uint32_t current_correction_s;
Float current_correction; uint32_t current_correction_us;
Float last_offset; int32_t freq_ppm;
Float rms_offset; int32_t resid_freq_ppm;
Float freq_ppm; int32_t skew_ppm;
Float resid_freq_ppm; int32_t root_delay;
Float skew_ppm; int32_t root_dispersion;
Float root_delay;
Float root_dispersion;
Float last_update_interval;
int32_t EOR; int32_t EOR;
} RPY_Tracking; } RPY_Tracking;
typedef struct { typedef struct {
uint32_t ref_id; uint32_t ip_addr;
IPAddr ip_addr;
uint32_t n_samples; uint32_t n_samples;
uint32_t n_runs; uint32_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
Float sd; uint32_t sd_us;
Float resid_freq_ppm; int32_t resid_freq_ppm;
Float skew_ppm; int32_t skew_ppm;
Float est_offset;
Float est_offset_err;
int32_t EOR; int32_t EOR;
} RPY_Sourcestats; } RPY_Sourcestats;
typedef struct { typedef struct {
Timeval ref_time; uint32_t ref_time;
uint16_t n_samples; uint16_t n_samples;
uint16_t n_runs; uint16_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
Float rtc_seconds_fast; int32_t rtc_seconds_fast;
Float rtc_gain_rate_ppm; int32_t rtc_gain_rate_ppm;
int32_t EOR; int32_t EOR;
} RPY_Rtc; } RPY_Rtc;
typedef struct { typedef struct {
uint32_t centiseconds; uint32_t centiseconds;
Float dfreq_ppm; int32_t dfreq_ppm;
Float new_afreq_ppm; int32_t new_afreq_ppm;
int32_t EOR; int32_t EOR;
} RPY_ManualTimestamp; } RPY_ManualTimestamp;
typedef struct { typedef struct {
IPAddr ip; uint32_t ip;
uint32_t bits_specd; uint32_t bits_specd;
uint32_t bitmap[8]; uint32_t bitmap[8];
} RPY_SubnetsAccessed_Subnet; } RPY_SubnetsAccessed_Subnet;
typedef struct { typedef struct {
IPAddr ip; uint32_t n_subnets;
RPY_SubnetsAccessed_Subnet subnets[MAX_SUBNETS_ACCESSED];
} RPY_SubnetsAccessed;
typedef struct {
uint32_t ip;
uint32_t client_hits; uint32_t client_hits;
uint32_t peer_hits; uint32_t peer_hits;
uint32_t cmd_hits_auth; uint32_t cmd_hits_auth;
@@ -597,27 +521,30 @@ typedef struct {
uint32_t last_cmd_hit_ago; uint32_t last_cmd_hit_ago;
} RPY_ClientAccesses_Client; } RPY_ClientAccesses_Client;
typedef struct {
uint32_t n_clients;
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
} RPY_ClientAccesses;
typedef struct { typedef struct {
uint32_t n_indices; /* how many indices there are in the server's table */ uint32_t n_indices; /* how many indices there are in the server's table */
uint32_t next_index; /* the index 1 beyond those processed on this call */ uint32_t next_index; /* the index 1 beyond those processed on this call */
uint32_t n_clients; /* the number of valid entries in the following array */ uint32_t n_clients; /* the number of valid entries in the following array */
RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES]; RPY_ClientAccesses_Client clients[MAX_CLIENT_ACCESSES];
int32_t EOR;
} RPY_ClientAccessesByIndex; } RPY_ClientAccessesByIndex;
#define MAX_MANUAL_LIST_SAMPLES 16 #define MAX_MANUAL_LIST_SAMPLES 32
typedef struct { typedef struct {
Timeval when; uint32_t when;
Float slewed_offset; int32_t slewed_offset;
Float orig_offset; int32_t orig_offset;
Float residual; int32_t residual;
} RPY_ManualListSample; } RPY_ManualListSample;
typedef struct { typedef struct {
uint32_t n_samples; uint32_t n_samples;
RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES]; RPY_ManualListSample samples[MAX_MANUAL_LIST_SAMPLES];
int32_t EOR;
} RPY_ManualList; } RPY_ManualList;
typedef struct { typedef struct {
@@ -625,7 +552,6 @@ typedef struct {
int32_t offline; int32_t offline;
int32_t burst_online; int32_t burst_online;
int32_t burst_offline; int32_t burst_offline;
int32_t unresolved;
int32_t EOR; int32_t EOR;
} RPY_Activity; } RPY_Activity;
@@ -637,13 +563,15 @@ typedef struct {
uint16_t command; /* Which command is being replied to */ uint16_t command; /* Which command is being replied to */
uint16_t reply; /* Which format of reply this is */ uint16_t reply; /* Which format of reply this is */
uint16_t status; /* Status of command processing */ uint16_t status; /* Status of command processing */
uint16_t pad1; /* Padding for compatibility and 4 byte alignment */ uint16_t number; /* Which packet this is in reply sequence */
uint16_t pad2; uint16_t total; /* Number of replies to expect in this sequence */
uint16_t pad3; uint16_t pad1; /* Get up to 4 byte alignment */
uint32_t sequence; /* Echo of client's sequence number */ uint32_t sequence; /* Echo of client's sequence number */
uint32_t utoken; /* Unique token per incarnation of daemon */ uint32_t utoken; /* Unique token per incarnation of daemon */
uint32_t token; /* New command token (only if command was successfully uint32_t token; /* New command token (only if command was successfully
authenticated) */ authenticated) */
uint32_t auth[4]; /* MD5 authentication of the packet */
union { union {
RPY_Null null; RPY_Null null;
RPY_N_Sources n_sources; RPY_N_Sources n_sources;
@@ -652,15 +580,13 @@ typedef struct {
RPY_Tracking tracking; RPY_Tracking tracking;
RPY_Sourcestats sourcestats; RPY_Sourcestats sourcestats;
RPY_Rtc rtc; RPY_Rtc rtc;
RPY_SubnetsAccessed subnets_accessed;
RPY_ClientAccesses client_accesses;
RPY_ClientAccessesByIndex client_accesses_by_index; RPY_ClientAccessesByIndex client_accesses_by_index;
RPY_ManualList manual_list; RPY_ManualList manual_list;
RPY_Activity activity; RPY_Activity activity;
} data; /* Reply specific parameters */ } data; /* Reply specific parameters */
/* authentication of the packet, there is no hole after the actual data
from the data union, this field only sets the maximum auth size */
uint8_t auth[MAX_HASH_LENGTH];
} CMD_Reply; } CMD_Reply;
/* ================================================== */ /* ================================================== */

View File

@@ -1,4 +1,4 @@
.TH CHRONY 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual" .TH CHRONY 1 "August 10, 2001" chrony "User's Manual"
.SH NAME .SH NAME
chrony \- programs for keeping computer clocks accurate chrony \- programs for keeping computer clocks accurate
@@ -21,7 +21,7 @@ to the Internet, and it can also act as an RFC1305-compatible NTP server.
.SH USAGE .SH USAGE
\fIchronyc\fR is a command-line interface program which can be used to \fIchronyc\fR is a command-line interface program which can be used to
monitor \fIchronyd\fR's performance and to change various operating monitor \fIchronyd\fR's performance and to change various operating
parameters whilst it is running. parateters whilst it is running.
\fIchronyd\fR's main function is to obtain measurements of the true (UTC) \fIchronyd\fR's main function is to obtain measurements of the true (UTC)
time from one of several sources, and correct the system clock time from one of several sources, and correct the system clock
@@ -30,18 +30,18 @@ gains or loses time and uses this information to keep it accurate
between measurements from the reference. between measurements from the reference.
The reference time can be derived from either Network Time Protocol The reference time can be derived from either Network Time Protocol
(NTP) servers, reference clocks, or wristwatch-and-keyboard (via \fIchronyc\fR). (NTP) servers (preferred), or wristwatch-and-keyboard (via \fIchronyc\fR).
The main source of information about the Network Time Protocol is The main source of information about the Network Time Protocol is
\fIhttp://www.ntp.org\fR. \fIhttp://www.eecis.udel.edu/~ntp\fR.
It is designed so that it can work on computers which only have It is designed so that it can work on computers which only have
intermittent access to reference sources, for example computers which intermittent access to reference sources, for example computers which
use a dial-up account to access the Internet or laptops. Of course, it use a dial-up account to access the Internet. Of course, it will work
will work well on computers with permanent connections too. on computers with permanent connections too.
In addition, on Linux it can monitor the system's real time clock In addition, for Linux 2.0.x (for x >= 32) or 2.2 onwards, chronyd can monitor
performance, so the system can maintain accurate time even across the system's real time clock performance, so the system can maintain accurate
reboots. time even across reboots.
Typical accuracies available between 2 machines are Typical accuracies available between 2 machines are
@@ -49,16 +49,13 @@ On an ethernet LAN : 100-200 microseconds, often much better
On a V32bis dial-up modem connection : 10's of milliseconds (from one On a V32bis dial-up modem connection : 10's of milliseconds (from one
session to the next) session to the next)
With a good reference clock the accuracy can reach one microsecond.
\fIchronyd\fR can also operate as an RFC1305-compatible NTP server and peer. \fIchronyd\fR can also operate as an RFC1305-compatible NTP server and peer.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chronyc(1), .BR chronyc(1),
.BR chrony.conf(5), .BR chrony(1)
.BR chronyd(8)
.I http://chrony.tuxfamily.org/ .I http://chrony.sunsite.dk/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

View File

@@ -1,9 +1,9 @@
.TH chrony.conf 5 "@MAN_DATE@" "chrony @VERSION@" "Configuration Files" .TH chrony.conf 5 "August 10, 2001" chrony "Configuration Files"
.SH NAME .SH NAME
chrony.conf \- chronyd configuration file chrony.conf \- chronyd configuration file
.SH SYNOPSIS .SH SYNOPSIS
.B @SYSCONFDIR@/chrony.conf .B /etc/chrony.conf
.SH DESCRIPTION .SH DESCRIPTION
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer \fIchrony\fR is a pair of programs for maintaining the accuracy of computer
@@ -12,7 +12,7 @@ boot time.
Assuming that you have found some servers, you need to set up a Assuming that you have found some servers, you need to set up a
configuration file to run \fIchrony\fR. The (compiled-in) default location configuration file to run \fIchrony\fR. The (compiled-in) default location
for this file is \fB@SYSCONFDIR@/chrony.conf\fR. Assuming that your ntp servers for this file is \fB/etc/chrony.conf\fR. Assuming that your ntp servers
are called `a.b.c' and `d.e.f', your \fBchrony.conf\fR file could contain are called `a.b.c' and `d.e.f', your \fBchrony.conf\fR file could contain
as a minimum as a minimum
@@ -22,27 +22,24 @@ as a minimum
However, you will probably want to include some of the other directives However, you will probably want to include some of the other directives
described in detail in the documentation supplied with the distribution described in detail in the documentation supplied with the distribution
(\fIchrony.txt\fR and \fIchrony.texi\fR). The following directives may be (\fIchrony.txt\fR and \fIchrony.texi\fR). The following directives will be
particularly useful : `driftfile', `generatecommandkey', `keyfile', `makestep'. particularly useful : `driftfile', `commandkey', `keyfile'. The smallest
Also, the `iburst' server option is useful to speed up the initial useful configuration file would look something like
synchronization. The smallest useful configuration file would look something
like
server a.b.c iburst server a.b.c
server d.e.f iburst server d.e.f
server g.h.i iburst server g.h.i
keyfile @SYSCONFDIR@/chrony.keys keyfile /etc/chrony.keys
generatecommandkey commandkey 1
driftfile @CHRONYVARDIR@/drift driftfile /etc/chrony.drift
makestep 10 3
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chrony(1), .BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chronyd(8) .BR chronyd(1)
.I http://chrony.tuxfamily.org/ .I http://chrony.sunsite.dk/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

29
chrony.lsm Normal file
View File

@@ -0,0 +1,29 @@
Begin3
Title: chrony
Version: 1.18
Entered-date: 01APR02
Description: A pair of programs for keeping computer clocks accurate.
chronyd is a background (daemon) program and chronyc is a
command-line interface to it. Time reference sources for
chronyd can be RFC1305 NTP servers, human (via keyboard and
chronyc), and the computer's real-time clock at boot time
(Linux only). chronyd can determine the rate at which the
computer gains or loses time and compensate for it whilst no
external reference is present. chronyd's use of NTP servers
can be switched on and off (through chronyc) to support
computers with dial-up/intermittent access to the
Internet. chronyd can also act as an RFC1305-compatible NTP
server.
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
295k chrony-1.18.tar.gz
2k chrony.lsm
Platforms: Linux 2.0/2.1/2.2/2.3/2.4 (x86, powerpc)
Solaris 2.5/6/7/8, SunOS 4.1.4. (Sparc)
BSDI/386.
NetBSD
Solaris 2.8 (x86)
Copying-policy: GPL
End

52
chrony.spec.sample Normal file
View File

@@ -0,0 +1,52 @@
Summary: An NTP client/server
Name: chrony
Version: @@VERSION@@
Release: 1
Source: chrony-%{version}.tar.gz
Copyright: GPL
Group: Applications/Utilities
Packager: Richard P. Curnow <rc@rc0.org.uk>
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
Requires: info
%description
A pair of programs for keeping computer clocks accurate. chronyd is a
background (daemon) program and chronyc is a command-line interface to it.
Time reference sources for chronyd can be RFC1305 NTP servers, human (via
keyboard and chronyc), and the computer's real-time clock at boot time (Linux
only). chronyd can determine the rate at which the computer gains or loses
time and compensate for it whilst no external reference is present. chronyd's
use of NTP servers can be switched on and off (through chronyc) to support
computers with dial-up/intermittent access to the Internet. chronyd can also
act as an RFC1305-compatible NTP server.
%prep
%setup
%build
./configure --prefix=%{_prefix} --mandir=%{_mandir}
make CC=gcc CFLAGS=-O2 prefix=%{_prefix}
make chrony.txt prefix=%{_prefix}
make chrony.info prefix=%{_prefix}
%install
rm -rf $RPM_BUILD_ROOT
cd $RPM_BUILD_DIR/chrony-%{version}
make install DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix}
mkdir -p $RPM_BUILD_ROOT%{_infodir}
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
%files
%{_sbindir}/chronyd
%{_bindir}/chronyc
%{_infodir}/chrony.info*
%{_mandir}/man1/chrony.1.gz
%{_mandir}/man1/chronyc.1.gz
%{_mandir}/man5/chrony.conf.5.gz
%{_mandir}/man8/chronyd.8.gz
%doc README
%doc chrony.txt
%doc COPYING
%doc examples/chrony.conf.example
%doc examples/chrony.keys.example

File diff suppressed because it is too large Load Diff

View File

@@ -35,16 +35,10 @@ struct timex {
int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32;
}; };
#define ADJ_OFFSET 0x0001 /* time offset */
#define ADJ_FREQUENCY 0x0002 /* frequency offset */ #define ADJ_FREQUENCY 0x0002 /* frequency offset */
#define ADJ_MAXERROR 0x0004 /* maximum time error */
#define ADJ_STATUS 0x0010 /* clock status */ #define ADJ_STATUS 0x0010 /* clock status */
#define ADJ_TIMECONST 0x0020 /* pll time constant */
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
#define ADJ_NANO 0x2000 /* select nanosecond resolution */
#define ADJ_TICK 0x4000 /* tick value */ #define ADJ_TICK 0x4000 /* tick value */
#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
#define SHIFT_USEC 16 /* frequency offset scale (shift) */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */
@@ -64,7 +58,6 @@ struct timex {
#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ #define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ #define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
#define STA_NANO 0x2000 /* resolution (0 = us, 1 = ns) (ro) */
/* This doesn't seem to be in any include files !! */ /* This doesn't seem to be in any include files !! */

View File

@@ -1,4 +1,4 @@
.TH CHRONYC 1 "@MAN_DATE@" "chrony @VERSION@" "User's Manual" .TH CHRONYC 1 "August 10, 2001" chrony "User's Manual"
.SH NAME .SH NAME
chronyc \- command-line interface for chronyd chronyc \- command-line interface for chronyd
@@ -12,7 +12,7 @@ clocks.
\fBchronyc\fR is a command-line interface program which can be used to \fBchronyc\fR is a command-line interface program which can be used to
monitor \fIchronyd\fR's performance and to change various operating monitor \fIchronyd\fR's performance and to change various operating
parameters whilst it is running. parateters whilst it is running.
.SH USAGE .SH USAGE
A detailed description of all commands supported by \fBchronyc\fR is available A detailed description of all commands supported by \fBchronyc\fR is available
@@ -24,46 +24,29 @@ A summary of the options supported by \fBchronyc\fR is included below.
.TP .TP
\fB\-h\fR \fIhostname\fR \fB\-h\fR \fIhostname\fR
specify hostname (default 127.0.0.1) specify hostname
.TP .TP
\fB\-p\fR \fIport-number\fR \fB\-p\fR \fIport-number\fR
specify port-number specify port-number
.TP .TP
\fB\-n\fR \fB\-n\fR
display raw IP addresses (don't attempt to look up hostnames) display raw IP addresses (don't attempt to look up hostnames)
.TP .TP \fIcommand\fR
\fB\-4\fR
resolve hostnames only to IPv4 addresses
.TP
\fB\-6\fR
resolve hostnames only to IPv6 addresses
.TP
\fB\-m\fR
allow multiple commands to be specified on the command line. Each argument
will be interpreted as a whole command.
.TP
\fB\-f\fR \fIconf-file\fR
This option can be used to specify an alternate location for the
configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR). The configuration file is
needed for the \fB-a\fR option.
.TP
\fB\-a\fR
With this option chronyc will try to authenticate automatically on
start. It will read the configuration file, read the command key from the
keyfile and run the authhash and password commands.
.TP
\fIcommand\fR
specify command. If no command is given, chronyc will read commands specify command. If no command is given, chronyc will read commands
interactively. interactively.
.SH VERSION
1.17
.SH BUGS .SH BUGS
To report bugs, please visit \fIhttp://chrony.tuxfamily.org\fR To report bugs, please contact the author and/or visit \fIhttp://chrony.sunsite.dk/\fR
.SH "SEE ALSO" .SH "SEE ALSO"
.BR chronyd(8), .BR chronyd(8),
.BR chrony(1) .BR chrony(1)
.I http://chrony.tuxfamily.org/ .I http://chrony.sunsite.dk/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>
@@ -73,3 +56,4 @@ Man Pages Project". Please see \fIhttp://www.netmeister.org/misc/m2p2/index.htm
for details. for details.
The complete chrony documentation is supplied in texinfo format. The complete chrony documentation is supplied in texinfo format.

View File

@@ -1,10 +1,10 @@
.TH CHRONYD 8 "@MAN_DATE@" "chrony @VERSION@" "System Administration" .TH CHRONYD 8 "August 10, 2001" chrony "System Administration"
.SH NAME .SH NAME
chronyd \- chrony background daemon chronyd \- chrony background daemon
.SH SYNOPSIS .SH SYNOPSIS
.B chronyd .B chronyd
[\fIOPTIONS\fR] [\fIconfiguration commands\fR] [\fIOPTIONS\fR]
.SH DESCRIPTION .SH DESCRIPTION
\fIchrony\fR is a pair of programs for maintaining the accuracy of computer \fIchrony\fR is a pair of programs for maintaining the accuracy of computer
@@ -21,46 +21,29 @@ gains or loses time, and compensates for this.
.SH USAGE .SH USAGE
\fBchronyd\fR is usually started at boot-time and requires superuser \fBchronyd\fR is usually started at boot-time and requires superuser
privileges. priviliges.
If \fBchronyd\fR has been installed to its default location If \fBchronyd\fR has been installed to its default location
\fI@SBINDIR@/chronyd\fR, starting it is simply a matter of entering the \fI/usr/local/sbin/chronyd\fR, starting it is simply a matter of entering the
command: command:
\fI@SBINDIR@/chronyd\fR \fI/usr/local/sbin/chronyd\fR
Information messages and warnings will be logged to syslog. Information messages and warnings will be logged to syslog.
If no configuration commands are specified on the command line,
\fBchronyd\fR will read the commands from the configuration file
(default \fI@SYSCONFDIR@/chrony.conf\fR).
.SH OPTIONS .SH OPTIONS
A summary of the options supported by \fBchronyd\fR is included below. A summary of the options supported by \fBchronyd\fR is included below.
.TP
\fB\-P\fR \fIpriority\fR
This option will select the SCHED_FIFO real-time scheduler at the specified
priority (which must be between 0 and 100). This mode is supported only on
Linux.
.TP
.B \-m
This option will lock chronyd into RAM so that it will never be paged out.
This mode is only supported on Linux.
.TP
.B \-n
When run in this mode, the program will not detach itself from the
terminal.
.TP .TP
.B \-d .B \-d
When run in this mode, the program will not detach itself from the When run in this mode, the program will not detach itself from the
terminal, and all messages will be sent to the terminal instead of terminal, and all messages will be sent to the terminal instead of
to syslog. When \fBchronyd\fR was compiled with debugging support, to syslog.
this option can be used twice to print also debugging messages.
.TP .TP
\fB\-f\fR \fIconf-file\fR \fB\-f\fR \fIconf-file\fR
This option can be used to specify an alternate location for the This option can be used to specify an alternate location for the
configuration file (default \fI@SYSCONFDIR@/chrony.conf\fR). configuration file (default \fI/etc/chrony.conf\fR).
.TP .TP
.B \-r .B \-r
This option will reload sample histories for each of the servers being used. This option will reload sample histories for each of the servers being used.
@@ -73,76 +56,53 @@ systems where the kernel can maintain clock compensation whilst not under
On systems where this is not the case, e.g. Solaris and SunOS the option On systems where this is not the case, e.g. Solaris and SunOS the option
should not be used. should not be used.
.TP .TP
.B \-R
When this option is used, the \fIinitstepslew\fR directive and the
\fImakestep\fR directive used with a positive limit will be ignored. This
option is useful when restarting \fBchronyd\fR and can be used in conjunction
with the \fB-r\fR option.
.TP
.B \-s .B \-s
This option will set the system clock from the computer's real-time This option will set the system clock from the computer's real-time
clock. This is analogous to supplying the \fI-s\fR flag to the clock. This is analogous to supplying the \fI-s\fR flag to the
\fI/sbin/hwclock\fR program during the Linux boot sequence. \fI/sbin/clock\fR program during the Linux boot sequence.
Support for real-time clocks is limited at present - the criteria Support for real-time clocks is limited at present - the criteria
are described in the section on the \fIrtcfile\fR directive in the are described in the section on the \fIrtcfile\fR directive in the
documentation supplied with the distribution. documentation supplied with the distribution.
If \fBchronyd\fR cannot support the real time clock on your computer,
this option cannot be used and a warning message will be logged to
the syslog.
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
to preserve the old samples after setting the system clock from to preserve the old samples after setting the system clock from
the real time clock (RTC). This can be used to allow \fBchronyd\fR to the real time clock. This can be used to allow \fBchronyd\fR to
perform long term averaging of the gain or loss rate across system perform long term averaging of the gain or loss rate across system
reboots, and is useful for dial-up systems that are shut down when reboots, and is useful for dial-up systems that are shut down when
not in use. For this to work well, it relies on \fBchronyd\fR having not in use. For this to work well, it relies on \fBchronyd\fR having
been able to determine accurate statistics for the difference been able to determine accurate statistics for the difference
between the RTC and system clock last time the computer was on. between the real time clock and system clock last time the
computer was on.
If \fBchronyd\fR doesn't support the RTC on your computer or there is no RTC
installed, the system clock will be set with this option forward to the time of
the last modification of the drift file (specified by the \fIdriftfile\fR
directive) to restore the system time at which \fBchronyd\fR was previously
stopped.
.TP
\fB\-u\fR \fIuser\fR
This option sets the name of the user to which will \fBchronyd\fR switch to
drop root privileges if compiled with Linux capabilities support (default
\fB@DEFAULT_USER@\fR).
.TP
.B \-q
When run in this mode, chronyd will set the system clock once
and exit. It will not detach from the terminal.
.TP
.B \-Q
This option is similar to \fB\-q\fR, but it will only print the offset and
not correct the clock.
.TP .TP
.B \-v .B \-v
This option displays \fBchronyd\fR's version number to the terminal and exits This option displays \fBchronyd\fR's version number to the terminal and exits
.TP
.B \-4
Resolve hostnames only to IPv4 addresses and create only IPv4 sockets.
.TP
.B \-6
Resolve hostnames only to IPv6 addresses and create only IPv6 sockets.
.SH FILES .SH FILES
\fI@SYSCONFDIR@/chrony.conf\fR \fI/etc/chrony.conf\fR
.SH VERSION
Version 1.17
.SH BUGS .SH BUGS
To report bugs, please visit \fIhttp://chrony.tuxfamily.org/\fR To report bugs, please contact the author and/or visit \fIhttp://chrony.sunsite.dk/\fR
.SH "SEE ALSO" .SH "SEE ALSO"
\fBchronyd\fR is documented in detail in the documentation supplied with the \fBchronyd\fR is documented in detail in the documentation supplied with the
distribution (\fIchrony.txt\fR and \fIchrony.texi\fR). distribution (\fIchrony.txt\fR and \fIchrony.texi\fR) and is also available
from \fIhttp://go.to/chrony\fR
.BR chrony(1), .BR chrony(1),
.BR chronyc(1), .BR chronyc(1),
.BR chrony.conf(5), .BR chrony.conf(5),
.BR hwclock(8), .BR clock(8),
.BR xntpd(8),
.BR ntpd(8) .BR ntpd(8)
.I http://chrony.tuxfamily.org/
.SH AUTHOR .SH AUTHOR
Richard Curnow <rc@rc0.org.uk> Richard Curnow <rc@rc0.org.uk>

2433
client.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/clientlog.c,v 1.11 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -31,8 +34,6 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "clientlog.h" #include "clientlog.h"
#include "conf.h" #include "conf.h"
@@ -52,7 +53,7 @@
#define TABLE_SIZE (1UL<<NBITS) #define TABLE_SIZE (1UL<<NBITS)
typedef struct _Node { typedef struct _Node {
IPAddr ip_addr; unsigned long ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_bad; unsigned long cmd_hits_bad;
@@ -68,10 +69,8 @@ typedef struct _Subnet {
/* ================================================== */ /* ================================================== */
/* Table for the IPv4 class A subnet */ /* Table for the class A subnet */
static Subnet top_subnet4; static Subnet top_subnet;
/* Table for IPv6 */
static Subnet top_subnet6;
/* Table containing pointers directly to all nodes that have been /* Table containing pointers directly to all nodes that have been
allocated. */ allocated. */
@@ -83,6 +82,8 @@ static int n_nodes = 0;
/* Number of entries for which the table has been sized. */ /* Number of entries for which the table has been sized. */
static int max_nodes = 0; static int max_nodes = 0;
#define NODE_TABLE_INCREMENT 4
/* Flag indicating whether facility is turned on or not */ /* Flag indicating whether facility is turned on or not */
static int active = 0; static int active = 0;
@@ -95,34 +96,6 @@ static unsigned long alloced;
/* ================================================== */ /* ================================================== */
static void
split_ip6(IPAddr *ip, uint32_t *dst)
{
int i;
for (i = 0; i < 4; i++)
dst[i] = ip->addr.in6[i * 4 + 0] << 24 |
ip->addr.in6[i * 4 + 1] << 16 |
ip->addr.in6[i * 4 + 2] << 8 |
ip->addr.in6[i * 4 + 3];
}
/* ================================================== */
inline static uint32_t
get_subnet(uint32_t *addr, unsigned int where)
{
int off;
off = where / 32;
where %= 32;
return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
}
/* ================================================== */
static void static void
clear_subnet(Subnet *subnet) clear_subnet(Subnet *subnet)
{ {
@@ -152,8 +125,7 @@ clear_node(Node *node)
void void
CLG_Initialise(void) CLG_Initialise(void)
{ {
clear_subnet(&top_subnet4); clear_subnet(&top_subnet);
clear_subnet(&top_subnet6);
if (CNF_GetNoClientLog()) { if (CNF_GetNoClientLog()) {
active = 0; active = 0;
} else { } else {
@@ -174,6 +146,7 @@ CLG_Initialise(void)
void void
CLG_Finalise(void) CLG_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -213,12 +186,13 @@ create_node(Subnet *parent_subnet, int the_entry)
if (n_nodes == max_nodes) { if (n_nodes == max_nodes) {
if (nodes) { if (nodes) {
assert(max_nodes > 0); max_nodes += NODE_TABLE_INCREMENT;
max_nodes *= 2;
nodes = ReallocArray(Node *, max_nodes, nodes); nodes = ReallocArray(Node *, max_nodes, nodes);
} else { } else {
assert(max_nodes == 0); if (max_nodes != 0) {
max_nodes = 16; CROAK("max_nodes should be 0");
}
max_nodes = NODE_TABLE_INCREMENT;
nodes = MallocArray(Node *, max_nodes); nodes = MallocArray(Node *, max_nodes);
} }
alloced += sizeof (Node *) * (max_nodes - n_nodes); alloced += sizeof (Node *) * (max_nodes - n_nodes);
@@ -232,20 +206,29 @@ create_node(Subnet *parent_subnet, int the_entry)
expanding subnet tables and node entries as we go if necessary. */ expanding subnet tables and node entries as we go if necessary. */
static void * static void *
find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed) find_subnet(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
{ {
uint32_t this_subnet; unsigned long this_subnet, new_subnet, mask, shift;
unsigned long new_bits_left;
this_subnet = get_subnet(addr, bits_consumed); shift = 32 - NBITS;
bits_consumed += NBITS; mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
if (bits_consumed < 32 * addr_len) { #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
if (new_bits_left > 0) {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached) if (alloc_limit_reached)
return NULL; return NULL;
create_subnet(subnet, this_subnet); create_subnet(subnet, this_subnet);
} }
return find_subnet((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed); return find_subnet((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
} else { } else {
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
if (alloc_limit_reached) if (alloc_limit_reached)
@@ -262,21 +245,30 @@ find_subnet(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed)
one of the parents does not exist - never open a node out */ one of the parents does not exist - never open a node out */
static void * static void *
find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_consumed) find_subnet_dont_open(Subnet *subnet, CLG_IP_Addr addr, int bits_left)
{ {
uint32_t this_subnet; unsigned long this_subnet, new_subnet, mask, shift;
unsigned long new_bits_left;
if (bits_consumed >= 32 * addr_len) { if (bits_left == 0) {
return subnet; return subnet;
} else { } else {
this_subnet = get_subnet(addr, bits_consumed); shift = 32 - NBITS;
bits_consumed += NBITS; mask = (1UL<<shift) - 1;
this_subnet = addr >> shift;
new_subnet = (addr & mask) << NBITS;
new_bits_left = bits_left - NBITS;
#if 0
fprintf(stderr, "fsdo addr=%08lx bl=%d this=%08lx newsn=%08lx nbl=%d\n",
addr, bits_left, this_subnet, new_subnet, new_bits_left);
#endif
if (!subnet->entry[this_subnet]) { if (!subnet->entry[this_subnet]) {
return NULL; return NULL;
} else { } else {
return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], addr, addr_len, bits_consumed); return find_subnet_dont_open((Subnet *) subnet->entry[this_subnet], new_subnet, new_bits_left);
} }
} }
} }
@@ -284,28 +276,14 @@ find_subnet_dont_open(Subnet *subnet, uint32_t *addr, int addr_len, int bits_con
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPClientAccess (IPAddr *client, time_t now) CLG_LogNTPClientAccess (CLG_IP_Addr client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
switch (client->family) { node = (Node *) find_subnet(&top_subnet, client, 32);
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) if (node == NULL)
return; return;
node->ip_addr = client;
node->ip_addr = *client;
++node->client_hits; ++node->client_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@@ -314,28 +292,14 @@ CLG_LogNTPClientAccess (IPAddr *client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogNTPPeerAccess(IPAddr *client, time_t now) CLG_LogNTPPeerAccess(CLG_IP_Addr client, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
switch (client->family) { node = (Node *) find_subnet(&top_subnet, client, 32);
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) if (node == NULL)
return; return;
node->ip_addr = client;
node->ip_addr = *client;
++node->peer_hits; ++node->peer_hits;
node->last_ntp_hit = now; node->last_ntp_hit = now;
} }
@@ -344,28 +308,14 @@ CLG_LogNTPPeerAccess(IPAddr *client, time_t now)
/* ================================================== */ /* ================================================== */
void void
CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now) CLG_LogCommandAccess(CLG_IP_Addr client, CLG_Command_Type type, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (active) { if (active) {
switch (client->family) { node = (Node *) find_subnet(&top_subnet, client, 32);
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) if (node == NULL)
return; return;
node->ip_addr = client;
node->ip_addr = *client;
node->last_cmd_hit = now; node->last_cmd_hit = now;
switch (type) { switch (type) {
case CLG_CMD_AUTH: case CLG_CMD_AUTH:
@@ -378,7 +328,7 @@ CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
++node->cmd_hits_bad; ++node->cmd_hits_bad;
break; break;
default: default:
assert(0); CROAK("Impossible");
break; break;
} }
} }
@@ -387,32 +337,16 @@ CLG_LogCommandAccess(IPAddr *client, CLG_Command_Type type, time_t now)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result) CLG_GetSubnetBitmap(CLG_IP_Addr subnet, int bits, CLG_Bitmap result)
{ {
Subnet *s; Subnet *s;
uint32_t ip6[4];
unsigned long i; unsigned long i;
unsigned long word, bit, mask; unsigned long word, bit, mask;
if (bits >= 0 && bits % 8 == 0) { if ((bits == 0) || (bits == 8) || (bits == 16) || (bits == 24)) {
memset (result, 0, TABLE_SIZE/8); memset (result, 0, TABLE_SIZE/8);
if (active) { if (active) {
switch (subnet->family) { s = find_subnet_dont_open(&top_subnet, subnet, bits);
case IPADDR_INET4:
if (bits >= 32)
return CLG_BADSUBNET;
s = find_subnet_dont_open(&top_subnet4, &subnet->addr.in4, 1, 32 - bits);
break;
case IPADDR_INET6:
if (bits >= 128)
return CLG_BADSUBNET;
split_ip6(subnet, ip6);
s = find_subnet_dont_open(&top_subnet6, ip6, 4, 128 - bits);
break;
default:
return CLG_BADSUBNET;
}
if (s) { if (s) {
for (i=0; i<256; i++) { for (i=0; i<256; i++) {
if (s->entry[i]) { if (s->entry[i]) {
@@ -437,25 +371,14 @@ CLG_GetSubnetBitmap(IPAddr *subnet, int bits, CLG_Bitmap result)
/* ================================================== */ /* ================================================== */
CLG_Status CLG_Status
CLG_GetClientAccessReportByIP(IPAddr *ip, RPT_ClientAccess_Report *report, time_t now) CLG_GetClientAccessReportByIP(unsigned long ip, RPT_ClientAccess_Report *report, time_t now)
{ {
uint32_t ip6[4];
Node *node; Node *node;
if (!active) { if (!active) {
return CLG_INACTIVE; return CLG_INACTIVE;
} else { } else {
switch (ip->family) { node = (Node *) find_subnet_dont_open(&top_subnet, ip, 32);
case IPADDR_INET4:
node = (Node *) find_subnet_dont_open(&top_subnet4, &ip->addr.in4, 1, 0);
break;
case IPADDR_INET6:
split_ip6(ip, ip6);
node = (Node *) find_subnet_dont_open(&top_subnet6, ip6, 4, 0);
break;
default:
return CLG_EMPTYSUBNET;
}
if (!node) { if (!node) {
return CLG_EMPTYSUBNET; return CLG_EMPTYSUBNET;

View File

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

1116
cmdmon.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/cmdmon.h,v 1.8 2002/02/28 23:27:09 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,13 +31,11 @@
#ifndef GOT_CMDMON_H #ifndef GOT_CMDMON_H
#define GOT_CMDMON_H #define GOT_CMDMON_H
#include "addressing.h" extern void CAM_Initialise(void);
extern void CAM_Initialise(int family);
extern void CAM_Finalise(void); extern void CAM_Finalise(void);
extern int CAM_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all); extern int CAM_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
extern int CAM_CheckAccessRestriction(IPAddr *ip_addr); extern int CAM_CheckAccessRestriction(unsigned long ip_addr);
#endif /* GOT_CMDMON_H */ #endif /* GOT_CMDMON_H */

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/cmdparse.c,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2013
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,57 +30,58 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "cmdparse.h" #include "cmdparse.h"
#include "memory.h"
#include "nameserv.h" #include "nameserv.h"
#include "util.h"
#define MAXLEN 2047
#define SMAXLEN "2047"
/* ================================================== */ /* ================================================== */
CPS_Status CPS_Status
CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src) CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
{ {
char *hostname, *cmd;
int ok, n, done; int ok, n, done;
char cmd[MAXLEN+1], hostname[MAXLEN+1];
CPS_Status result; CPS_Status result;
src->port = SRC_DEFAULT_PORT; src->port = 123;
src->params.minpoll = SRC_DEFAULT_MINPOLL; src->params.minpoll = 6;
src->params.maxpoll = SRC_DEFAULT_MAXPOLL; src->params.maxpoll = 10;
src->params.presend_minpoll = SRC_DEFAULT_PRESEND_MINPOLL; src->params.presend_minpoll = 0;
src->params.authkey = INACTIVE_AUTHKEY; src->params.authkey = INACTIVE_AUTHKEY;
src->params.max_delay = SRC_DEFAULT_MAXDELAY; src->params.max_delay = 16.0;
src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO; src->params.max_delay_ratio = 16384.0;
src->params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
src->params.online = 1; src->params.online = 1;
src->params.auto_offline = 0; src->params.auto_offline = 0;
src->params.iburst = 0;
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
src->params.sel_option = SRC_SelectNormal;
result = CPS_Success; result = CPS_Success;
hostname = line; ok = 0;
line = CPS_SplitWord(line); if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
src->ip_addr = DNS_Name2IPAddress(hostname);
if (src->ip_addr != DNS_Failed_Address) {
ok = 1;
}
}
if (!*hostname) { if (!ok) {
result = CPS_BadHost; result = CPS_BadHost;
ok = 0;
} else { } else {
line += n;
/* Parse subfields */ /* Parse subfields */
ok = 1; ok = 1;
done = 0; done = 0;
do { do {
cmd = line; if (sscanf(line, "%" SMAXLEN "s%n", cmd, &n) == 1) {
line = CPS_SplitWord(line);
if (*cmd) { line += n;
if (!strcasecmp(cmd, "port")) {
if (!strncasecmp(cmd, "port", 4)) {
if (sscanf(line, "%hu%n", &src->port, &n) != 1) { if (sscanf(line, "%hu%n", &src->port, &n) != 1) {
result = CPS_BadPort; result = CPS_BadPort;
ok = 0; ok = 0;
@@ -85,7 +89,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "minpoll")) { } else if (!strncasecmp(cmd, "minpoll", 7)) {
if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.minpoll, &n) != 1) {
result = CPS_BadMinpoll; result = CPS_BadMinpoll;
ok = 0; ok = 0;
@@ -93,7 +97,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "maxpoll")) { } else if (!strncasecmp(cmd, "maxpoll", 7)) {
if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.maxpoll, &n) != 1) {
result = CPS_BadMaxpoll; result = CPS_BadMaxpoll;
ok = 0; ok = 0;
@@ -101,7 +105,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "presend")) { } else if (!strncasecmp(cmd, "presend", 7)) {
if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1) { if (sscanf(line, "%d%n", &src->params.presend_minpoll, &n) != 1) {
result = CPS_BadPresend; result = CPS_BadPresend;
ok = 0; ok = 0;
@@ -109,15 +113,8 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "maxdelaydevratio")) { /* This MUST come before the following one ! */
if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) { } else if (!strncasecmp(cmd, "maxdelayratio", 13)) {
result = CPS_BadMaxdelaydevratio;
ok = 0;
done = 1;
} else {
line += n;
}
} else if (!strcasecmp(cmd, "maxdelayratio")) {
if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) { if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) {
result = CPS_BadMaxdelayratio; result = CPS_BadMaxdelayratio;
ok = 0; ok = 0;
@@ -125,7 +122,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "maxdelay")) { } else if (!strncasecmp(cmd, "maxdelay", 8)) {
if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1) { if (sscanf(line, "%lf%n", &src->params.max_delay, &n) != 1) {
result = CPS_BadMaxdelay; result = CPS_BadMaxdelay;
ok = 0; ok = 0;
@@ -133,48 +130,20 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "key")) { } else if (!strncasecmp(cmd, "key", 3)) {
if (sscanf(line, "%lu%n", &src->params.authkey, &n) != 1 || if (sscanf(line, "%lu%n", &src->params.authkey, &n) != 1) {
src->params.authkey == INACTIVE_AUTHKEY) {
result = CPS_BadKey; result = CPS_BadKey;
ok = 0; ok = 0;
done = 1; done = 1;
} else { } else {
line += n; line += n;
} }
} else if (!strcasecmp(cmd, "offline")) { } else if (!strncasecmp(cmd, "offline", 7)) {
src->params.online = 0; src->params.online = 0;
} else if (!strcasecmp(cmd, "auto_offline")) { } else if (!strncasecmp(cmd, "auto_offline", 12)) {
src->params.auto_offline = 1; src->params.auto_offline = 1;
} else if (!strcasecmp(cmd, "iburst")) {
src->params.iburst = 1;
} else if (!strcasecmp(cmd, "minstratum")) {
if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) {
result = CPS_BadMinstratum;
ok = 0;
done = 1;
} else {
line += n;
}
} else if (!strcasecmp(cmd, "polltarget")) {
if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
result = CPS_BadPolltarget;
ok = 0;
done = 1;
} else {
line += n;
}
} else if (!strcasecmp(cmd, "noselect")) {
src->params.sel_option = SRC_SelectNoselect;
} else if (!strcasecmp(cmd, "prefer")) {
src->params.sel_option = SRC_SelectPrefer;
} else { } else {
result = CPS_BadOption; result = CPS_BadOption;
ok = 0; ok = 0;
@@ -186,97 +155,9 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
} while (!done); } while (!done);
} }
if (ok) {
src->name = strdup(hostname);
}
return result; return result;
} }
/* ================================================== */ /* ================================================== */
void
CPS_NormalizeLine(char *line)
{
char *p, *q;
int space = 1, first = 1;
/* Remove white-space at beginning and replace white-spaces with space char */
for (p = q = line; *p; p++) {
if (isspace((unsigned char)*p)) {
if (!space)
*q++ = ' ';
space = 1;
continue;
}
/* Discard comment lines */
if (first && strchr("!;#%", *p))
break;
*q++ = *p;
space = first = 0;
}
/* Strip trailing space */
if (q > line && q[-1] == ' ')
q--;
*q = '\0';
}
/* ================================================== */
char *
CPS_SplitWord(char *line)
{
char *p = line, *q = line;
/* Skip white-space before the word */
while (*q && isspace((unsigned char)*q))
q++;
/* Move the word to the beginning */
while (*q && !isspace((unsigned char)*q))
*p++ = *q++;
/* Find the next word */
while (*q && isspace((unsigned char)*q))
q++;
*p = '\0';
/* Return pointer to the next word or NUL */
return q;
}
/* ================================================== */
int
CPS_ParseKey(char *line, unsigned long *id, const char **hash, char **key)
{
char *s1, *s2, *s3, *s4;
s1 = line;
s2 = CPS_SplitWord(s1);
s3 = CPS_SplitWord(s2);
s4 = CPS_SplitWord(s3);
/* Require two or three words */
if (!*s2 || *s4)
return 0;
if (sscanf(s1, "%lu", id) != 1)
return 0;
if (*s3) {
*hash = s2;
*key = s3;
} else {
*hash = "MD5";
*key = s2;
}
return 1;
}

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/cmdparse.h,v 1.7 2002/02/28 23:27:09 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,7 +32,6 @@
#define GOT_CMDPARSE_H #define GOT_CMDPARSE_H
#include "srcparams.h" #include "srcparams.h"
#include "addressing.h"
typedef enum { typedef enum {
CPS_Success, CPS_Success,
@@ -38,30 +41,20 @@ typedef enum {
CPS_BadMinpoll, CPS_BadMinpoll,
CPS_BadMaxpoll, CPS_BadMaxpoll,
CPS_BadPresend, CPS_BadPresend,
CPS_BadMaxdelaydevratio,
CPS_BadMaxdelayratio, CPS_BadMaxdelayratio,
CPS_BadMaxdelay, CPS_BadMaxdelay,
CPS_BadKey, CPS_BadKey
CPS_BadMinstratum,
CPS_BadPolltarget
} CPS_Status; } CPS_Status;
typedef struct { typedef struct {
char *name; unsigned long ip_addr;
unsigned short port; unsigned short port;
SourceParameters params; SourceParameters params;
} CPS_NTP_Source; } CPS_NTP_Source;
/* Parse a command to add an NTP server or peer */ /* Parse a command to add an NTP server or peer */
extern CPS_Status CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src); extern CPS_Status CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src);
/* Remove extra white-space and comments */
extern void CPS_NormalizeLine(char *line);
/* Terminate first word and return pointer to the next word */
extern char *CPS_SplitWord(char *line);
/* Parse a key from keyfile */
extern int CPS_ParseKey(char *line, unsigned long *id, const char **hash, char **key);
#endif /* GOT_CMDPARSE_H */ #endif /* GOT_CMDPARSE_H */

1566
conf.c

File diff suppressed because it is too large Load Diff

62
conf.h
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/conf.h,v 1.25 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2013-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,82 +31,45 @@
#ifndef GOT_CONF_H #ifndef GOT_CONF_H
#define GOT_CONF_H #define GOT_CONF_H
#include "addressing.h"
extern void CNF_SetRestarted(int);
extern char *CNF_GetRtcDevice(void); extern char *CNF_GetRtcDevice(void);
extern void CNF_ReadFile(const char *filename); extern void CNF_ReadFile(const char *filename);
extern void CNF_ParseLine(const char *filename, int number, char *line);
extern void CNF_AddInitSources(void);
extern void CNF_AddSources(void); extern void CNF_AddSources(void);
extern void CNF_AddBroadcasts(void); extern void CNF_AddBroadcasts(void);
extern void CNF_AddRefclocks(void);
extern int CNF_GetAcquisitionPort(void); extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
extern int CNF_GetNTPPort(void);
extern unsigned short CNF_GetAcquisitionPort(void);
extern unsigned short CNF_GetNTPPort(void);
extern char *CNF_GetDriftFile(void); extern char *CNF_GetDriftFile(void);
extern char *CNF_GetLogDir(void); extern char *CNF_GetLogDir(void);
extern char *CNF_GetDumpDir(void); extern char *CNF_GetDumpDir(void);
extern int CNF_GetLogBanner(void);
extern int CNF_GetLogMeasurements(void); extern int CNF_GetLogMeasurements(void);
extern int CNF_GetLogStatistics(void); extern int CNF_GetLogStatistics(void);
extern int CNF_GetLogTracking(void); extern int CNF_GetLogTracking(void);
extern int CNF_GetLogRtc(void); extern int CNF_GetLogRtc(void);
extern int CNF_GetLogRefclocks(void);
extern int CNF_GetLogTempComp(void);
extern char *CNF_GetKeysFile(void); extern char *CNF_GetKeysFile(void);
extern char *CNF_GetRtcFile(void); extern char *CNF_GetRtcFile(void);
extern unsigned long CNF_GetCommandKey(void); extern unsigned long CNF_GetCommandKey(void);
extern int CNF_GetGenerateCommandKey(void);
extern int CNF_GetDumpOnExit(void); extern int CNF_GetDumpOnExit(void);
extern int CNF_GetManualEnabled(void); extern int CNF_GetManualEnabled(void);
extern int CNF_GetCommandPort(void); extern int CNF_GetCommandPort(void);
extern int CNF_GetRtcOnUtc(void); extern int CNF_GetRTCOnUTC(void);
extern int CNF_GetRtcSync(void);
extern void CNF_GetMakeStep(int *limit, double *threshold);
extern void CNF_GetMaxChange(int *delay, int *ignore, double *offset);
extern void CNF_GetLogChange(int *enabled, double *threshold); extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user); extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void); extern int CNF_GetNoClientLog(void);
extern unsigned long CNF_GetClientLogLimit(void); extern unsigned long CNF_GetClientLogLimit(void);
extern void CNF_GetFallbackDrifts(int *min, int *max); extern void CNF_GetBindAddress(unsigned long *addr);
extern void CNF_GetBindAddress(int family, IPAddr *addr); extern void CNF_GetBindCommandAddress(unsigned long *addr);
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
extern char *CNF_GetPidFile(void); extern char *CNF_GetPidFile(void);
extern char *CNF_GetLeapSecTimezone(void); extern void CNF_GetLinuxHz(int *set, int *hz);
extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale);
/* Value returned in ppm, as read from file */ /* Value returned in ppm, as read from file */
extern double CNF_GetMaxUpdateSkew(void); extern double CNF_GetMaxUpdateSkew(void);
extern double CNF_GetMaxClockError(void);
extern double CNF_GetCorrectionTimeRatio(void);
extern double CNF_GetMaxSlewRate(void);
extern double CNF_GetReselectDistance(void);
extern double CNF_GetStratumWeight(void);
extern double CNF_GetCombineLimit(void);
extern int CNF_AllowLocalReference(int *stratum); extern int CNF_AllowLocalReference(int *stratum);
extern void CNF_SetupAccessRestrictions(void); extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void);
extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2);
extern char *CNF_GetUser(void);
extern int CNF_GetMaxSamples(void);
extern int CNF_GetMinSamples(void);
extern double CNF_GetRtcAutotrim(void);
extern char *CNF_GetHwclockFile(void);
extern int CNF_GetInitSources(void);
extern double CNF_GetInitStepThreshold(void);
#endif /* GOT_CONF_H */ #endif /* GOT_CONF_H */

687
configure vendored
View File

@@ -1,15 +1,15 @@
#!/bin/sh #!/bin/sh
#
# $Header: /cvs/src/chrony/configure,v 1.30 2003/09/22 21:53:57 richard Exp $
#
# ======================================================================= # =======================================================================
# #
# chronyd/chronyc - Programs for keeping computer clocks accurate. # chronyd/chronyc - Programs for keeping computer clocks accurate.
# #
# Copyright (C) Richard P. Curnow 1997-2003 # Copyright (C) Richard P. Curnow 1997-2003
# Copyright (C) Miroslav Lichvar 2009, 2012-2014
# #
# ======================================================================= # =======================================================================
rm -f config.h config.log
# This configure script determines the operating system type and version # This configure script determines the operating system type and version
if [ "x${CC}" = "x" ]; then if [ "x${CC}" = "x" ]; then
@@ -24,60 +24,92 @@ else
MYCFLAGS="${CFLAGS}" MYCFLAGS="${CFLAGS}"
fi fi
MYCPPFLAGS="${CPPFLAGS}"
if [ "x${MYCC}" = "xgcc" ]; then
MYCFLAGS="${MYCFLAGS} -Wmissing-prototypes -Wall"
fi
MYLDFLAGS="${LDFLAGS}"
# ====================================================================== # ======================================================================
# FUNCTIONS # FUNCTIONS
#{{{ test_code #{{{ test_for_sqrt
test_code () { test_for_sqrt () {
name=$1 # 0 : doesn't need -lm
headers=$2 # 1 : needs -lm
cflags=$3 # 2 : doesn't even link with -lm
ldflags=$4
code=$5
echo -n "Checking for $name : " cat >docheck.c <<EOF;
#include <math.h>
( int main(int argc, char **argv) {
for h in $headers; do return (int) sqrt((double)argc);
echo "#include <$h>" }
done EOF
echo "int main(int argc, char **argv) {"
echo "$code"
echo "return 0; }"
) > docheck.c
echo "docheck.c:" >> config.log
cat docheck.c >> config.log
echo $MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
$MYLDFLAGS >> config.log
$MYCC $MYCFLAGS $MYCPPFLAGS $cflags -o docheck docheck.c $ldflags \
$MYLDFLAGS >> config.log 2>&1
${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
if [ $? -eq 0 ] if [ $? -eq 0 ]
then then
echo "Yes"
result=0 result=0
else else
echo "No"
result=1 result=1
fi fi
rm -f docheck.c docheck
echo >> config.log rm -f docheck.c docheck.o
return $result echo $result
}
#}}}
#{{{ test_for_inttypes_h
test_for_inttypes_h () {
cat >docheck.c <<EOF;
#include <inttypes.h>
int main(int argc, char **argv) {
return 0;
}
EOF
${MYCC} ${MYCFLAGS} -c -o docheck.o docheck.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
result=0
else
result=1
fi
rm -f docheck.c docheck.o
echo $result
} }
#}}} #}}}
#{{{ usage #{{{ usage
usage () { usage () {
cat <<EOF cat <<EOF;
\`configure' configures this package to adapt to many kinds of systems. \`configure' configures tdl to adapt to many kinds of systems.
Usage: ./configure [OPTION]... Usage: ./configure [OPTION]...
@@ -89,8 +121,6 @@ Configuration:
Installation directories: Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX --prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local] [/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in By default, \`make install' will install all the files in
\`/usr/local/bin', \`/usr/local/lib' etc. You can specify \`/usr/local/bin', \`/usr/local/lib' etc. You can specify
@@ -98,75 +128,31 @@ an installation prefix other than \`/usr/local' using \`--prefix',
for instance \`--prefix=$HOME'. for instance \`--prefix=$HOME'.
For better control, use the options below. For better control, use the options below.
--disable-readline Disable line editing support --disable-readline Don't try to use GNU readline
--without-readline Don't use GNU readline even if it is available
--without-editline Don't use editline even if it is available
--readline-dir=DIR Specify parent of readline include and lib directories --readline-dir=DIR Specify parent of readline include and lib directories
--readline-inc-dir=DIR Specify where readline include directory is --readline-inc-dir=DIR Specify where readline include directory is
--readline-lib-dir=DIR Specify where readline lib directory is --readline-lib-dir=DIR Specify where readline lib directory is
--with-ncurses-library=DIR Specify where ncurses lib directory is --with-ncurses-library=DIR Specify where ncurses lib directory is
--without-nss Don't use NSS even if it is available
--without-tomcrypt Don't use libtomcrypt even if it is available
--disable-ipv6 Disable IPv6 support
--disable-phc Disable PHC support
--disable-pps Disable PPS API support
--disable-rtc Don't include RTC even on Linux --disable-rtc Don't include RTC even on Linux
--disable-linuxcaps Disable Linux capabilities support
--disable-asyncdns Disable asynchronous name resolving
--disable-forcednsretry Don't retry on permanent DNS error
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
since 1970-01-01 [50*365 days ago]
--with-user=USER Specify default chronyd user [root]
--with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail]
--enable-debug Enable debugging support
Fine tuning of the installation directories: Fine tuning of the installation directories:
--sysconfdir=DIR chrony.conf location [/etc] --infodir=DIR info documentation [PREFIX/info]
--bindir=DIR user executables [EPREFIX/bin] --mandir=DIR man documentation [PREFIX/man]
--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]
--localstatedir=DIR modifiable single-machine data [/var]
--chronyvardir=DIR location for chrony data [LOCALSTATEDIR/lib/chrony]
Overriding system detection when cross-compiling:
--host-system=OS Specify system name (uname -s)
--host-release=REL Specify system release (uname -r)
--host-machine=CPU Specify machine (uname -m)
Some influential environment variables: Some influential environment variables:
CC C compiler command CC C compiler command
CFLAGS C compiler flags CFLAGS C compiler flags
CPPFLAGS C preprocessor flags, e.g. -I<include dir> if you have
headers in a nonstandard directory <include dir>
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir> nonstandard directory <lib dir>
Use these variables to override the choices made by \`configure' or to help Use these variables to override the choices made by \`configure' or to help
it to find libraries and programs with nonstandard names/locations. it to find libraries and programs with nonstandard names/locations.
Report bugs to <rc@rc0.org.uk>.
EOF EOF
} }
#}}} #}}}
#{{{
add_def () {
if [ "x$2" = "x" ]; then
echo "#define $1 1" >> config.h
else
echo "#define $1 $2" >> config.h
fi
}
#}}}
#{{{ pkg_config
pkg_config () {
type pkg-config > /dev/null 2> /dev/null || return 1
pkg-config $@ 2> /dev/null
}
#}}}
# ====================================================================== # ======================================================================
@@ -176,52 +162,37 @@ OPERATINGSYSTEM=`uname -s`
VERSION=`uname -r` VERSION=`uname -r`
MACHINE=`uname -m` MACHINE=`uname -m`
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
EXTRA_LIBS="" EXTRA_LIBS=""
EXTRA_CLI_LIBS="" EXTRA_CLI_LIBS=""
EXTRA_OBJECTS="" EXTRA_OBJECTS=""
EXTRA_DEFS="" EXTRA_DEFS=""
INSTALL_PREFIX=/usr/local
SYSDEFS="" SYSDEFS=""
debug=0 # Support for readline (on by default)
feat_readline=1 feat_readline=1
try_readline=1
try_editline=1
try_nss=1
try_tomcrypt=1
feat_rtc=1 feat_rtc=1
try_rtc=0
feat_linuxcaps=1
try_linuxcaps=0
readline_lib="" readline_lib=""
readline_inc="" readline_inc=""
ncurses_lib="" ncurses_lib=""
feat_ipv6=1
feat_phc=1 SETINFODIR=""
try_phc=0 SETMANDIR=""
feat_pps=1
try_setsched=0
try_lockmem=0
feat_asyncdns=1
feat_forcednsretry=1
ntp_era_split=""
default_user="root"
mail_program="/usr/lib/sendmail"
for option for option
do do
case "$option" in case "$option" in
--enable-debug ) --prefix=* | --install_prefix=* )
debug=1 INSTALL_PREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--trace )
EXTRA_DEFS="-DTRACEON"
;; ;;
--disable-readline ) --disable-readline )
feat_readline=0 feat_readline=0
;; ;;
--without-readline )
try_readline=0
;;
--without-editline )
try_editline=0
;;
--with-readline-library=* ) --with-readline-library=* )
readline_lib=-L`echo $option | sed -e 's/^.*=//;'` readline_lib=-L`echo $option | sed -e 's/^.*=//;'`
;; ;;
@@ -231,84 +202,15 @@ do
--with-ncurses-library=* ) --with-ncurses-library=* )
ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'` ncurses_lib=-L`echo $option | sed -e 's/^.*=//;'`
;; ;;
--prefix=* | --install_prefix=* )
SETPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--exec-prefix=* )
SETEPREFIX=`echo $option | sed -e 's/[^=]*=//;'`
;;
--sysconfdir=* )
SETSYSCONFDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--bindir=* )
SETBINDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--sbindir=* )
SETSBINDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--datarootdir=* )
SETDATAROOTDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--infodir=* ) --infodir=* )
SETINFODIR=`echo $option | sed -e 's/^.*=//;'` SETINFODIR=`echo $option | sed -e 's/^.*=//;'`
;; ;;
--mandir=* ) --mandir=* )
SETMANDIR=`echo $option | sed -e 's/^.*=//;'` SETMANDIR=`echo $option | sed -e 's/^.*=//;'`
;; ;;
--docdir=* )
SETDOCDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--localstatedir=* )
SETLOCALSTATEDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--chronyvardir=* )
SETCHRONYVARDIR=`echo $option | sed -e 's/^.*=//;'`
;;
--disable-rtc) --disable-rtc)
feat_rtc=0 feat_rtc=0
;; ;;
--disable-ipv6)
feat_ipv6=0
;;
--disable-phc)
feat_phc=0
;;
--disable-pps)
feat_pps=0
;;
--disable-linuxcaps)
feat_linuxcaps=0
;;
--disable-asyncdns)
feat_asyncdns=0
;;
--disable-forcednsretry)
feat_forcednsretry=0
;;
--with-ntp-era=* )
ntp_era_split=`echo $option | sed -e 's/^.*=//;'`
;;
--with-user=* )
default_user=`echo $option | sed -e 's/^.*=//;'`
;;
--with-sendmail=* )
mail_program=`echo $option | sed -e 's/^.*=//;'`
;;
--without-nss )
try_nss=0
;;
--without-tomcrypt )
try_tomcrypt=0
;;
--host-system=* )
OPERATINGSYSTEM=`echo $option | sed -e 's/^.*=//;'`
;;
--host-release=* )
VERSION=`echo $option | sed -e 's/^.*=//;'`
;;
--host-machine=* )
MACHINE=`echo $option | sed -e 's/^.*=//;'`
;;
--help | -h ) --help | -h )
usage usage
exit 0 exit 0
@@ -318,49 +220,50 @@ do
esac esac
done done
SYSTEM=${OPERATINGSYSTEM}-${MACHINE}
case $SYSTEM in case $SYSTEM in
SunOS-sun4* ) SunOS-sun4* )
case $VERSION in case $VERSION in
4.* ) 4.* )
EXTRA_OBJECTS="sys_sunos.o strerror.o" EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm" EXTRA_LIBS="-lkvm"
add_def SUNOS SYSDEFS="-DSUNOS"
echo "Configuring for SunOS (" $SYSTEM "version" $VERSION ")" echo "Configuring for SunOS (" $SYSTEM "version" $VERSION ")"
;; ;;
5.* ) 5.* )
EXTRA_OBJECTS="sys_solaris.o" EXTRA_OBJECTS="sys_solaris.o"
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf" EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
EXTRA_CLI_LIBS="-lsocket -lnsl" EXTRA_CLI_LIBS="-lsocket -lnsl"
add_def SOLARIS SYSDEFS="-DSOLARIS"
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")" echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
if [ $VERSION = "5.3" ]; then
SYSDEFS="$SYSDEFS -DHAS_NO_BZERO"
echo "Using memset() instead of bzero()"
fi
;; ;;
esac esac
;; ;;
Linux* ) Linux* )
EXTRA_OBJECTS="sys_generic.o sys_linux.o wrap_adjtimex.o" EXTRA_OBJECTS="sys_linux.o wrap_adjtimex.o"
try_linuxcaps=1 if [ $feat_rtc -eq 1 ] ; then
try_rtc=1 EXTRA_OBJECTS+=" rtc_linux.o"
try_setsched=1 EXTRA_DEFS+=" -DFEAT_RTC=1"
try_lockmem=1 fi
try_phc=1 SYSDEFS="-DLINUX"
add_def LINUX
echo "Configuring for " $SYSTEM echo "Configuring for " $SYSTEM
if [ "${MACHINE}" = "alpha" ]; then if [ "${MACHINE}" = "alpha" ]; then
echo "Enabling -mieee" echo "Enabling -mieee"
# FIXME: Should really test for GCC # FIXME: Should really test for GCC
MYCFLAGS="$MYCFLAGS -mieee" SYSDEFS="$SYSDEFS -mieee -DALPHA"
fi fi
;; ;;
BSD/386-i[3456]86|FreeBSD-i386|FreeBSD-amd64 ) BSD/386-i[3456]86|FreeBSD-i386 )
# Antti Jrvinen <costello@iki.fi> reported that this system can # Antti Jrvinen <costello@iki.fi> reported that this system can
# be supported with the SunOS 4.x driver files. # be supported with the SunOS 4.x driver files.
EXTRA_OBJECTS="sys_sunos.o strerror.o" EXTRA_OBJECTS="sys_sunos.o strerror.o"
EXTRA_LIBS="-lkvm" EXTRA_LIBS="-lkvm"
add_def SUNOS SYSDEFS="-DSUNOS"
echo "Configuring for $SYSTEM (using SunOS driver)" echo "Configuring for BSD/386 (using SunOS driver)"
;; ;;
NetBSD-* ) NetBSD-* )
EXTRA_OBJECTS="sys_netbsd.o" EXTRA_OBJECTS="sys_netbsd.o"
@@ -374,13 +277,13 @@ case $SYSTEM in
EXTRA_OBJECTS="sys_solaris.o" EXTRA_OBJECTS="sys_solaris.o"
EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf" EXTRA_LIBS="-lsocket -lnsl -lkvm -lelf"
EXTRA_CLI_LIBS="-lsocket -lnsl" EXTRA_CLI_LIBS="-lsocket -lnsl"
add_def SOLARIS SYSDEFS="-DSOLARIS"
echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")" echo "Configuring for Solaris (" $SYSTEM "SunOS version" $VERSION ")"
;; ;;
CYGWIN32_NT-i[3456]86 ) CYGWIN32_NT-i[3456]86 )
EXTRA_OBJECTS="sys_winnt.o" EXTRA_OBJECTS="sys_winnt.o"
EXTRA_LIBS="" EXTRA_LIBS=""
add_def WINNT SYSDEFS="-DWINNT"
echo "Configuring for Windows NT (Cygwin32)" echo "Configuring for Windows NT (Cygwin32)"
;; ;;
* ) * )
@@ -389,345 +292,77 @@ case $SYSTEM in
;; ;;
esac esac
if test_code '64-bit time_t' 'time.h' '' '' ' printf "Checking if sqrt() needs -lm : "
char x[sizeof(time_t) > 4 ? 1 : -1] = {0}; case `test_for_sqrt`
return x[0];' in
then 0)
add_def HAVE_LONG_TIME_T 1 printf "No\n"
if [ "x$ntp_era_split" != "x" ]; then
split_seconds=$ntp_era_split
split_days=0
else
split_seconds=`date '+%s'`
if [ "x$split_seconds" = "" ]; then
echo "Could not get current time, --with-ntp-era option is needed"
exit 1
fi
split_days=$((50 * 365))
fi
add_def NTP_ERA_SPLIT "(${split_seconds}LL - $split_days * 24 * 3600)"
date_format='+%Y-%m-%dT%H:%M:%SZ'
# Print the full NTP interval if a suitable date is found
if [ "x`date -u -d '1970-01-01 UTC 9 days ago 5 seconds 3 seconds' \
$date_format 2> /dev/null`" = "x1969-12-23T00:00:08Z" ]
then
time1="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds" \
$date_format`"
time2="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds 4294967296 seconds" \
$date_format`"
echo "NTP time mapped to $time1/$time2"
fi
fi
MATHCODE='return (int) pow(2.0, log(sqrt((double)argc)));'
if test_code 'math' 'math.h' '' '' "$MATHCODE"; then
LIBS="" 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"
SYSDEFS="${SYSDEFS} -DHAS_STDINT_H"
else else
if test_code 'math in -lm' 'math.h' '' '-lm' "$MATHCODE"; then printf "No\n"
LIBS="-lm"
else
echo "Can't compile/link a program which uses sqrt(), log(), pow(), bailing out"
exit 1
fi
fi fi
if test_code '<stdint.h>' 'stdint.h' '' '' ''; then printf "Checking for <inttypes.h> : "
add_def HAS_STDINT_H if [ `test_for_inttypes_h` -eq 0 ]; then
printf "Yes\n"
SYSDEFS="${SYSDEFS} -DHAS_INTTYPES_H"
else
printf "No\n"
fi fi
if test_code '<inttypes.h>' 'inttypes.h' '' '' ''; then if [ "x${MYCC}" = "xgcc" ]; then
add_def HAS_INTTYPES_H CCWARNFLAGS="-Wmissing-prototypes -Wall"
else
CCWARNFLAGS=""
fi fi
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
add_def HAVE_IPV6
if test_code 'in6_pktinfo' 'sys/socket.h netinet/in.h' '' '' '
return sizeof(struct in6_pktinfo);'
then
add_def HAVE_IN6_PKTINFO
else
if test_code 'in6_pktinfo with _GNU_SOURCE' 'sys/socket.h netinet/in.h' \
'-D_GNU_SOURCE' '' 'return sizeof(struct in6_pktinfo);'
then
add_def _GNU_SOURCE
add_def HAVE_IN6_PKTINFO
fi
fi
fi
if test_code 'getaddrinfo()' 'sys/types.h sys/socket.h netdb.h' '' '' \
'return getaddrinfo(0, 0, 0, 0);'
then
add_def HAVE_GETADDRINFO
fi
if [ $feat_asyncdns = "1" ] && \
test_code 'pthread' 'pthread.h' '-pthread' '' \
'return pthread_create((void *)1, NULL, (void *)1, NULL);'
then
add_def FEAT_ASYNCDNS
add_def USE_PTHREAD_ASYNCDNS
MYCFLAGS="$MYCFLAGS -pthread"
fi
timepps_h=""
if [ $feat_pps = "1" ]; then
if test_code '<sys/timepps.h>' 'sys/timepps.h' '' '' ''; then
timepps_h="sys/timepps.h"
add_def HAVE_SYS_TIMEPPS_H
else
if test_code '<timepps.h>' 'timepps.h' '' '' ''; then
timepps_h="timepps.h"
add_def HAVE_TIMEPPS_H
fi
fi
fi
if [ "x$timepps_h" != "x" ] && \
test_code 'PPSAPI' "string.h $timepps_h" '' '' '
pps_handle_t h = 0;
pps_info_t i;
struct timespec ts;
return time_pps_fetch(h, PPS_TSFMT_TSPEC, &i, &ts);'
then
add_def HAVE_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
add_def FEAT_LINUXCAPS
EXTRA_LIBS="$EXTRA_LIBS -lcap"
fi
if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \
test_code '<linux/rtc.h>' 'sys/ioctl.h linux/rtc.h' '' '' \
'ioctl(1, RTC_UIE_ON&RTC_UIE_OFF&RTC_RD_TIME&RTC_SET_TIME, 0&RTC_UF);'
then
EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o"
add_def FEAT_RTC
fi
if [ $feat_phc = "1" ] && [ $try_phc = "1" ] && \
test_code '<linux/ptp_clock.h>' 'sys/ioctl.h linux/ptp_clock.h' '' '' \
'ioctl(1, PTP_CLOCK_GETCAPS, 0);'
then
if test_code 'clock_gettime()' 'time.h' '' '' 'clock_gettime(0, NULL);'; then
add_def FEAT_PHC
else
if test_code 'clock_gettime() in -lrt' 'time.h' '' '-lrt' \
'clock_gettime(0, NULL);'
then
EXTRA_LIBS="$EXTRA_LIBS -lrt"
add_def FEAT_PHC
fi
fi
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
add_def HAVE_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
add_def HAVE_MLOCKALL
fi
if [ $feat_forcednsretry = "1" ]
then
add_def FORCE_DNSRETRY
fi
READLINE_COMPILE=""
READLINE_LINK=""
if [ $feat_readline = "1" ]; then if [ $feat_readline = "1" ]; then
if [ $try_editline = "1" ]; then READLINE_COMPILE="-DFEAT_READLINE=1 $readline_inc"
if test_code editline 'stdio.h editline/readline.h' \ READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
"$readline_inc" "$readline_lib -ledit" \ else
'add_history(readline("prompt"));' READLINE_COMPILE=""
then READLINE_LINK=""
add_def FEAT_READLINE
add_def USE_EDITLINE
READLINE_COMPILE="$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 -lreadline" \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
READLINE_COMPILE="$readline_inc"
READLINE_LINK="$readline_lib -lreadline"
fi
fi
if [ "x$READLINE_LINK" = "x" ] && [ $try_readline = "1" ]; then
if test_code 'readline with -lncurses' \
'stdio.h readline/readline.h readline/history.h' \
"$readline_inc" "$readline_lib $ncurses_lib -lreadline -lncurses" \
'add_history(readline("prompt"));'
then
add_def FEAT_READLINE
READLINE_COMPILE="$readline_inc"
READLINE_LINK="$readline_lib $ncurses_lib -lreadline -lncurses"
fi
fi
EXTRA_CLI_LIBS="$EXTRA_CLI_LIBS $READLINE_LINK"
fi fi
HASH_OBJ="hash_intmd5.o" MANDIR=${INSTALL_PREFIX}/man
HASH_COMPILE="" INFODIR=${INSTALL_PREFIX}/info
HASH_LINK=""
if [ $try_nss = "1" ]; then
test_cflags="`pkg_config --cflags nss`"
test_link="`pkg_config --libs-only-L nss` -lfreebl3"
if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \
"$test_cflags" "$test_link" \
'NSSLOWHASH_Begin(NSSLOWHASH_NewContext(NSSLOW_Init(), HASH_AlgSHA512));'
then
HASH_OBJ="hash_nss.o"
HASH_COMPILE="$test_cflags"
HASH_LINK="$test_link"
LIBS="$LIBS $HASH_LINK"
add_def GENERATE_SHA1_KEY
fi
fi
if [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]; then
if test_code 'tomcrypt' 'tomcrypt.h' '-I/usr/include/tomcrypt' '-ltomcrypt' \
'hash_memory_multi(find_hash("md5"), NULL, NULL, NULL, 0, NULL, 0);'
then
HASH_OBJ="hash_tomcrypt.o"
HASH_COMPILE="-I/usr/include/tomcrypt"
HASH_LINK="-ltomcrypt"
LIBS="$LIBS $HASH_LINK"
add_def GENERATE_SHA1_KEY
fi
fi
SYSCONFDIR=/etc
if [ "x$SETSYSCONFDIR" != "x" ]; then
SYSCONFDIR=$SETSYSCONFDIR
fi
PREFIX=/usr/local
if [ "x$SETPREFIX" != "x" ]; then
PREFIX=$SETPREFIX
fi
EPREFIX=${PREFIX}
if [ "x$SETEPREFIX" != "x" ]; then
EPREFIX=$SETEPREFIX
fi
BINDIR=${EPREFIX}/bin
if [ "x$SETBINDIR" != "x" ]; then
BINDIR=$SETBINDIR
fi
SBINDIR=${EPREFIX}/sbin
if [ "x$SETSBINDIR" != "x" ]; then
SBINDIR=$SETSBINDIR
fi
DATAROOTDIR=${PREFIX}/share
if [ "x$SETDATAROOTDIR" != "x" ]; then
DATAROOTDIR=$SETDATAROOTDIR
fi
INFODIR=${DATAROOTDIR}/info
if [ "x$SETINFODIR" != "x" ]; then if [ "x$SETINFODIR" != "x" ]; then
INFODIR=$SETINFODIR INFODIR=$SETINFODIR
fi fi
MANDIR=${DATAROOTDIR}/man
if [ "x$SETMANDIR" != "x" ]; then if [ "x$SETMANDIR" != "x" ]; then
MANDIR=$SETMANDIR MANDIR=$SETMANDIR
fi fi
DOCDIR=${DATAROOTDIR}/doc/chrony sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
if [ "x$SETDOCDIR" != "x" ]; then s%@CC@%${MYCC}%;\
DOCDIR=$SETDOCDIR s%@CFLAGS@%${MYCFLAGS}%;\
fi s%@CCWARNFLAGS@%${CCWARNFLAGS}%;\
s%@LIBS@%${LIBS}%;\
LOCALSTATEDIR=/var s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
if [ "x$SETLOCALSTATEDIR" != "x" ]; then s%@SYSDEFS@%${SYSDEFS}%;\
LOCALSTATEDIR=$SETLOCALSTATEDIR s%@EXTRA_DEFS@%${EXTRA_DEFS}%;\
fi s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
CHRONYVARDIR=${LOCALSTATEDIR}/lib/chrony s%@READLINE_LINK@%${READLINE_LINK}%;\
if [ "x$SETCHRONYVARDIR" != "x" ]; then s%@INSTALL_PREFIX@%${INSTALL_PREFIX}%;\
CHRONYVARDIR=$SETCHRONYVARDIR s%@MANDIR@%${MANDIR}%;\
fi s%@INFODIR@%${INFODIR}%;"\
< Makefile.in > Makefile
add_def DEBUG $debug
add_def DEFAULT_CONF_FILE "\"$SYSCONFDIR/chrony.conf\""
add_def DEFAULT_USER "\"$default_user\""
add_def MAIL_PROGRAM "\"$mail_program\""
if [ -f version.txt ]; then
add_def CHRONY_VERSION "\"`cat version.txt`\""
else
add_def CHRONY_VERSION "\"DEVELOPMENT\""
fi
for f in Makefile chrony.conf.5 chrony.texi chronyc.1 chronyd.8
do
echo Creating $f
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\
s%@CC@%${MYCC}%;\
s%@CFLAGS@%${MYCFLAGS}%;\
s%@CPPFLAGS@%${MYCPPFLAGS}%;\
s%@LIBS@%${LIBS}%;\
s%@LDFLAGS@%${MYLDFLAGS}%;\
s%@EXTRA_LIBS@%${EXTRA_LIBS}%;\
s%@EXTRA_CLI_LIBS@%${EXTRA_CLI_LIBS}%;\
s%@READLINE_COMPILE@%${READLINE_COMPILE}%;\
s%@HASH_OBJ@%${HASH_OBJ}%;\
s%@HASH_COMPILE@%${HASH_COMPILE}%;\
s%@SYSCONFDIR@%${SYSCONFDIR}%;\
s%@BINDIR@%${BINDIR}%;\
s%@SBINDIR@%${SBINDIR}%;\
s%@DOCDIR@%${DOCDIR}%;\
s%@MANDIR@%${MANDIR}%;\
s%@INFODIR@%${INFODIR}%;\
s%@LOCALSTATEDIR@%${LOCALSTATEDIR}%;\
s%@CHRONYVARDIR@%${CHRONYVARDIR}%;\
s%@DEFAULT_USER@%${default_user}%;"\
< ${f}.in > $f
done
# ======================================================================= # =======================================================================
# vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s # vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s

View File

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

View File

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

View File

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

View File

@@ -1,17 +0,0 @@
[Unit]
Description=Wait for chrony to synchronize system clock
After=chronyd.service
Requires=chronyd.service
Before=time-sync.target
Wants=time-sync.target
[Service]
Type=oneshot
# Wait up to ~10 minutes for chronyd to synchronize and the remaining
# clock correction to be less than 0.1 seconds
ExecStart=/usr/bin/chronyc waitsync 60 0.1
RemainAfterExit=yes
StandardOutput=null
[Install]
WantedBy=multi-user.target

View File

@@ -1,8 +1,9 @@
####################################################################### #######################################################################
# $Header: /cvs/src/chrony/examples/chrony.conf.example,v 1.2 2002/02/03 21:46:29 richard Exp $
# #
# This is an example chrony configuration file. You should copy it to # This is an example chrony configuration file. You should copy it to
# /etc/chrony.conf after uncommenting and editing the options that you # /etc/chrony.conf after uncommenting and editing the options that you
# want to enable. The more obscure options are not included. Refer # want to enable. I have not included the more obscure options. Refer
# to the documentation for these. # to the documentation for these.
# #
# Copyright 2002 Richard P. Curnow # Copyright 2002 Richard P. Curnow
@@ -18,7 +19,7 @@
# #
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
# #
# #
####################################################################### #######################################################################
@@ -40,21 +41,21 @@
# more 'NTP servers'. You will probably find that your Internet Service # more 'NTP servers'. You will probably find that your Internet Service
# Provider or company have one or more NTP servers that you can specify. # Provider or company have one or more NTP servers that you can specify.
# Failing that, there are a lot of public NTP servers. There is a list # Failing that, there are a lot of public NTP servers. There is a list
# you can access at http://support.ntp.org/bin/view/Servers/WebHome or # you can access at
# you can use servers from the pool.ntp.org project. # http://www.eecis.udel.edu/~mills/ntp/servers.htm.
! server 0.pool.ntp.org iburst ! server ntp0.your-isp.com
! server 1.pool.ntp.org iburst ! server ntp1.your-isp.com
! server 2.pool.ntp.org iburst ! server ntp.public-server.org
# However, for dial-up use you probably want these instead. The word # However, for dial-up use you probably want these instead. The word
# 'offline' means that the server is not visible at boot time. Use # 'offline' means that the server is not visible at boot time. Use
# chronyc's 'online' command to tell chronyd that these servers have # chronyc's 'online' command to tell chronyd that these servers have
# become visible after you go on-line. # become visible after you go on-line.
! server 0.pool.ntp.org offline ! server ntp0.your-isp.com offline
! server 1.pool.ntp.org offline ! server ntp1.your-isp.com offline
! server 2.pool.ntp.org offline ! server ntp.public-server.org offline
# You may want to specify NTP 'peers' instead. If you run a network # You may want to specify NTP 'peers' instead. If you run a network
# with a lot of computers and want several computers running chrony to # with a lot of computers and want several computers running chrony to
@@ -89,7 +90,7 @@
# immediately so that it doesn't gain or lose any more time. You # immediately so that it doesn't gain or lose any more time. You
# generally want this, so it is uncommented. # generally want this, so it is uncommented.
driftfile /var/lib/chrony/drift driftfile /etc/chrony.drift
# If you want to use the program called chronyc to configure aspects of # If you want to use the program called chronyc to configure aspects of
# chronyd's operation once it is running (e.g. tell it the Internet link # chronyd's operation once it is running (e.g. tell it the Internet link
@@ -106,9 +107,6 @@ keyfile /etc/chrony.keys
commandkey 1 commandkey 1
# With this directive a random password will be generated automatically.
generatecommandkey
# chronyd can save the measurement history for the servers to files when # chronyd can save the measurement history for the servers to files when
# it it exits. This is useful in 2 situations: # it it exits. This is useful in 2 situations:
# #
@@ -125,7 +123,7 @@ generatecommandkey
# Enable these two options to use this. # Enable these two options to use this.
! dumponexit ! dumponexit
! dumpdir /var/lib/chrony ! dumpdir /var/log/chrony
# chronyd writes its process ID to a file. If you try to start a second # chronyd writes its process ID to a file. If you try to start a second
# copy of chronyd, it will detect that the process named in the file is # copy of chronyd, it will detect that the process named in the file is
@@ -136,16 +134,17 @@ generatecommandkey
####################################################################### #######################################################################
### INITIAL CLOCK CORRECTION ### INITIAL CLOCK CORRECTION
# This option is useful to quickly correct the clock on start if it's # This option is only useful if your NTP servers are visible at boot
# off by a large amount. The value '10' means that if the error is less # time. This probably means you are on a LAN. If so, the following
# option will choose the best-looking of the servers and correct the
# system time to that. The value '10' means that if the error is less
# than 10 seconds, it will be gradually removed by speeding up or # than 10 seconds, it will be gradually removed by speeding up or
# slowing down your computer's clock until it is correct. If the error # slowing down your computer's clock until it is correct. If the error
# is above 10 seconds, an immediate time jump will be applied to correct # is above 10 seconds, an immediate time jump will be applied to correct
# it. The value '1' means the step is allowed only on the first update # it. Some software can get upset if the system clock jumps (especially
# of the clock. Some software can get upset if the system clock jumps # backwards), so be careful!
# (especially backwards), so be careful!
! makestep 10 1 ! initstepslew 10 ntp0.your-company.com ntp1.your-company.com ntp2.your-company.com
####################################################################### #######################################################################
### LOGGING ### LOGGING
@@ -158,8 +157,8 @@ generatecommandkey
! logdir /var/log/chrony ! logdir /var/log/chrony
! log measurements statistics tracking ! log measurements statistics tracking
# If you have real time clock support enabled (see below), you might want If you have real time clock support enabled (see below), you might want
# this line instead: this line instead:
! log measurements statistics tracking rtc ! log measurements statistics tracking rtc
@@ -210,12 +209,6 @@ generatecommandkey
! noclientlog ! noclientlog
# The clientlog size is limited to 512KB by default. If you have many
# clients, especially in many different subnets, you might want to
# increase the limit.
! clientloglimit 4194304
####################################################################### #######################################################################
### REPORTING BIG CLOCK CHANGES ### REPORTING BIG CLOCK CHANGES
# Perhaps you want to know if chronyd suddenly detects any large error # Perhaps you want to know if chronyd suddenly detects any large error
@@ -257,6 +250,13 @@ generatecommandkey
# put into chronyc to allow you to modify chronyd's parameters. By # put into chronyc to allow you to modify chronyd's parameters. By
# default all you can do is view information about chronyd's operation. # default all you can do is view information about chronyd's operation.
# Some people have reported that the need the following line to allow
# chronyc to work even on the same machine. This should not be
# necessary, and the problem is being investigated. You can leave this
# line enabled, as it's benign otherwise.
cmdallow 127.0.0.1
####################################################################### #######################################################################
### REAL TIME CLOCK ### REAL TIME CLOCK
# chronyd can characterise the system's real-time clock. This is the # chronyd can characterise the system's real-time clock. This is the
@@ -268,7 +268,7 @@ generatecommandkey
# You need to have 'enhanced RTC support' compiled into your Linux # You need to have 'enhanced RTC support' compiled into your Linux
# kernel. (Note, these options apply only to Linux.) # kernel. (Note, these options apply only to Linux.)
! rtcfile /var/lib/chrony/rtc ! rtcfile /etc/chrony.rtc
# Your RTC can be set to keep Universal Coordinated Time (UTC) or local # Your RTC can be set to keep Universal Coordinated Time (UTC) or local
# time. (Local time means UTC +/- the effect of your timezone.) If you # time. (Local time means UTC +/- the effect of your timezone.) If you
@@ -287,21 +287,3 @@ generatecommandkey
! rtcdevice /dev/misc/rtc ! rtcdevice /dev/misc/rtc
####################################################################### #######################################################################
### REAL TIME SCHEDULER
# This directive tells chronyd to use the real-time FIFO scheduler with the
# specified priority (which must be between 0 and 100). This should result
# in reduced latency. You don't need it unless you really have a requirement
# for extreme clock stability. Works only on Linux. Note that the "-P"
# command-line switch will override this.
! sched_priority 1
#######################################################################
### LOCKING CHRONYD INTO RAM
# This directive tells chronyd to use the mlockall() syscall to lock itself
# into RAM so that it will never be paged out. This should result in reduced
# latency. You don't need it unless you really have a requirement
# for extreme clock stability. Works only on Linux. Note that the "-m"
# command-line switch will also enable this feature.
! lock_all

View File

@@ -1,46 +0,0 @@
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst
# Ignore stratum in source selection.
stratumweight 0
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
# Enable kernel RTC synchronization.
rtcsync
# In first three updates step the system clock instead of slew
# if the adjustment is larger than 10 seconds.
makestep 10 3
# Allow NTP client access from local network.
#allow 192.168/16
# Listen for commands only on localhost.
bindcmdaddress 127.0.0.1
bindcmdaddress ::1
# Serve time even if not synchronized to any NTP server.
#local stratum 10
keyfile /etc/chrony.keys
# Specify the key used as password for chronyc.
commandkey 1
# Generate command key if missing.
generatecommandkey
# Disable logging of client accesses.
noclientlog
# Send a message to syslog if a clock adjustment is larger than 0.5 seconds.
logchange 0.5
logdir /var/log/chrony
#log measurements statistics tracking

View File

@@ -1,29 +1,27 @@
####################################################################### #######################################################################
# $Header: /cvs/src/chrony/examples/chrony.keys.example,v 1.1 2002/01/31 00:00:08 richard Exp $
# #
# This is an example chrony keys file. You should copy it to /etc/chrony.keys # This is an example chrony keys file. You should copy it to /etc/chrony.keys
# after editing it to set up the key(s) you want to use. It should be readable # after editing it to set up the key(s) you want to use. In most situations,
# only by root or the user chronyd drops the root privileges to. In most # you will require a single key (the 'commandkey') so that you can supply a
# situations, you will require a single key (the 'commandkey') so that you can # password to chronyc to enable you to modify chronyd's operation whilst it is
# supply a password to chronyc to enable you to modify chronyd's operation # running.
# whilst it is running.
# #
# Copyright 2002 Richard P. Curnow # Copyright 2002 Richard P. Curnow
# #
###################################################################### #######################################################################
# A valid key line looks like this
# Examples of valid keys: 1 a_key
#1 ALongAndRandomPassword # It must consist of an integer, followed by whitespace, followed by a block of
#2 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC # text with no spaces in it. (You cannot put a space in a key). If you wanted
#3 SHA1 HEX:1DC764E0791B11FA67EFC7ECBC4B0D73F68A070C # to use the above line as your commandkey (i.e. chronyc password), you would
# put the following line into chrony.conf (remove the # from the start):
# The keys should be random for maximum security. If you wanted to use a key # commandkey 1
# with ID 1 as your commandkey (i.e. chronyc password) you would put
# "commandkey 1" into chrony.conf. If no commandkey is present in the keys
# file and the generatecommandkey directive is specified in chrony.conf,
# a random commandkey will be generated and added to the keys file
# automatically on chronyd start.
# You might want to define more keys if you use the authentication facility # You might want to define more keys if you use the MD5 authentication facility
# in the network time protocol to authenticate request/response packets between # in the network time protocol to authenticate request/response packets between
# trusted clients and servers. # trusted clients and servers.

View File

@@ -1,8 +0,0 @@
/var/log/chrony/*.log {
missingok
nocreate
sharedscripts
postrotate
/usr/bin/chronyc -a cyclelogs > /dev/null 2>&1 || true
endscript
}

View File

@@ -1,17 +0,0 @@
#!/bin/sh
# This is a NetworkManager dispatcher script for chronyd to set its NTP sources
# online/offline when a default route is configured/removed on the system.
export LC_ALL=C
if [ "$2" = "up" ]; then
/sbin/ip route list dev "$1" | grep -q '^default' &&
/usr/bin/chronyc -a online > /dev/null 2>&1
fi
if [ "$2" = "down" ]; then
/sbin/ip route list | grep -q '^default' ||
/usr/bin/chronyc -a offline > /dev/null 2>&1
fi
exit 0

View File

@@ -1,57 +0,0 @@
%global chrony_version @@VERSION@@
%if 0%(echo %{chrony_version} | grep -q pre && echo 1)
%global prerelease %(echo %{chrony_version} | sed 's/.*-//')
%endif
Summary: An NTP client/server
Name: chrony
Version: %(echo %{chrony_version} | sed 's/-.*//')
Release: %{!?prerelease:1}%{?prerelease:0.1.%{prerelease}}
Source: chrony-%{version}%{?prerelease:-%{prerelease}}.tar.gz
License: GPLv2
Group: Applications/Utilities
BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(id -u -n)
Requires: info
%description
chrony is a client and server for the Network Time Protocol (NTP).
This program keeps your computer's clock accurate. It was specially
designed to support systems with intermittent Internet connections,
but it also works well in permanently connected environments. It can
also use hardware reference clocks, the system real-time clock, or
manual input as time references.
%prep
%setup -q -n %{name}-%{version}%{?prerelease:-%{prerelease}}
%build
./configure \
--prefix=%{_prefix} \
--bindir=%{_bindir} \
--sbindir=%{_sbindir} \
--infodir=%{_infodir} \
--mandir=%{_mandir}
make
make chrony.txt
make chrony.info
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
rm -rf $RPM_BUILD_ROOT%{_docdir}
mkdir -p $RPM_BUILD_ROOT%{_infodir}
cp chrony.info* $RPM_BUILD_ROOT%{_infodir}
%files
%{_sbindir}/chronyd
%{_bindir}/chronyc
%{_infodir}/chrony.info*
%{_mandir}/man1/chrony.1.gz
%{_mandir}/man1/chronyc.1.gz
%{_mandir}/man5/chrony.conf.5.gz
%{_mandir}/man8/chronyd.8.gz
%doc README
%doc chrony.txt
%doc COPYING
%doc examples/chrony.conf.example*
%doc examples/chrony.keys.example

View File

@@ -1,13 +0,0 @@
[Unit]
Description=NTP client/server
After=ntpdate.service sntp.service ntpd.service
Conflicts=ntpd.service systemd-timesyncd.service
[Service]
Type=forking
PIDFile=/var/run/chronyd.pid
EnvironmentFile=-/etc/sysconfig/chronyd
ExecStart=/usr/sbin/chronyd $OPTIONS
[Install]
WantedBy=multi-user.target

387
faq.txt Normal file
View File

@@ -0,0 +1,387 @@
@@PROLOGUE
<html>
<head>
<title>Frequently asked questions</title>
<meta name="description" content="Chrony FAQ (frequently asked questions)">
<meta name="keywords" content="chrony,network time protocol,NTP,RFC 1305,dial-up connection,real time clock,RTC,Linux,FAQ,frequently asked questns">
<?php
$root = ".";
include "$root/styles.php";
?>
</head>
<body>
<?php
include 'main_banner.php';
include 'header.php';
?>
<?php pretty_h1("Introduction") ?>
<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
to this page.
<hr>
<p>
The author can be reached by email
<a href="mailto:rc@rc0.org.uk">
</a>
<p>
<b>PLEASE</b>
include the word &quot;chrony&quot; in your subject line if possible (so that my
mail reader can keep my mail sorted by topic)!
<hr>
<br clear=all>
@@ENDPROLOGUE
S: Administrative issues
Q: Where can I get chrony source code?
Via the home page, see below.
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.
Q: Where is the home page?
It is currently at <a href="http://chrony.sunsite.dk/">http://chrony.sunsite.dk/</a>.
Q: Is there a mailing list?
Yes, it's currently at chrony-users@sunsite.dk. 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.
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>.
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.
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
is, for the several hours it takes xntpd to settle down), or you need to
support hardware reference clocks to your computer, then xntpd will work fine.
Apart from not supporting hardware clocks, chrony will work fine too.
If your computer connects to the 'net for 5 minutes once a day (or something
like that), or you turn your (Linux v2.0) computer off when you're not using
it, or you want to use NTP on an isolated network with no hardware clocks in
sight, chrony will work much better for you.
The reason I wrote chrony was that I could not get xntpd to do
anything sensible on my PC at home, which is connected to the 'net for
about 5 minutes once or twice a day, mainly to upload/download email
and news. Nowadays it is also turned off for 22-23 hours a day, when
not in use. I wanted a program which would :
- slew the time to correct it when I go online and NTP servers become visible
- determine the rate at which the computer gains or loses time and use this
information to keep it reasonably correct between connects to the 'net. This
has to be done using a method that does not care about the intermittent
availability of the references or the fact the computer is turned off between
groups of measurements..
- maintain the time across reboots, by working out the error and drift rate of
the computer's real-time clock and using this information to set the system
clock correctly at boot up. (In the last few months, it became impossible for
me to leave my computer powered permanently.)
Also, when working with isolated networks with no true time references
at all, I found xntpd gave me no help with managing the local clock's
gain/loss rate on the NTP master node (which I set from my watch). I
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
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:
tar xzvf ../chrony-1.X.tar.gz
cd chrony-1.X
gunzip < ../../chrony-1.X-1.X.1.gz | patch -p1
./configure
make
make install
Q:Can I compile chrony with an ANSI-C compiler that is not GCC v2.x?
I have had reports that chrony can be compiled with GCC v1.42, by using the
following trick when running make
make CC='gcc -D__FUNCTION__=\"function_not_available\"'
(this gets around the lack of a __FUNCTION__ macro in GCC v1.)
The same trick may be enough to allow other compilers to be used.
Q: I get errors like 'client.c:44: readline/readline.h: file not found'
Read the section about 'readline' in the INSTALL file or in chrony.txt. You
may need to disable readline support (e.g. if you haven't got readline
installed at all, or just don't want it), or specify the location of the
readline files (e.g. if you've installed them in a non-standard place).
Q: I have RedHat 7.3 and can't compile rtc_linux.c (error in spinlock.h)
The following solution has been found for this. Enter the following 3 commands
(as root):
cd /usr/include/
mv linux linux.rh
ln -s /usr/src/linux/include/linux ./linux
The problem seems to be that RedHat provide their own kernel header files in
/usr/include/linux. Besides differing from those used by your current kernel,
if you compiled it yourself, they also seem to have been changed in a way that
causes a problem compiling chrony. Chrony compiles fine with standard kernel
header files.
There have also been reports that just replacing the file
/usr/src/linux/spinlock.h by the equivalent file from a vanilla kernel source
tree is sufficient to fix the problem.
Note : from version 1.21 onwards, this problem no longer exists. The kernel
header files are no longer included.
S: Selection of NTP servers
Q: I have several computers on a LAN. Should I make one the master, or make them all clients of an external server?
I think the best configuration is to make one computer the master, with the
others as clients of it. Add a 'local' directive to the master's chrony.conf
file. This configuration will be better because
* the load on the external connection is less
* the load on the external NTP server(s) is less
* if your external connection goes down, the computers on the LAN will maintain
a common time with each other.
S: Addressing issues
Q: I get the following error message : "Could not get IP adress for localhost"
Add a line like the following to your /etc/hosts file
127.0.0.1 localhost
Q: I have problems if I put the names of my NTP servers in the chrony.conf file.
If you have no connection to the Internet at boot time, chrony won't be able to
turn the names into IP addresses when it starts. There seem to be 2 solutions:
1. Put the numeric IP addresses in the chrony.conf file
or
2. Put the server->IP address mappings in your /etc/hosts file and ensure that
/etc/host.conf reads 'order hosts,bind'.
The problem is that chronyd (currently) isn't designed in a way that allows
hostname->IP address lookups during normal operation. I hope to work on this
problem very soon.
S: My computer is not synchronising.
This is the most common problem. There are a number of reasons, see the
following questions.
Q: Behind a firewall?
If there is a firewall between you and the NTP server you're trying to use,
the packets may be blocked. Try using a tool like etherfind or tcpdump to see
if you're getting responses from the server. If you have an external modem,
see if the receive light blinks straight after the transmit light (when the
link is quiet apart from the NTP traffic.) Try adding 'log measurements' to
the chrony.conf file and look in the measurements.log file after chrony has
been running for a short period. See if any measurements appear.
Most people run chronyd on the firewall itself, to avoid all issues of UDP
packet forwarding and/or masquerading.
Q: Do you have a non-permanant (i.e. intermittent) Internet connection?
Check that you're using chronyc's 'online' and 'offline' commands
appropriately. Again, check in measurements.log to see if you're getting any
data back from the server.
Q: In measurements.log, do the '7' and '8' flag columns always show zero?
Do you have a 'local stratum X' directive in the chrony.conf file? If X is
lower than the stratum of the server you're trying to use, this situation will
arise. You should always make X quite high (e.g. 10) in this directive.
S: Issues with chronyd
Q: chronyd crashes after a syslog message "adjtimex failed for set frequency"
The usual cause is that the kernel is running with a different value of 'HZ'
(the timer interrupt rate) than the value that was found in the kernel header
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'.
Make sure that the chrony.conf file (on the computer where chronyd is running)
has a 'cmdallow' entry for the computer you are running chronyc on. This
shouldn't be necessary for localhost, but some people still seem to need an
entry like 'cmdallow 127.0.0.1'. (It would be good to understand why problem
only affects some people).
Q: I cannot log in from chronyc to carry out privileged tasks.
This is the second most common problem.
Perhaps your /etc/chrony.keys file is badly formatted. Make sure that the
final line has a line feed at the end, otherwise the key on that line will work
as though the last character is missing. (Note, this bug was fixed in version
1.16.)
Q: When I enter a command and hit &lt;Return&gt;, chronyc hangs
This probably means that chronyc cannot communicate with chronyd.
Perhaps chronyd is not running. Try using the ps command (e.g. on Linux, 'ps
-auxw') to see if it's running. Or try 'netstat -a' and see if the ports
123/udp and 323/udp are listening. If chronyd is not running, you may have a
problem with the way you are trying to start it (e.g. at boot time).
Perhaps you have a firewall set up in a way that blocks packets on port
323/udp. You need to amend the firewall configuration in this case.
Q: Is the chronyc&lt;-&gt;chronyd protocol documented anywhere?
Only by the source code :-) See cmdmon.c (chronyd side) and client.c (chronyc
side).
S: Real-time clock issues.
Q: What is the real-time clock (RTC)?
This is the clock which keeps the time even when your computer is turned off.
It works with 1 second resolution. chronyd can monitor the rate at which the
real-time clock gains or loses time, and compensate for it when you set the
system time from it at the next reboot. See the documentation for details.
Q: I want to use chronyd's real-time clock support. Must I disable hwclock?
The hwclock program is often set-up by default in the boot and shutdown scripts
with many Linux installations. If you want to use chronyd's real-time clock
support, the important thing is to disable hwclock in the <b>shutdown</b>
procedure. If you don't, it will over-write the RTC with a new value, unknown
to chronyd. At the next reboot, chronyd will compensate this (wrong) time with
its estimate of how far the RTC has drifted whilst the power was off, giving a
meaningless initial system time.
There is no need to remove hwclock from the boot process, as long as chronyd is
started after it has run.
Q: I just keep getting the '513 RTC driver not running' message
For the real time clock support to work, you need the following three things:
* a kernel that is supported (e.g. 2.2 onwards)
* enhanced RTC support compiled into the kernel
* an 'rtcfile' directive in your chrony.conf file.
S: Problems with isolated networks.
Q: When I use the 'settime' command, chronyd crashes.
If you enter times that are too far away from the real time, chronyd will
think the system clock runs fast or slow by an excessive amount. The required
compensation factor will be outside the bounds for the adjtimex() system call.
chronyd will crash when it tries to apply such an excessive adjustment.
S: Microsoft Windows
Q: Does chrony support Windows?
No. The chronyc program (the command-line client used for configuring
chronyd while it is running) has been successfully built and run under Cygwin
in the past. chronyd is not portable, because part of it is very
system-dependent. It needs adapting to work with Windows' equivalent of the
adjtimex() call, and it needs to be made to work as 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
contribute it back to the project.
Q: What alternative NTP clients are there for Windows?
Some of the names I've seen mentioned are
- Automachron
- NetTime (nettime.sourceforge.net)
S: NTP-specific issues
Q: Can chrony be driven from broadcast NTP servers?
No. I remember looking at how they worked when I was first writing chrony.
Since the 'target market' then was dial-up systems, broadcast packets were not
relevant so I didn't bother working out how to deal with the complexities of
doing the delay estimation.
I no longer have root access to a LAN environment to develop and test broadcast
server support. Neither have I the time to work on this. I would be very
happy to accept a patch from anyone who can develop, test and debug the
necessary changes!
Q: Can chronyd transmit broadcast NTP packets (e.g. to synchronise other computers on a private LAN)?
Yes. Starting from version 1.17, chrony has this capability.
Q: Can chrony keep the system clock a fixed offset away from real time?
I have not experimented much, but I don't believe this would be possible as
the program currently stands.
Q: What happens if the network connection is dropped without using chronyc's 'offline' command first?
In this case chronyd will keep trying to access the server(s) that it thinks
are online. Eventually it will decide that they are unreachable and no longer
consider itself synchronised to them. If you have other computers on your LAN
accessing the computer that is affected this way, they too will become
'unsynchronised', unless you have the 'local' directive set up on the master
computer.
The 'auto_offline' option to the 'server' entry in the chrony.conf file may be
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.
S: Linux-specific issues
Q: Why does the source code include kernel header files?
The program needs to see the definitions of structures used to interact with
the real time clock (via /dev/rtc) and with the adjtimex() system call. Sadly
this has led to a number of compilation problems with newer kernels which have
been increasingly hard to fix in a way that makes the code compilable on all
Linux kernel versions (from 2.0 up anyway, I doubt 1.x still works.) Hopefully
the situation will not deteriorate further with future kernel versions.
Q: I get "Could not open /dev/rtc, Device or resource busy" in my syslog file.
Check that you haven't accidentally got two copies of chronyd running (perhaps
defined in different start-up scripts.)
S: Solaris-specific issues
Q: On Solaris 2.8, I get an error message about not being able to open kvm to change dosynctodr.
(The dosynctodr variable controls whether Solaris couples the equivalent of its
BIOS clock into its system clock at regular intervals). The Solaris port of
chrony was developed in the Solaris 2.5 era. Some aspect of the Solaris kernel
has changed which prevents the same technique working. I no longer have root
access to any Solaris machines to work on this, and am reliant on somebody
developing the patch and testing it. A good starting point would be to see if
xntpd has been modified to work for Solaris 2.8.
@@EPILOGUE
<hr>
Back to
<a href="mailto:rc@rc0.org.uk?subject=chrony">the author</a>'s
<a href="http://www.rc0.org.uk/">main page</a>
</body>
</html>
@@ENDEPILOGUE

140
faqgen.pl Normal file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env perl
# $Header
# Copyright 2001 Richard P. Curnow
# LICENCE
# A script to generate an HTML FAQ page from a text input file. The input is assumed to consist of the following:
# Lines starting with 'S:'. These introduce sections.
# Lines starting with 'Q:'. These are the topics of questions.
# Body text (either as an introduction to the sections, or as answers to the questions.
# The body text is set as pre-formatted.
$| = 1;
@prologue = ();
@epilogue = ();
@sections=(); # section titles
@sect_text=(); # introductory text in sections
@questions=(); # questions in sections
@answers=(); # answers to questions
$sn = -1;
$had_q = 0;
#{{{ Parse input
while (<>) {
if (m/\@\@PROLOG/o) {
while (<>) {
last if (m/^\@\@ENDPROLOG/);
push (@prologue, $_);
}
} elsif (m/\@\@EPILOG/o) {
while (<>) {
last if (m/^\@\@ENDEPILOG/);
push (@epilogue, $_);
}
} elsif (m/^[sS]:[ \t]*(.*)$/) {
chomp;
$qn = -1;
++$sn;
$sections[$sn] = &guard($1);
$sect_text[$sn] = "";
$questions[$sn] = [ ];
$answers[$sn] = [ ];
$had_q = 0;
} elsif (/^[qQ]:[ \t]*(.*)$/) {
chomp;
die unless ($sn >= 0);
++$qn;
$questions[$sn]->[$qn] = &guard($1);
$had_q = 1;
} else {
if ($had_q) {
if ($qn >= 0) {
$answers[$sn]->[$qn] .= $_;
}
} else {
if ($sect_text[$sn] ne "" || $_ !~ /^\s*$/) {
$sect_text[$sn] .= $_;
}
}
}
}
#}}}
# Emit file header
if ($#prologue >= 0) {
print @prologue;
} else {
print <<EOF;
<html>
<head>
<title>
Chrony Frequently Asked Questions
</title>
</head>
<body>
<font face=\"arial,helvetica\" size=+4><b>Table of contents</b></font>
EOF
}
# Emit table of contents
print "<ul>\n";
for $sn (0 .. $#sections) {
print "<b><li> <a href=\"#section_".($sn+1)."\">".($sn+1).".</a> ".$sections[$sn]."</b>\n";
print " <ul>\n";
for $qn (0 .. $#{$questions[$sn]}) {
$sq = ($sn+1).".".($qn+1);
print " <li> <a href=\"#question_".$sq."\">".$sq.".</a> ".$questions[$sn]->[$qn]."\n";
#print " <li> ".$sq.". ".$questions[$sn]->[$qn]."\n";
}
print " </ul>\n";
}
print "</ul>\n";
# Emit main sections
for $sn (0 .. $#sections) {
print "<hr>\n";
print "<a name=section_".($sn+1).">\n";
#print "<b><font size=+2 face=\"arial,helvetica\">".($sn+1).". ".$sections[$sn]."</font></b>\n";
print "<?php pretty_h2(\"".($sn+1).". ".$sections[$sn]."\"); ?>\n";
if ($sect_text[$sn] ne "") {
print "<pre>\n";
print $sect_text[$sn];
print "</pre>\n";
}
for $qn (0 .. $#{$questions[$sn]}) {
$sq = ($sn+1).".".($qn+1);
print "<p>\n";
print "<a name=question_".$sq.">\n";
print "<font size=+1 face=\"arial,helvetica\">".$sq.". ".$questions[$sn]->[$qn]."</font>\n";
print "<pre>\n";
print $answers[$sn]->[$qn];
print "</pre>\n";
}
}
# Print footer
if ($#epilogue >= 0) {
print @epilogue;
} else {
print <<EOF;
</body>
</html>
EOF
}
#{{{ sub guard {
sub guard {
# Hide wierd tags etc
my ($x) = @_;
return $x;
}
#}}}

2927
getdate.c

File diff suppressed because it is too large Load Diff

View File

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

1049
getdate.y

File diff suppressed because it is too large Load Diff

41
hash.h
View File

@@ -1,41 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* 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 crypto hashing.
*/
#ifndef GOT_HASH_H
#define GOT_HASH_H
/* length of hash values produced by SHA512 */
#define MAX_HASH_LENGTH 64
extern int HSH_GetHashId(const char *name);
extern unsigned int HSH_Hash(int id,
const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len);
#endif

View File

@@ -1,89 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* 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 crypto hashing using NSSLOWHASH API of the NSS library.
*/
#include <nss.h>
#include <hasht.h>
#include <nsslowhash.h>
/* #include "config.h" */
#include "hash.h"
static NSSLOWInitContext *ictx;
struct hash {
HASH_HashType type;
const char *name;
NSSLOWHASHContext *context;
};
static struct hash hashes[] = {
{ HASH_AlgMD5, "MD5", NULL },
{ HASH_AlgSHA1, "SHA1", NULL },
{ HASH_AlgSHA256, "SHA256", NULL },
{ HASH_AlgSHA384, "SHA384", NULL },
{ HASH_AlgSHA512, "SHA512", NULL },
{ 0, NULL, NULL }
};
int
HSH_GetHashId(const char *name)
{
int i;
for (i = 0; hashes[i].name; i++) {
if (!strcmp(name, hashes[i].name))
break;
}
if (!hashes[i].name)
return -1; /* not found */
if (!ictx && !(ictx = NSSLOW_Init()))
return -1; /* couldn't init NSS */
if (!hashes[i].context &&
!(hashes[i].context = NSSLOWHASH_NewContext(ictx, hashes[i].type)))
return -1; /* couldn't init hash */
return i;
}
unsigned int
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
unsigned int ret;
NSSLOWHASH_Begin(hashes[id].context);
NSSLOWHASH_Update(hashes[id].context, in1, in1_len);
if (in2)
NSSLOWHASH_Update(hashes[id].context, in2, in2_len);
NSSLOWHASH_End(hashes[id].context, out, &ret, out_len);
return ret;
}

View File

@@ -1,116 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2012
*
* 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 crypto hashing using tomcrypt library.
*/
#include <tomcrypt.h>
#include "config.h"
#include "hash.h"
struct hash {
const char *name;
const char *int_name;
const struct ltc_hash_descriptor *desc;
};
static const struct hash hashes[] = {
{ "MD5", "md5", &md5_desc },
#ifdef LTC_RIPEMD128
{ "RMD128", "rmd128", &rmd128_desc },
#endif
#ifdef LTC_RIPEMD160
{ "RMD160", "rmd160", &rmd160_desc },
#endif
#ifdef LTC_RIPEMD256
{ "RMD256", "rmd256", &rmd256_desc },
#endif
#ifdef LTC_RIPEMD320
{ "RMD320", "rmd320", &rmd320_desc },
#endif
#ifdef LTC_SHA1
{ "SHA1", "sha1", &sha1_desc },
#endif
#ifdef LTC_SHA256
{ "SHA256", "sha256", &sha256_desc },
#endif
#ifdef LTC_SHA384
{ "SHA384", "sha384", &sha384_desc },
#endif
#ifdef LTC_SHA512
{ "SHA512", "sha512", &sha512_desc },
#endif
#ifdef LTC_TIGER
{ "TIGER", "tiger", &tiger_desc },
#endif
#ifdef LTC_WHIRLPOOL
{ "WHIRLPOOL", "whirlpool", &whirlpool_desc },
#endif
{ NULL, NULL, NULL }
};
int
HSH_GetHashId(const char *name)
{
int i, h;
for (i = 0; hashes[i].name; i++) {
if (!strcmp(name, hashes[i].name))
break;
}
if (!hashes[i].name)
return -1; /* not found */
h = find_hash(hashes[i].int_name);
if (h >= 0)
return h; /* already registered */
/* register and try again */
register_hash(hashes[i].desc);
return find_hash(hashes[i].int_name);
}
unsigned int
HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len,
const unsigned char *in2, unsigned int in2_len,
unsigned char *out, unsigned int out_len)
{
unsigned long len;
int r;
len = out_len;
if (in2)
r = hash_memory_multi(id, out, &len,
in1, (unsigned long)in1_len, in2, (unsigned long)in2_len, NULL, 0);
else
r = hash_memory(id, in1, in1_len, out, &len);
if (r != CRYPT_OK)
return 0;
return len;
}

74
io_linux.h Normal file
View File

@@ -0,0 +1,74 @@
/* Taken from <asm-$foo/ioctl.h> in the Linux kernel sources.
* The ioctl.h file is pretty similar from one architecture to another.
* */
#ifndef IO_LINUX_H
#define IO_LINUX_H
/* Hmm. These constants vary a bit between systems. */
/* (__sh__ includes both sh and sh64) */
#if defined(__i386__) || defined(__sh__) || defined(__arm__)||defined(__x86_64__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 14
#define CHRONY_IOC_DIRBITS 2
#define CHRONY_IOC_NONE 0U
#define CHRONY_IOC_WRITE 1U
#define CHRONY_IOC_READ 2U
#elif defined(__alpha__) || defined(__sparc__) || defined(__ppc__) || defined(__ppc64__) || defined(__sparc64__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 13
#define CHRONY_IOC_DIRBITS 2
#define CHRONY_IOC_NONE 1U
#define CHRONY_IOC_READ 2U
#define CHRONY_IOC_WRITE 4U
#elif defined(__mips__) || defined(__mips32__)
#define CHRONY_IOC_NRBITS 8
#define CHRONY_IOC_TYPEBITS 8
#define CHRONY_IOC_SIZEBITS 13
#define CHRONY_IOC_DIRBITS 3
#define CHRONY_IOC_NONE 1U
#define CHRONY_IOC_READ 2U
#define CHRONY_IOC_WRITE 4U
#else
#error "I don't know the values of the _IOC_* constants for your architecture"
#endif
#define CHRONY_IOC_NRMASK ((1 << CHRONY_IOC_NRBITS)-1)
#define CHRONY_IOC_TYPEMASK ((1 << CHRONY_IOC_TYPEBITS)-1)
#define CHRONY_IOC_SIZEMASK ((1 << CHRONY_IOC_SIZEBITS)-1)
#define CHRONY_IOC_DIRMASK ((1 << CHRONY_IOC_DIRBITS)-1)
#define CHRONY_IOC_NRSHIFT 0
#define CHRONY_IOC_TYPESHIFT (CHRONY_IOC_NRSHIFT+CHRONY_IOC_NRBITS)
#define CHRONY_IOC_SIZESHIFT (CHRONY_IOC_TYPESHIFT+CHRONY_IOC_TYPEBITS)
#define CHRONY_IOC_DIRSHIFT (CHRONY_IOC_SIZESHIFT+CHRONY_IOC_SIZEBITS)
#define CHRONY_IOC(dir,type,nr,size) \
(((dir) << CHRONY_IOC_DIRSHIFT) | \
((type) << CHRONY_IOC_TYPESHIFT) | \
((nr) << CHRONY_IOC_NRSHIFT) | \
((size) << CHRONY_IOC_SIZESHIFT))
/* used to create numbers */
#define CHRONY_IO(type,nr) CHRONY_IOC(CHRONY_IOC_NONE,(type),(nr),0)
#define CHRONY_IOR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ,(type),(nr),sizeof(size))
#define CHRONY_IOW(type,nr,size) CHRONY_IOC(CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
#define CHRONY_IOWR(type,nr,size) CHRONY_IOC(CHRONY_IOC_READ|CHRONY_IOC_WRITE,(type),(nr),sizeof(size))
#define RTC_UIE_ON CHRONY_IO('p', 0x03) /* Update int. enable on */
#define RTC_UIE_OFF CHRONY_IO('p', 0x04) /* ... off */
#define RTC_RD_TIME CHRONY_IOR('p', 0x09, struct rtc_time) /* Read RTC time */
#define RTC_SET_TIME CHRONY_IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
/* From mc146818.h */
#define RTC_UIE 0x10 /* update-finished interrupt enable */
#endif

339
keys.c
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/keys.c,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,25 +29,18 @@
*/ */
#include "config.h" #include <stdio.h>
#include <stdlib.h>
#include "sysincl.h" #include <string.h>
#include "keys.h" #include "keys.h"
#include "cmdparse.h"
#include "conf.h" #include "conf.h"
#include "memory.h" #include "memory.h"
#include "util.h"
#include "local.h"
#include "logging.h"
typedef struct { typedef struct {
unsigned long id; unsigned long id;
char *val; char *val;
int len; int len;
int hash_id;
int auth_delay;
} Key; } Key;
#define MAX_KEYS 256 #define MAX_KEYS 256
@@ -53,71 +49,13 @@ static int n_keys;
static Key keys[MAX_KEYS]; static Key keys[MAX_KEYS];
static int command_key_valid; static int command_key_valid;
static int command_key_id; static int command_key_pos;
static int cache_valid; static int cache_valid;
static unsigned long cache_key_id; static unsigned long cache_key_id;
static int cache_key_pos; static int cache_key_pos;
/* ================================================== */ /* ================================================== */
static int
generate_key(unsigned long key_id)
{
#ifdef GENERATE_SHA1_KEY
unsigned char key[20];
const char *hashname = "SHA1";
#else
unsigned char key[16];
const char *hashname = "MD5";
#endif
const char *key_file, *rand_dev = "/dev/urandom";
FILE *f;
struct stat st;
int i;
key_file = CNF_GetKeysFile();
if (!key_file)
return 0;
f = fopen(rand_dev, "r");
if (!f || fread(key, sizeof (key), 1, f) != 1) {
if (f)
fclose(f);
LOG_FATAL(LOGF_Keys, "Could not read %s", rand_dev);
return 0;
}
fclose(f);
f = fopen(key_file, "a");
if (!f) {
LOG_FATAL(LOGF_Keys, "Could not open keyfile %s for writing", key_file);
return 0;
}
/* Make sure the keyfile is not world-readable */
if (stat(key_file, &st) || chmod(key_file, st.st_mode & 0770)) {
fclose(f);
LOG_FATAL(LOGF_Keys, "Could not change permissions of keyfile %s", key_file);
return 0;
}
fprintf(f, "\n%lu %s HEX:", key_id, hashname);
for (i = 0; i < sizeof (key); i++)
fprintf(f, "%02hhX", key[i]);
fprintf(f, "\n");
fclose(f);
/* Erase the key from stack */
memset(key, 0, sizeof (key));
LOG(LOGS_INFO, LOGF_Keys, "Generated key %lu", key_id);
return 1;
}
/* ================================================== */
void void
KEY_Initialise(void) KEY_Initialise(void)
{ {
@@ -125,11 +63,7 @@ KEY_Initialise(void)
command_key_valid = 0; command_key_valid = 0;
cache_valid = 0; cache_valid = 0;
KEY_Reload(); KEY_Reload();
return;
if (CNF_GetGenerateCommandKey() && !KEY_KeyKnown(KEY_GetCommandKey())) {
if (generate_key(KEY_GetCommandKey()))
KEY_Reload();
}
} }
/* ================================================== */ /* ================================================== */
@@ -137,37 +71,8 @@ KEY_Initialise(void)
void void
KEY_Finalise(void) KEY_Finalise(void)
{ {
} /* Nothing to do */
return;
/* ================================================== */
static int
determine_hash_delay(unsigned long key_id)
{
NTP_Packet pkt;
struct timeval before, after;
unsigned long usecs, min_usecs=0;
int i;
for (i = 0; i < 10; i++) {
LCL_ReadRawTime(&before);
KEY_GenerateAuth(key_id, (unsigned char *)&pkt, NTP_NORMAL_PACKET_SIZE,
(unsigned char *)&pkt.auth_data, sizeof (pkt.auth_data));
LCL_ReadRawTime(&after);
usecs = (after.tv_sec - before.tv_sec) * 1000000 + (after.tv_usec - before.tv_usec);
if (i == 0 || usecs < min_usecs) {
min_usecs = usecs;
}
}
/* Add on a bit extra to allow for copying, conversions etc */
min_usecs += min_usecs >> 4;
DEBUG_LOG(LOGF_Keys, "authentication delay for key %lu: %ld useconds", key_id, min_usecs);
return min_usecs;
} }
/* ================================================== */ /* ================================================== */
@@ -192,84 +97,61 @@ compare_keys_by_id(const void *a, const void *b)
/* ================================================== */ /* ================================================== */
#define KEYLEN 2047
#define SKEYLEN "2047"
void void
KEY_Reload(void) KEY_Reload(void)
{ {
int i, line_number; int i, len1;
char *key_file;
FILE *in; FILE *in;
unsigned long key_id; unsigned long key_id;
char line[2048], *keyval, *key_file; char line[KEYLEN+1], keyval[KEYLEN+1];
const char *hashname;
for (i=0; i<n_keys; i++) { for (i=0; i<n_keys; i++) {
Free(keys[i].val); Free(keys[i].val);
} }
n_keys = 0; n_keys = 0;
key_file = CNF_GetKeysFile();
if (key_file) {
in = fopen(key_file, "r");
if (in) {
while (fgets(line, sizeof(line), in)) {
len1 = strlen(line) - 1;
/* Guard against removing last character of the line
* if the last line of the file is missing an end-of-line */
if (line[len1] == '\n') {
line[len1] = '\0';
}
if (sscanf(line, "%lu%" SKEYLEN "s", &key_id, keyval) == 2) {
keys[n_keys].id = key_id;
keys[n_keys].len = strlen(keyval);
keys[n_keys].val = MallocArray(char, 1 + keys[n_keys].len);
strcpy(keys[n_keys].val, keyval);
n_keys++;
}
}
fclose(in);
/* Sort keys into order. Note, if there's a duplicate, it is
arbitrary which one we use later - the user should have been
more careful! */
qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id);
}
}
command_key_valid = 0; command_key_valid = 0;
cache_valid = 0; cache_valid = 0;
key_file = CNF_GetKeysFile(); return;
line_number = 0;
if (!key_file)
return;
in = fopen(key_file, "r");
if (!in) {
LOG(LOGS_WARN, LOGF_Keys, "Could not open keyfile %s", key_file);
return;
}
while (fgets(line, sizeof (line), in)) {
line_number++;
CPS_NormalizeLine(line);
if (!*line)
continue;
if (!CPS_ParseKey(line, &key_id, &hashname, &keyval)) {
LOG(LOGS_WARN, LOGF_Keys, "Could not parse key at line %d in file %s", line_number, key_file);
continue;
}
keys[n_keys].hash_id = HSH_GetHashId(hashname);
if (keys[n_keys].hash_id < 0) {
LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %lu", key_id);
continue;
}
keys[n_keys].len = UTI_DecodePasswordFromText(keyval);
if (!keys[n_keys].len) {
LOG(LOGS_WARN, LOGF_Keys, "Could not decode password in key %lu", key_id);
continue;
}
keys[n_keys].id = key_id;
keys[n_keys].val = MallocArray(char, keys[n_keys].len);
memcpy(keys[n_keys].val, keyval, keys[n_keys].len);
n_keys++;
}
fclose(in);
/* Sort keys into order. Note, if there's a duplicate, it is
arbitrary which one we use later - the user should have been
more careful! */
qsort((void *) keys, n_keys, sizeof(Key), compare_keys_by_id);
/* Check for duplicates */
for (i = 1; i < n_keys; i++) {
if (keys[i - 1].id == keys[i].id) {
LOG(LOGS_WARN, LOGF_Keys, "Detected duplicate key %lu", keys[i].id);
}
}
/* Erase any passwords from stack */
memset(line, 0, sizeof (line));
for (i=0; i<n_keys; i++) {
keys[i].auth_delay = determine_hash_delay(keys[i].id);
}
} }
/* ================================================== */ /* ================================================== */
@@ -292,35 +174,46 @@ lookup_key(unsigned long id)
/* ================================================== */ /* ================================================== */
static int void
get_key_pos(unsigned long key_id) KEY_CommandKey(char **key, int *len)
{ {
int position; unsigned long command_key_id;
if (cache_valid && key_id == cache_key_id) if (!command_key_valid) {
return cache_key_pos; command_key_id = CNF_GetCommandKey();
command_key_pos = lookup_key(command_key_id);
position = lookup_key(key_id); command_key_valid = 1;
if (position >= 0) {
cache_valid = 1;
cache_key_pos = position;
cache_key_id = key_id;
} }
return position; if (command_key_pos >= 0) {
*key = keys[command_key_pos].val;
*len = keys[command_key_pos].len;
} else {
*key = "";
*len = 0;
}
} }
/* ================================================== */ /* ================================================== */
unsigned long int
KEY_GetCommandKey(void) KEY_GetKey(unsigned long key_id, char **key, int *len)
{ {
if (!command_key_valid) { if (!cache_valid || key_id != cache_key_id) {
command_key_id = CNF_GetCommandKey(); cache_valid = 1;
cache_key_pos = lookup_key(key_id);
cache_key_id = key_id;
} }
return command_key_id; if (cache_key_pos >= 0) {
*key = keys[cache_key_pos].val;
*len = keys[cache_key_pos].len;
return 1;
} else {
*key = "";
*len = 0;
return 0;
}
} }
/* ================================================== */ /* ================================================== */
@@ -328,59 +221,23 @@ KEY_GetCommandKey(void)
int int
KEY_KeyKnown(unsigned long key_id) KEY_KeyKnown(unsigned long key_id)
{ {
return get_key_pos(key_id) >= 0; int position;
}
/* ================================================== */ if (cache_valid && (key_id == cache_key_id)) {
return 1;
} else {
int position = lookup_key(key_id);
KEY_GetAuthDelay(unsigned long key_id)
{
int key_pos;
key_pos = get_key_pos(key_id); if (position >= 0) {
/* Store key in cache, we will probably be using it in a
if (key_pos < 0) { minute... */
return 0; cache_valid = 1;
cache_key_pos = position;
cache_key_id = key_id;
return 1;
} else {
return 0;
}
} }
return keys[key_pos].auth_delay;
}
/* ================================================== */
int
KEY_GenerateAuth(unsigned long key_id, const unsigned char *data, int data_len,
unsigned char *auth, int auth_len)
{
int key_pos;
key_pos = get_key_pos(key_id);
if (key_pos < 0) {
return 0;
}
return UTI_GenerateNTPAuth(keys[key_pos].hash_id,
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
data, data_len, auth, auth_len);
}
/* ================================================== */
int
KEY_CheckAuth(unsigned long key_id, const unsigned char *data, int data_len,
const unsigned char *auth, int auth_len)
{
int key_pos;
key_pos = get_key_pos(key_id);
if (key_pos < 0) {
return 0;
}
return UTI_CheckNTPAuth(keys[key_pos].hash_id,
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
data, data_len, auth, auth_len);
} }

14
keys.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/keys.h,v 1.8 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -32,15 +36,9 @@ extern void KEY_Finalise(void);
extern void KEY_Reload(void); extern void KEY_Reload(void);
extern unsigned long KEY_GetCommandKey(void); extern void KEY_CommandKey(char **key, int *len);
extern int KEY_GetKey(unsigned long key_id, char **key, int *len); extern int KEY_GetKey(unsigned long key_id, char **key, int *len);
extern int KEY_KeyKnown(unsigned long key_id); extern int KEY_KeyKnown(unsigned long key_id);
extern int KEY_GetAuthDelay(unsigned long key_id);
extern int KEY_GenerateAuth(unsigned long key_id, const unsigned char *data,
int data_len, unsigned char *auth, int auth_len);
extern int KEY_CheckAuth(unsigned long key_id, const unsigned char *data,
int data_len, const unsigned char *auth, int auth_len);
#endif /* GOT_KEYS_H */ #endif /* GOT_KEYS_H */

321
local.c
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/local.c,v 1.21 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011, 2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,11 +31,9 @@
They interface with the system specific driver files in sys_*.c They interface with the system specific driver files in sys_*.c
*/ */
#include "config.h" #include <assert.h>
#include <stddef.h>
#include "sysincl.h"
#include "conf.h"
#include "local.h" #include "local.h"
#include "localp.h" #include "localp.h"
#include "memory.h" #include "memory.h"
@@ -44,9 +45,6 @@
/* Variable to store the current frequency, in ppm */ /* Variable to store the current frequency, in ppm */
static double current_freq_ppm; static double current_freq_ppm;
/* Temperature compensation, in ppm */
static double temp_comp_ppm;
/* ================================================== */ /* ================================================== */
/* Store the system dependent drivers */ /* Store the system dependent drivers */
@@ -55,7 +53,7 @@ static lcl_SetFrequencyDriver drv_set_freq;
static lcl_AccrueOffsetDriver drv_accrue_offset; static lcl_AccrueOffsetDriver drv_accrue_offset;
static lcl_ApplyStepOffsetDriver drv_apply_step_offset; static lcl_ApplyStepOffsetDriver drv_apply_step_offset;
static lcl_OffsetCorrectionDriver drv_offset_convert; static lcl_OffsetCorrectionDriver drv_offset_convert;
static lcl_SetLeapDriver drv_set_leap; static lcl_ImmediateStepDriver drv_immediate_step;
/* ================================================== */ /* ================================================== */
@@ -90,8 +88,6 @@ static DispersionNotifyListEntry dispersion_notify_list;
static int precision_log; static int precision_log;
static double precision_quantum; static double precision_quantum;
static double max_clock_error;
/* ================================================== */ /* ================================================== */
/* Define the number of increments of the system clock that we want /* Define the number of increments of the system clock that we want
@@ -104,15 +100,17 @@ static double max_clock_error;
static void static void
calculate_sys_precision(void) calculate_sys_precision(void)
{ {
struct timeval tv, old_tv; struct timeval tv, old_tv, first_tv;
struct timezone tz;
int dusec, best_dusec; int dusec, best_dusec;
int iters; int iters;
gettimeofday(&old_tv, NULL); gettimeofday(&old_tv, &tz);
first_tv = old_tv;
best_dusec = 1000000; /* Assume we must be better than a second */ best_dusec = 1000000; /* Assume we must be better than a second */
iters = 0; iters = 0;
do { do {
gettimeofday(&tv, NULL); gettimeofday(&tv, &tz);
dusec = 1000000*(tv.tv_sec - old_tv.tv_sec) + (tv.tv_usec - old_tv.tv_usec); dusec = 1000000*(tv.tv_sec - old_tv.tv_sec) + (tv.tv_usec - old_tv.tv_usec);
old_tv = tv; old_tv = tv;
if (dusec > 0) { if (dusec > 0) {
@@ -122,19 +120,18 @@ calculate_sys_precision(void)
iters++; iters++;
} }
} while (iters < NITERS); } while (iters < NITERS);
if (!(best_dusec > 0)) {
assert(best_dusec > 0); CROAK("best_dusec should be positive");
}
precision_quantum = best_dusec * 1.0e-6;
/* Get rounded log2 value of the measured precision */
precision_log = 0; precision_log = 0;
while (best_dusec < 707107) { while (best_dusec < 500000) {
precision_log--; precision_log--;
best_dusec *= 2; best_dusec *= 2;
} }
DEBUG_LOG(LOGF_Local, "Clock precision %.9f (%d)", precision_quantum, precision_log); precision_quantum = 1.0 / (double)(1<<(-precision_log));
return;
} }
/* ================================================== */ /* ================================================== */
@@ -156,11 +153,8 @@ LCL_Initialise(void)
/* This ought to be set from the system driver layer */ /* This ought to be set from the system driver layer */
current_freq_ppm = 0.0; current_freq_ppm = 0.0;
temp_comp_ppm = 0.0;
calculate_sys_precision(); calculate_sys_precision();
max_clock_error = CNF_GetMaxClockError() * 1e-6;
} }
/* ================================================== */ /* ================================================== */
@@ -168,6 +162,7 @@ LCL_Initialise(void)
void void
LCL_Finalise(void) LCL_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -190,14 +185,6 @@ LCL_GetSysPrecisionAsQuantum(void)
/* ================================================== */ /* ================================================== */
double
LCL_GetMaxClockError(void)
{
return max_clock_error;
}
/* ================================================== */
void void
LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything) LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
{ {
@@ -206,7 +193,7 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
/* Check that the handler is not already registered */ /* Check that the handler is not already registered */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) { for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
if (!(ptr->handler != handler || ptr->anything != anything)) { if (!(ptr->handler != handler || ptr->anything != anything)) {
assert(0); CROAK("a handler is already registered");
} }
} }
@@ -220,11 +207,14 @@ LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything
new_entry->prev = change_list.prev; new_entry->prev = change_list.prev;
change_list.prev->next = new_entry; change_list.prev->next = new_entry;
change_list.prev = new_entry; change_list.prev = new_entry;
return;
} }
/* ================================================== */ /* ================================================== */
/* Remove a handler */ /* Remove a handler */
extern
void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything) void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything)
{ {
@@ -241,35 +231,17 @@ void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler handler, void *
} }
} }
assert(ok); if (!ok) {
CROAK("did not find a matching handler");
}
/* Unlink entry from the list */ /* Unlink entry from the list */
ptr->next->prev = ptr->prev; ptr->next->prev = ptr->prev;
ptr->prev->next = ptr->next; ptr->prev->next = ptr->next;
free(ptr); free(ptr);
}
/* ================================================== */ return;
int
LCL_IsFirstParameterChangeHandler(LCL_ParameterChangeHandler handler)
{
return change_list.next->handler == handler;
}
/* ================================================== */
static void
invoke_parameter_change_handlers(struct timeval *raw, struct timeval *cooked,
double dfreq, double doffset,
LCL_ChangeType change_type)
{
ChangeListEntry *ptr;
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(raw, cooked, dfreq, doffset, change_type, ptr->anything);
}
} }
/* ================================================== */ /* ================================================== */
@@ -282,7 +254,7 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
/* Check that the handler is not already registered */ /* Check that the handler is not already registered */
for (ptr = dispersion_notify_list.next; ptr != &dispersion_notify_list; ptr = ptr->next) { for (ptr = dispersion_notify_list.next; ptr != &dispersion_notify_list; ptr = ptr->next) {
if (!(ptr->handler != handler || ptr->anything != anything)) { if (!(ptr->handler != handler || ptr->anything != anything)) {
assert(0); CROAK("a handler is already registered");
} }
} }
@@ -296,6 +268,8 @@ LCL_AddDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void *anythi
new_entry->prev = dispersion_notify_list.prev; new_entry->prev = dispersion_notify_list.prev;
dispersion_notify_list.prev->next = new_entry; dispersion_notify_list.prev->next = new_entry;
dispersion_notify_list.prev = new_entry; dispersion_notify_list.prev = new_entry;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -318,13 +292,17 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
} }
} }
assert(ok); if (!ok) {
CROAK("no matching handler found");
}
/* Unlink entry from the list */ /* Unlink entry from the list */
ptr->next->prev = ptr->prev; ptr->next->prev = ptr->prev;
ptr->prev->next = ptr->next; ptr->prev->next = ptr->next;
free(ptr); free(ptr);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -334,9 +312,13 @@ void LCL_RemoveDispersionNotifyHandler(LCL_DispersionNotifyHandler handler, void
void void
LCL_ReadRawTime(struct timeval *result) LCL_ReadRawTime(struct timeval *result)
{ {
if (gettimeofday(result, NULL) < 0) { struct timezone tz;
LOG_FATAL(LOGF_Local, "gettimeofday() failed");
if (!(gettimeofday(result, &tz) >= 0)) {
CROAK("Could not get time of day");
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -345,47 +327,39 @@ void
LCL_ReadCookedTime(struct timeval *result, double *err) LCL_ReadCookedTime(struct timeval *result, double *err)
{ {
struct timeval raw; struct timeval raw;
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, result, err);
}
/* ================================================== */
void
LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err)
{
double correction; double correction;
LCL_GetOffsetCorrection(raw, &correction, err); LCL_ReadRawTime(&raw);
UTI_AddDoubleToTimeval(raw, correction, cooked);
}
/* ================================================== */ /* For now, cheat and set the error to zero in all cases.
*/
*err = 0.0;
void
LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err)
{
/* Call system specific driver to get correction */ /* Call system specific driver to get correction */
(*drv_offset_convert)(raw, correction, err); (*drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, result);
return;
} }
/* ================================================== */ /* ================================================== */
/* Return current frequency */
double
LCL_GetOffsetCorrection(struct timeval *raw)
{
double correction;
(*drv_offset_convert)(raw, &correction);
return correction;
}
/* ================================================== */
/* This is just a simple passthrough of the system specific routine */
double double
LCL_ReadAbsoluteFrequency(void) LCL_ReadAbsoluteFrequency(void)
{ {
double freq; return (*drv_read_freq)();
freq = current_freq_ppm;
/* Undo temperature compensation */
if (temp_comp_ppm != 0.0) {
freq = (freq + temp_comp_ppm) / (1.0 - 1.0e-6 * temp_comp_ppm);
}
return freq;
} }
/* ================================================== */ /* ================================================== */
@@ -395,25 +369,25 @@ LCL_ReadAbsoluteFrequency(void)
void void
LCL_SetAbsoluteFrequency(double afreq_ppm) LCL_SetAbsoluteFrequency(double afreq_ppm)
{ {
ChangeListEntry *ptr;
struct timeval raw, cooked; struct timeval raw, cooked;
double correction;
double dfreq; double dfreq;
/* Apply temperature compensation */
if (temp_comp_ppm != 0.0) {
afreq_ppm = afreq_ppm * (1.0 - 1.0e-6 * temp_comp_ppm) - temp_comp_ppm;
}
/* Call the system-specific driver for setting the frequency */ /* Call the system-specific driver for setting the frequency */
afreq_ppm = (*drv_set_freq)(afreq_ppm); (*drv_set_freq)(afreq_ppm);
dfreq = (afreq_ppm - current_freq_ppm) / (1.0e6 - current_freq_ppm); dfreq = 1.0e-6 * (afreq_ppm - current_freq_ppm) / (1.0 - 1.0e-6 * current_freq_ppm);
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL); (drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
/* Dispatch to all handlers */ /* Dispatch to all handlers */
invoke_parameter_change_handlers(&raw, &cooked, dfreq, 0.0, LCL_ChangeAdjust); for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, afreq_ppm, 0.0, 0, ptr->anything);
}
current_freq_ppm = afreq_ppm; current_freq_ppm = afreq_ppm;
@@ -424,45 +398,54 @@ LCL_SetAbsoluteFrequency(double afreq_ppm)
void void
LCL_AccumulateDeltaFrequency(double dfreq) LCL_AccumulateDeltaFrequency(double dfreq)
{ {
ChangeListEntry *ptr;
struct timeval raw, cooked; struct timeval raw, cooked;
double old_freq_ppm; double correction;
old_freq_ppm = current_freq_ppm;
/* Work out new absolute frequency. Note that absolute frequencies /* Work out new absolute frequency. Note that absolute frequencies
are handled in units of ppm, whereas the 'dfreq' argument is in are handled in units of ppm, whereas the 'dfreq' argument is in
terms of the gradient of the (offset) v (local time) function. */ terms of the gradient of the (offset) v (local time) function. */
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm); current_freq_ppm = (1.0 - dfreq) * current_freq_ppm +
(1.0e6 * dfreq);
/* Call the system-specific driver for setting the frequency */ /* Call the system-specific driver for setting the frequency */
current_freq_ppm = (*drv_set_freq)(current_freq_ppm); (*drv_set_freq)(current_freq_ppm);
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm);
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL); (drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
/* Dispatch to all handlers */ /* Dispatch to all handlers */
invoke_parameter_change_handlers(&raw, &cooked, dfreq, 0.0, LCL_ChangeAdjust); for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, 0.0, 0, ptr->anything);
}
} }
/* ================================================== */ /* ================================================== */
void void
LCL_AccumulateOffset(double offset, double corr_rate) LCL_AccumulateOffset(double offset)
{ {
ChangeListEntry *ptr;
struct timeval raw, cooked; struct timeval raw, cooked;
double correction;
/* In this case, the cooked time to be passed to the notify clients /* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */ has to be the cooked time BEFORE the change was made */
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL); (drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
(*drv_accrue_offset)(offset, corr_rate); (*drv_accrue_offset)(offset);
/* Dispatch to all handlers */ /* Dispatch to all handlers */
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeAdjust); for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 0, ptr->anything);
}
} }
/* ================================================== */ /* ================================================== */
@@ -470,63 +453,65 @@ LCL_AccumulateOffset(double offset, double corr_rate)
void void
LCL_ApplyStepOffset(double offset) LCL_ApplyStepOffset(double offset)
{ {
ChangeListEntry *ptr;
struct timeval raw, cooked; struct timeval raw, cooked;
double correction;
/* In this case, the cooked time to be passed to the notify clients /* In this case, the cooked time to be passed to the notify clients
has to be the cooked time BEFORE the change was made */ has to be the cooked time BEFORE the change was made */
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL); (drv_offset_convert)(&raw, &correction);
UTI_AddDoubleToTimeval(&raw, correction, &cooked);
(*drv_apply_step_offset)(offset); (*drv_apply_step_offset)(offset);
/* Dispatch to all handlers */ /* Dispatch to all handlers */
invoke_parameter_change_handlers(&raw, &cooked, 0.0, offset, LCL_ChangeStep); for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, 0.0, current_freq_ppm, offset, 1, ptr->anything);
}
} }
/* ================================================== */ /* ================================================== */
void void
LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked, LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
double offset, double dispersion)
{
/* Dispatch to all handlers */
invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeUnknownStep);
lcl_InvokeDispersionNotifyHandlers(dispersion);
}
/* ================================================== */
void
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
{ {
ChangeListEntry *ptr;
struct timeval raw, cooked; struct timeval raw, cooked;
double correction;
double old_freq_ppm; double old_freq_ppm;
LCL_ReadRawTime(&raw); LCL_ReadRawTime(&raw);
(drv_offset_convert)(&raw, &correction);
/* Due to modifying the offset, this has to be the cooked time prior /* Due to modifying the offset, this has to be the cooked time prior
to the change we are about to make */ to the change we are about to make */
LCL_CookTime(&raw, &cooked, NULL); UTI_AddDoubleToTimeval(&raw, correction, &cooked);
old_freq_ppm = current_freq_ppm; old_freq_ppm = current_freq_ppm;
/* Work out new absolute frequency. Note that absolute frequencies /* Work out new absolute frequency. Note that absolute frequencies
are handled in units of ppm, whereas the 'dfreq' argument is in are handled in units of ppm, whereas the 'dfreq' argument is in
terms of the gradient of the (offset) v (local time) function. */ terms of the gradient of the (offset) v (local time) function. */
current_freq_ppm += dfreq * (1.0e6 - current_freq_ppm); current_freq_ppm = (1.0 - dfreq) * old_freq_ppm +
(1.0e6 * dfreq);
DEBUG_LOG(LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec", #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Local, "old_freq=%.3fppm new_freq=%.3fppm offset=%.6fsec",
old_freq_ppm, current_freq_ppm, doffset); old_freq_ppm, current_freq_ppm, doffset);
#endif
/* Call the system-specific driver for setting the frequency */ /* Call the system-specific driver for setting the frequency */
current_freq_ppm = (*drv_set_freq)(current_freq_ppm); (*drv_set_freq)(current_freq_ppm);
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 - old_freq_ppm); (*drv_accrue_offset)(doffset);
(*drv_accrue_offset)(doffset, corr_rate);
/* Dispatch to all handlers */ /* Dispatch to all handlers */
invoke_parameter_change_handlers(&raw, &cooked, dfreq, doffset, LCL_ChangeAdjust); for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
(ptr->handler)(&raw, &cooked, dfreq, current_freq_ppm, doffset, 0, ptr->anything);
}
} }
/* ================================================== */ /* ================================================== */
@@ -550,18 +535,22 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset, lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset, lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert, lcl_OffsetCorrectionDriver offset_convert,
lcl_SetLeapDriver set_leap) lcl_ImmediateStepDriver immediate_step)
{ {
drv_read_freq = read_freq; drv_read_freq = read_freq;
drv_set_freq = set_freq; drv_set_freq = set_freq;
drv_accrue_offset = accrue_offset; drv_accrue_offset = accrue_offset;
drv_apply_step_offset = apply_step_offset; drv_apply_step_offset = apply_step_offset;
drv_offset_convert = offset_convert; drv_offset_convert = offset_convert;
drv_set_leap = set_leap; drv_immediate_step = immediate_step;
current_freq_ppm = (*drv_read_freq)(); current_freq_ppm = (*drv_read_freq)();
DEBUG_LOG(LOGF_Local, "Local freq=%.3fppm", current_freq_ppm); #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Local, "Local freq=%.3fppm", current_freq_ppm);
#endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -571,57 +560,15 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
int int
LCL_MakeStep(void) LCL_MakeStep(void)
{ {
struct timeval raw; if (drv_immediate_step) {
double correction; (drv_immediate_step)();
#ifdef TRACEON
LCL_ReadRawTime(&raw); LOG(LOGS_INFO, LOGF_Local, "Made step to system time to apply remaining slew");
LCL_GetOffsetCorrection(&raw, &correction, NULL); #endif
return 1;
/* Cancel remaining slew and make the step */
LCL_AccumulateOffset(correction, 0.0);
LCL_ApplyStepOffset(-correction);
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.6f seconds", correction);
return 1;
}
/* ================================================== */
void
LCL_SetLeap(int leap)
{
if (drv_set_leap) {
(drv_set_leap)(leap);
} }
}
return 0;
/* ================================================== */
double
LCL_SetTempComp(double comp)
{
double uncomp_freq_ppm;
if (temp_comp_ppm == comp)
return comp;
/* Undo previous compensation */
current_freq_ppm = (current_freq_ppm + temp_comp_ppm) /
(1.0 - 1.0e-6 * temp_comp_ppm);
uncomp_freq_ppm = current_freq_ppm;
/* Apply new compensation */
current_freq_ppm = current_freq_ppm * (1.0 - 1.0e-6 * comp) - comp;
/* Call the system-specific driver for setting the frequency */
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
temp_comp_ppm = (uncomp_freq_ppm - current_freq_ppm) /
(1.0e-6 * uncomp_freq_ppm + 1.0);
return temp_comp_ppm;
} }
/* ================================================== */ /* ================================================== */

63
local.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/local.h,v 1.16 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -46,13 +50,11 @@ extern void LCL_ReadRawTime(struct timeval *);
extern void LCL_ReadCookedTime(struct timeval *t, double *err); extern void LCL_ReadCookedTime(struct timeval *t, double *err);
/* Convert raw time to cooked. */
extern void LCL_CookTime(struct timeval *raw, struct timeval *cooked, double *err);
/* Read the current offset between the system clock and true time /* Read the current offset between the system clock and true time
(i.e. 'cooked' - 'raw') (in seconds). */ (i.e. 'cooked' - 'raw') (in seconds). Only intended for use in
status reporting, really. */
extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err); extern double LCL_GetOffsetCorrection(struct timeval *raw);
/* Type of routines that may be invoked as callbacks when there is a /* Type of routines that may be invoked as callbacks when there is a
change to the frequency or offset. change to the frequency or offset.
@@ -64,25 +66,23 @@ extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, dou
dfreq : delta frequency relative to previous value (in terms of dfreq : delta frequency relative to previous value (in terms of
seconds gained by system clock per unit system clock time) seconds gained by system clock per unit system clock time)
afreq : absolute frequency relative to uncompensated system (in
terms of ppm seconds gained by system clock per unit of the
uncalibrated system clock)
doffset : delta offset applied (positive => make local system fast doffset : delta offset applied (positive => make local system fast
by that amount, negative => make it slow by that amount) by that amount, negative => make it slow by that amount)
change_type : what type of change is being applied is_step_change : true if change is being applied as a jump (using
settimeofday rather than adjtime)
anything : Passthrough argument from call to registration routine */ anything : Passthrough argument from call to registration routine */
typedef enum {
LCL_ChangeAdjust,
LCL_ChangeStep,
LCL_ChangeUnknownStep
} LCL_ChangeType;
typedef void (*LCL_ParameterChangeHandler) typedef void (*LCL_ParameterChangeHandler)
(struct timeval *raw, struct timeval *cooked, (struct timeval *raw, struct timeval *cooked,
double dfreq, double dfreq, double afreq_ppm,
double doffset, double doffset, int is_step_change,
LCL_ChangeType change_type,
void *anything void *anything
); );
@@ -92,9 +92,6 @@ extern void LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, vo
/* Remove a handler */ /* Remove a handler */
extern void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler, void *anything); extern void LCL_RemoveParameterChangeHandler(LCL_ParameterChangeHandler, void *anything);
/* Check if a handler is invoked first when dispatching */
extern int LCL_IsFirstParameterChangeHandler(LCL_ParameterChangeHandler handler);
/* Function type for handlers to be called back when an indeterminate /* Function type for handlers to be called back when an indeterminate
offset is introduced into the local time. This situation occurs offset is introduced into the local time. This situation occurs
when the frequency must be adjusted to effect a clock slew and when the frequency must be adjusted to effect a clock slew and
@@ -147,10 +144,9 @@ extern void LCL_AccumulateDeltaFrequency(double dfreq);
/* Routine to apply an offset (in seconds) to the local clock. The /* Routine to apply an offset (in seconds) to the local clock. The
argument should be positive to move the clock backwards (i.e. the argument should be positive to move the clock backwards (i.e. the
local clock is currently fast of true time), or negative to move it local clock is currently fast of true time), or negative to move it
forwards (i.e. it is currently slow of true time). Provided is also forwards (i.e. it is currently slow of true time). */
a suggested correction rate (correction time * offset). */
extern void LCL_AccumulateOffset(double offset, double corr_rate); extern void LCL_AccumulateOffset(double offset);
/* Routine to apply an immediate offset by doing a sudden step if /* Routine to apply an immediate offset by doing a sudden step if
possible. (Intended for use after an initial estimate of offset has possible. (Intended for use after an initial estimate of offset has
@@ -161,14 +157,9 @@ extern void LCL_AccumulateOffset(double offset, double corr_rate);
extern void LCL_ApplyStepOffset(double offset); extern void LCL_ApplyStepOffset(double offset);
/* Routine to invoke notify handlers on an unexpected time jump
in system clock */
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
double offset, double dispersion);
/* Perform the combination of modifying the frequency and applying /* Perform the combination of modifying the frequency and applying
a slew, in one easy step */ a slew, in one easy step */
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate); extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
/* Routine to read the system precision as a log to base 2 value. */ /* Routine to read the system precision as a log to base 2 value. */
extern int LCL_GetSysPrecisionAsLog(void); extern int LCL_GetSysPrecisionAsLog(void);
@@ -176,10 +167,6 @@ extern int LCL_GetSysPrecisionAsLog(void);
/* Routine to read the system precision in terms of the actual time step */ /* Routine to read the system precision in terms of the actual time step */
extern double LCL_GetSysPrecisionAsQuantum(void); extern double LCL_GetSysPrecisionAsQuantum(void);
/* Routine to read the maximum frequency error of the local clock. This
is a frequency stability, not an absolute error. */
extern double LCL_GetMaxClockError(void);
/* Routine to initialise the module (to be called once at program /* Routine to initialise the module (to be called once at program
start-up) */ start-up) */
@@ -194,16 +181,4 @@ extern void LCL_Finalise(void);
to a timezone problem. */ to a timezone problem. */
extern int LCL_MakeStep(void); extern int LCL_MakeStep(void);
/* Routine to schedule a leap second. Leap second will be inserted
at the end of the day if argument is positive, deleted if negative,
and zero cancels scheduled leap second. */
extern void LCL_SetLeap(int leap);
/* Routine to set a frequency correction (in ppm) that should be applied
to local clock to compensate for temperature changes. A positive
argument means that the clock frequency should be increased. Return the
actual compensation (may be different from the requested compensation
due to clamping or rounding). */
extern double LCL_SetTempComp(double comp);
#endif /* GOT_LOCAL_H */ #endif /* GOT_LOCAL_H */

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/localp.h,v 1.9 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -36,14 +40,12 @@ typedef double (*lcl_ReadFrequencyDriver)(void);
/* System driver to set the current local frequency, in ppm relative /* System driver to set the current local frequency, in ppm relative
to nominal. A positive value indicates that the local clock runs to nominal. A positive value indicates that the local clock runs
fast when uncompensated. Return actual frequency (may be different fast when uncompensated. */
from the requested frequency due to clamping or rounding). */ typedef void (*lcl_SetFrequencyDriver)(double freq_ppm);
typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
/* System driver to accrue an offset. A positive argument means slew /* System driver to accrue an offset. A positive argument means slew
the clock forwards. The suggested correction rate of time to correct the the clock forwards. */
offset is given in 'corr_rate'. */ typedef void (*lcl_AccrueOffsetDriver)(double offset);
typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
/* System driver to apply a step offset. A positive argument means step /* System driver to apply a step offset. A positive argument means step
the clock forwards. */ the clock forwards. */
@@ -52,10 +54,11 @@ typedef void (*lcl_ApplyStepOffsetDriver)(double offset);
/* System driver to convert a raw time to an adjusted (cooked) time. /* System driver to convert a raw time to an adjusted (cooked) time.
The number of seconds returned in 'corr' have to be added to the The number of seconds returned in 'corr' have to be added to the
raw time to get the corrected time */ raw time to get the corrected time */
typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr, double *err); typedef void (*lcl_OffsetCorrectionDriver)(struct timeval *raw, double *corr);
/* System driver to schedule leap second */ /* System driver to stop slewing the current offset and to apply is
typedef void (*lcl_SetLeapDriver)(int leap); as an immediate step instead */
typedef void (*lcl_ImmediateStepDriver)(void);
extern void lcl_InvokeDispersionNotifyHandlers(double dispersion); extern void lcl_InvokeDispersionNotifyHandlers(double dispersion);
@@ -65,6 +68,6 @@ lcl_RegisterSystemDrivers(lcl_ReadFrequencyDriver read_freq,
lcl_AccrueOffsetDriver accrue_offset, lcl_AccrueOffsetDriver accrue_offset,
lcl_ApplyStepOffsetDriver apply_step_offset, lcl_ApplyStepOffsetDriver apply_step_offset,
lcl_OffsetCorrectionDriver offset_convert, lcl_OffsetCorrectionDriver offset_convert,
lcl_SetLeapDriver set_leap); lcl_ImmediateStepDriver immediate_step_driver);
#endif /* GOT_LOCALP_H */ #endif /* GOT_LOCALP_H */

362
logging.c
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/logging.c,v 1.15 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -25,48 +28,24 @@
Module to handle logging of diagnostic information Module to handle logging of diagnostic information
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "conf.h" #include "main.h"
#include "logging.h" #include "logging.h"
#include "mkdirpp.h" #include "version.h"
#include "util.h"
/* This is used by DEBUG_LOG macro */
int log_debug_enabled = 0;
/* ================================================== */ /* ================================================== */
/* Flag indicating we have initialised */ /* Flag indicating we have initialised */
static int initialised = 0; static int initialised = 0;
static int system_log = 0; static int is_detached = 0;
static int parent_fd = 0; static time_t last_limited = 0;
#define DEBUG_LEVEL_PRINT_FUNCTION 2
#define DEBUG_LEVEL_PRINT_DEBUG 2
static int debug_level = 0;
#ifdef WINNT #ifdef WINNT
static FILE *logfile; static FILE *logfile;
#endif #endif
struct LogFile {
const char *name;
const char *banner;
FILE *file;
unsigned long writes;
};
static int n_filelogs = 0;
/* Increase this when adding a new logfile */
#define MAX_FILELOGS 6
static struct LogFile logfiles[MAX_FILELOGS];
/* ================================================== */ /* ================================================== */
/* Init function */ /* Init function */
@@ -78,6 +57,8 @@ LOG_Initialise(void)
#ifdef WINNT #ifdef WINNT
logfile = fopen("./chronyd.err", "a"); logfile = fopen("./chronyd.err", "a");
#endif #endif
return;
} }
/* ================================================== */ /* ================================================== */
@@ -91,242 +72,163 @@ LOG_Finalise(void)
fclose(logfile); fclose(logfile);
} }
#else #else
if (system_log) { if (is_detached) {
closelog(); closelog();
} }
#endif #endif
LOG_CycleLogFiles();
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
static void log_message(int fatal, LOG_Severity severity, const char *message) void
{ LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *format, ...)
#ifdef WINNT
if (logfile) {
fprintf(logfile, fatal ? "Fatal error : %s\n" : "%s\n", message);
}
#else
if (system_log) {
int priority;
switch (severity) {
case LOGS_DEBUG:
priority = LOG_DEBUG;
break;
case LOGS_INFO:
priority = LOG_INFO;
break;
case LOGS_WARN:
priority = LOG_WARNING;
break;
case LOGS_ERR:
priority = LOG_ERR;
break;
case LOGS_FATAL:
priority = LOG_CRIT;
break;
default:
assert(0);
}
syslog(priority, fatal ? "Fatal error : %s" : "%s", message);
} else {
fprintf(stderr, fatal ? "Fatal error : %s\n" : "%s\n", message);
}
#endif
}
/* ================================================== */
void LOG_Message(LOG_Severity severity, LOG_Facility facility,
int line_number, const char *filename,
const char *function_name, const char *format, ...)
{ {
char buf[2048]; char buf[2048];
va_list other_args; va_list other_args;
time_t t; va_start(other_args, format);
struct tm stm; vsnprintf(buf, sizeof(buf), format, other_args);
va_end(other_args);
#ifdef WINNT #ifdef WINNT
if (logfile) {
fprintf(logfile, "%s\n", buf);
}
#else #else
if (!system_log) { if (is_detached) {
/* Don't clutter up syslog with timestamps and internal debugging info */ switch (severity) {
time(&t); case LOGS_INFO:
stm = *gmtime(&t); syslog(LOG_INFO, "%s", buf);
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &stm); break;
fprintf(stderr, "%s ", buf); case LOGS_WARN:
if (debug_level >= DEBUG_LEVEL_PRINT_FUNCTION) syslog(LOG_WARNING, "%s", buf);
fprintf(stderr, "%s:%d:(%s) ", filename, line_number, function_name); break;
case LOGS_ERR:
default:
syslog(LOG_ERR, "%s", buf);
break;
}
} else {
fprintf(stderr, "%s\n", buf);
} }
#endif #endif
return;
}
/* ================================================== */
void
LOG_Fatal_Function(LOG_Facility facility, const char *format, ...)
{
char buf[2048];
va_list other_args;
va_start(other_args, format); va_start(other_args, format);
vsnprintf(buf, sizeof(buf), format, other_args); vsnprintf(buf, sizeof(buf), format, other_args);
va_end(other_args); va_end(other_args);
switch (severity) { #ifdef WINNT
case LOGS_DEBUG: if (logfile) {
case LOGS_INFO: fprintf(logfile, "Fatal error : %s\n", buf);
case LOGS_WARN:
case LOGS_ERR:
log_message(0, severity, buf);
break;
case LOGS_FATAL:
log_message(1, severity, buf);
/* With syslog, send the message also to the grandparent
process or write it to stderr if not detached */
if (system_log) {
if (parent_fd > 0) {
if (write(parent_fd, buf, strlen(buf) + 1) < 0)
; /* Not much we can do here */
} else if (parent_fd == 0) {
system_log = 0;
log_message(1, severity, buf);
}
}
break;
default:
assert(0);
} }
#else
if (is_detached) {
syslog(LOG_CRIT, "Fatal error : %s", buf);
} else {
fprintf(stderr, "Fatal error : %s\n", buf);
}
#endif
MAI_CleanupAndExit();
return;
} }
/* ================================================== */ /* ================================================== */
void void
LOG_OpenSystemLog(void) LOG_Position(const char *filename, int line_number, const char *function_name)
{ {
#ifdef WINNT #ifdef WINNT
#else #else
system_log = 1; time_t t;
openlog("chronyd", LOG_PID, LOG_DAEMON); struct tm stm;
char buf[64];
if (!is_detached) {
/* Don't clutter up syslog with internal debugging info */
time(&t);
stm = *gmtime(&t);
strftime(buf, sizeof(buf), "%d-%H:%M:%S", &stm);
fprintf(stderr, "%s:%d:(%s)[%s] ", filename, line_number, function_name, buf);
}
#endif
return;
}
/* ================================================== */
void
LOG_GoDaemon(void)
{
#ifdef WINNT
#else
int pid, fd;
/* Does this preserve existing signal handlers? */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'grandparent' */
} else {
setsid();
/* Do 2nd fork, as-per recommended practice for launching daemons. */
pid = fork();
if (pid < 0) {
LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'parent' */
} else {
/* In the child we want to leave running as the daemon */
/* Don't keep stdin/out/err from before. */
for (fd=0; fd<1024; fd++) {
close(fd);
}
is_detached = 1;
openlog("chronyd", LOG_PID, LOG_DAEMON);
LOG(LOGS_INFO, LOGF_Logging, "chronyd version %s starting", PROGRAM_VERSION_STRING);
}
}
#endif #endif
} }
/* ================================================== */ /* ================================================== */
void LOG_SetDebugLevel(int level) int
LOG_RateLimited(void)
{ {
debug_level = level; time_t now;
if (level >= DEBUG_LEVEL_PRINT_DEBUG) {
if (!DEBUG) now = time(NULL);
LOG(LOGS_WARN, LOGF_Logging, "Not compiled with full debugging support");
log_debug_enabled = 1; if (last_limited + 10 > now && last_limited <= now)
} return 1;
}
last_limited = now;
/* ================================================== */ return 0;
void
LOG_SetParentFd(int fd)
{
parent_fd = fd;
}
/* ================================================== */
void
LOG_CloseParentFd()
{
if (parent_fd > 0)
close(parent_fd);
parent_fd = -1;
}
/* ================================================== */
LOG_FileID
LOG_FileOpen(const char *name, const char *banner)
{
assert(n_filelogs < MAX_FILELOGS);
logfiles[n_filelogs].name = name;
logfiles[n_filelogs].banner = banner;
logfiles[n_filelogs].file = NULL;
logfiles[n_filelogs].writes = 0;
return n_filelogs++;
}
/* ================================================== */
void
LOG_FileWrite(LOG_FileID id, const char *format, ...)
{
va_list other_args;
int banner;
if (id < 0 || id >= n_filelogs || !logfiles[id].name)
return;
if (!logfiles[id].file) {
char filename[512];
if (snprintf(filename, sizeof(filename), "%s/%s.log",
CNF_GetLogDir(), logfiles[id].name) >= sizeof(filename) ||
!(logfiles[id].file = fopen(filename, "a"))) {
LOG(LOGS_WARN, LOGF_Refclock, "Couldn't open logfile %s for update", filename);
logfiles[id].name = NULL;
return;
}
/* Close on exec */
UTI_FdSetCloexec(fileno(logfiles[id].file));
}
banner = CNF_GetLogBanner();
if (banner && logfiles[id].writes++ % banner == 0) {
char bannerline[256];
int i, bannerlen;
bannerlen = strlen(logfiles[id].banner);
for (i = 0; i < bannerlen; i++)
bannerline[i] = '=';
bannerline[i] = '\0';
fprintf(logfiles[id].file, "%s\n", bannerline);
fprintf(logfiles[id].file, "%s\n", logfiles[id].banner);
fprintf(logfiles[id].file, "%s\n", bannerline);
}
va_start(other_args, format);
vfprintf(logfiles[id].file, format, other_args);
va_end(other_args);
fprintf(logfiles[id].file, "\n");
fflush(logfiles[id].file);
}
/* ================================================== */
void
LOG_CreateLogFileDir(void)
{
const char *logdir;
logdir = CNF_GetLogDir();
if (!mkdir_and_parents(logdir)) {
LOG(LOGS_ERR, LOGF_Logging, "Could not create directory %s", logdir);
}
}
/* ================================================== */
void
LOG_CycleLogFiles(void)
{
LOG_FileID i;
for (i = 0; i < n_filelogs; i++) {
if (logfiles[i].file)
fclose(logfiles[i].file);
logfiles[i].file = NULL;
logfiles[i].writes = 0;
}
} }
/* ================================================== */ /* ================================================== */

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/logging.h,v 1.15 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2002 * Copyright (C) Richard P. Curnow 1997-2002
* Copyright (C) Miroslav Lichvar 2013-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -29,41 +32,11 @@
#ifndef GOT_LOGGING_H #ifndef GOT_LOGGING_H
#define GOT_LOGGING_H #define GOT_LOGGING_H
#include "sysincl.h"
/* Flag indicating whether debug messages are logged */
extern int log_debug_enabled;
/* Line logging macros. If the compiler is GNU C, we take advantage of
being able to get the function name also. */
#ifdef __GNUC__
#define FUNCTION_NAME __FUNCTION__
#define FORMAT_ATTRIBUTE_PRINTF(str, first) __attribute__ ((format (printf, str, first)))
#else
#define FUNCTION_NAME ""
#define FORMAT_ATTRIBUTE_PRINTF(str, first)
#endif
#define DEBUG_LOG(facility, ...) \
do { \
if (DEBUG && log_debug_enabled) \
LOG_Message(LOGS_DEBUG, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__); \
} while (0)
#define LOG(severity, facility, ...) LOG_Message(severity, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__)
#define LOG_FATAL(facility, ...) \
do { \
LOG_Message(LOGS_FATAL, facility, __LINE__, __FILE__, FUNCTION_NAME, __VA_ARGS__); \
exit(1); \
} while (0)
/* Definition of severity */ /* Definition of severity */
typedef enum { typedef enum {
LOGS_INFO, LOGS_INFO,
LOGS_WARN, LOGS_WARN,
LOGS_ERR, LOGS_ERR
LOGS_FATAL,
LOGS_DEBUG
} LOG_Severity; } LOG_Severity;
/* Definition of facility. Each message is tagged with who generated /* Definition of facility. Each message is tagged with who generated
@@ -85,21 +58,14 @@ typedef enum {
LOGF_CmdMon, LOGF_CmdMon,
LOGF_Acquire, LOGF_Acquire,
LOGF_Manual, LOGF_Manual,
LOGF_Keys,
LOGF_Logging, LOGF_Logging,
LOGF_Nameserv,
LOGF_Rtc, LOGF_Rtc,
LOGF_Regress, LOGF_Regress,
LOGF_Sys,
LOGF_SysGeneric,
LOGF_SysLinux, LOGF_SysLinux,
LOGF_SysNetBSD,
LOGF_SysSolaris, LOGF_SysSolaris,
LOGF_SysSunOS, LOGF_SysSunOS,
LOGF_SysWinnt, LOGF_SysWinnt,
LOGF_TempComp, LOGF_RtcLinux
LOGF_RtcLinux,
LOGF_Refclock
} LOG_Facility; } LOG_Facility;
/* Init function */ /* Init function */
@@ -109,37 +75,27 @@ extern void LOG_Initialise(void);
extern void LOG_Finalise(void); extern void LOG_Finalise(void);
/* Line logging function */ /* Line logging function */
FORMAT_ATTRIBUTE_PRINTF(6, 7) extern void LOG_Line_Function(LOG_Severity severity, LOG_Facility facility, const char *format, ...);
extern void LOG_Message(LOG_Severity severity, LOG_Facility facility,
int line_number, const char *filename,
const char *function_name, const char *format, ...);
/* Set debug level: /* Logging function for fatal errors */
0, 1 - only non-debug messages are logged extern void LOG_Fatal_Function(LOG_Facility facility, const char *format, ...);
2 - debug messages are logged too, all messages are prefixed with
filename, line, and function name
*/
extern void LOG_SetDebugLevel(int level);
/* Log messages to syslog instead of stderr */ /* Position in code reporting function */
extern void LOG_OpenSystemLog(void); extern void LOG_Position(const char *filename, int line_number, const char *function_name);
/* Send fatal message also to the foreground process */ extern void LOG_GoDaemon(void);
extern void LOG_SetParentFd(int fd);
/* Close the pipe to the foreground process so it can exit */ /* Return zero once per 10 seconds */
extern void LOG_CloseParentFd(void); extern int LOG_RateLimited(void);
/* File logging functions */ /* Line logging macro. If the compiler is GNU C, we take advantage of
being able to get the function name also. */
typedef int LOG_FileID; #if defined(__GNUC__)
#define LOG LOG_Position(__FILE__, __LINE__, __FUNCTION__); LOG_Line_Function
extern LOG_FileID LOG_FileOpen(const char *name, const char *banner); #define LOG_FATAL LOG_Position(__FILE__, __LINE__, __FUNCTION__); LOG_Fatal_Function
#else
FORMAT_ATTRIBUTE_PRINTF(2, 3) #define LOG LOG_Position(__FILE__, __LINE__, ""); LOG_Line_Function
extern void LOG_FileWrite(LOG_FileID id, const char *format, ...); #define LOG_FATAL LOG_Position(__FILE__, __LINE__, ""); LOG_Fatal_Function
#endif /* defined (__GNUC__) */
extern void LOG_CreateLogFileDir(void);
extern void LOG_CycleLogFiles(void);
#endif /* GOT_LOGGING_H */ #endif /* GOT_LOGGING_H */

316
main.c
View File

@@ -1,10 +1,12 @@
/* /*
$Header: /cvs/src/chrony/main.c,v 1.31 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) John G. Hasler 2009
* Copyright (C) Miroslav Lichvar 2012-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -17,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,8 +28,6 @@
The main program The main program
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "main.h" #include "main.h"
@@ -44,13 +44,12 @@
#include "conf.h" #include "conf.h"
#include "cmdmon.h" #include "cmdmon.h"
#include "keys.h" #include "keys.h"
#include "acquire.h"
#include "manual.h" #include "manual.h"
#include "version.h"
#include "rtc.h" #include "rtc.h"
#include "refclock.h"
#include "clientlog.h" #include "clientlog.h"
#include "broadcast.h" #include "broadcast.h"
#include "nameserv.h"
#include "tempcomp.h"
/* ================================================== */ /* ================================================== */
@@ -59,12 +58,10 @@
static int initialised = 0; static int initialised = 0;
static int exit_status = 0; /* ================================================== */
static int reload = 0; static int reload = 0;
static REF_Mode ref_mode = REF_ModeNormal;
/* ================================================== */ /* ================================================== */
static void static void
@@ -80,26 +77,25 @@ delete_pidfile(void)
void void
MAI_CleanupAndExit(void) MAI_CleanupAndExit(void)
{ {
if (!initialised) exit(exit_status); if (!initialised) exit(0);
if (CNF_GetDumpOnExit()) { if (CNF_GetDumpOnExit()) {
SRC_DumpSources(); SRC_DumpSources();
} }
TMC_Finalise(); RTC_Finalise();
MNL_Finalise(); MNL_Finalise();
ACQ_Finalise();
CAM_Finalise();
KEY_Finalise();
CLG_Finalise(); CLG_Finalise();
NIO_Finalise();
NSR_Finalise(); NSR_Finalise();
NCR_Finalise(); NCR_Finalise();
BRD_Finalise(); BRD_Finalise();
SRC_Finalise();
SST_Finalise(); SST_Finalise();
REF_Finalise(); REF_Finalise();
KEY_Finalise();
RCL_Finalise();
SRC_Finalise();
RTC_Finalise();
CAM_Finalise();
NIO_Finalise();
SYS_Finalise(); SYS_Finalise();
SCH_Finalise(); SCH_Finalise();
LCL_Finalise(); LCL_Finalise();
@@ -108,7 +104,7 @@ MAI_CleanupAndExit(void)
LOG_Finalise(); LOG_Finalise();
exit(exit_status); exit(0);
} }
/* ================================================== */ /* ================================================== */
@@ -116,17 +112,18 @@ MAI_CleanupAndExit(void)
static void static void
signal_cleanup(int x) signal_cleanup(int x)
{ {
if (!initialised) exit(0); LOG(LOGS_WARN, LOGF_Main, "chronyd exiting on signal");
SCH_QuitProgram(); MAI_CleanupAndExit();
} }
/* ================================================== */ /* ================================================== */
static void static void
ntp_source_resolving_end(void) post_acquire_hook(void *anything)
{ {
NSR_SetSourceResolvingEndHandler(NULL);
CNF_AddSources();
CNF_AddBroadcasts();
if (reload) { if (reload) {
/* Note, we want reload to come well after the initialisation from /* Note, we want reload to come well after the initialisation from
the real time clock - this gives us a fighting chance that the the real time clock - this gives us a fighting chance that the
@@ -134,62 +131,9 @@ ntp_source_resolving_end(void)
semblence of validity about it. */ semblence of validity about it. */
SRC_ReloadSources(); SRC_ReloadSources();
} }
CNF_SetupAccessRestrictions();
RTC_StartMeasurements(); RTC_StartMeasurements();
RCL_StartRefclocks();
NSR_StartSources();
NSR_AutoStartSources();
/* Special modes can end only when sources update their reachability.
Give up immediatelly if there are no active sources. */
if (ref_mode != REF_ModeNormal && !SRC_ActiveSources()) {
REF_SetUnsynchronised();
}
}
/* ================================================== */
static void
post_init_ntp_hook(void *anything)
{
if (ref_mode == REF_ModeInitStepSlew) {
/* Remove the initstepslew sources and set normal mode */
NSR_RemoveAllSources();
ref_mode = REF_ModeNormal;
REF_SetMode(ref_mode);
}
/* Close the pipe to the foreground process so it can exit */
LOG_CloseParentFd();
CNF_AddSources();
CNF_AddBroadcasts();
NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
NSR_ResolveSources();
}
/* ================================================== */
static void
reference_mode_end(int result)
{
switch (ref_mode) {
case REF_ModeNormal:
case REF_ModeUpdateOnce:
case REF_ModePrintOnce:
exit_status = !result;
SCH_QuitProgram();
break;
case REF_ModeInitStepSlew:
/* Switch to the normal mode, the delay is used to prevent polling
interval shorter than the burst interval if some configured servers
were used also for initstepslew */
SCH_AddTimeoutByDelay(2.0, post_init_ntp_hook, NULL);
break;
default:
assert(0);
}
} }
/* ================================================== */ /* ================================================== */
@@ -197,14 +141,7 @@ reference_mode_end(int result)
static void static void
post_init_rtc_hook(void *anything) post_init_rtc_hook(void *anything)
{ {
if (CNF_GetInitSources() > 0) { CNF_ProcessInitStepSlew(post_acquire_hook, NULL);
CNF_AddInitSources();
NSR_StartSources();
assert(REF_GetMode() != REF_ModeNormal);
/* Wait for mode end notification */
} else {
(post_init_ntp_hook)(NULL);
}
} }
/* ================================================== */ /* ================================================== */
@@ -256,7 +193,7 @@ write_lockfile(void)
out = fopen(pidfile, "w"); out = fopen(pidfile, "w");
if (!out) { if (!out) {
LOG_FATAL(LOGF_Main, "could not open lockfile %s for writing", pidfile); LOG(LOGS_ERR, LOGF_Main, "could not open lockfile %s for writing", pidfile);
} else { } else {
fprintf(out, "%d\n", getpid()); fprintf(out, "%d\n", getpid());
fclose(out); fclose(out);
@@ -265,89 +202,13 @@ write_lockfile(void)
/* ================================================== */ /* ================================================== */
static void
go_daemon(void)
{
#ifdef WINNT
#else
int pid, fd, pipefd[2];
/* Create pipe which will the daemon use to notify the grandparent
when it's initialised or send an error message */
if (pipe(pipefd)) {
LOG_FATAL(LOGF_Logging, "Could not detach, pipe failed : %s", strerror(errno));
}
/* Does this preserve existing signal handlers? */
pid = fork();
if (pid < 0) {
LOG_FATAL(LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
/* In the 'grandparent' */
char message[1024];
int r;
close(pipefd[1]);
r = read(pipefd[0], message, sizeof (message));
if (r) {
if (r > 0) {
/* Print the error message from the child */
fprintf(stderr, "%.1024s\n", message);
}
exit(1);
} else
exit(0);
} else {
close(pipefd[0]);
setsid();
/* Do 2nd fork, as-per recommended practice for launching daemons. */
pid = fork();
if (pid < 0) {
LOG_FATAL(LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno));
} else if (pid > 0) {
exit(0); /* In the 'parent' */
} else {
/* In the child we want to leave running as the daemon */
/* Change current directory to / */
if (chdir("/") < 0) {
LOG_FATAL(LOGF_Logging, "Could not chdir to / : %s", strerror(errno));
}
/* Don't keep stdin/out/err from before. But don't close
the parent pipe yet. */
for (fd=0; fd<1024; fd++) {
if (fd != pipefd[1])
close(fd);
}
LOG_SetParentFd(pipefd[1]);
}
}
#endif
}
/* ================================================== */
int main int main
(int argc, char **argv) (int argc, char **argv)
{ {
const char *conf_file = DEFAULT_CONF_FILE; char *conf_file = NULL;
char *user = NULL; int debug = 0;
int debug = 0, nofork = 0, address_family = IPADDR_UNSPEC; int do_init_rtc = 0;
int do_init_rtc = 0, restarted = 0;
int other_pid; int other_pid;
int lock_memory = 0, sched_priority = 0;
int system_log = 1;
int config_args = 0;
LOG_Initialise(); LOG_Initialise();
@@ -357,87 +218,32 @@ int main
if (!strcmp("-f", *argv)) { if (!strcmp("-f", *argv)) {
++argv, --argc; ++argv, --argc;
conf_file = *argv; conf_file = *argv;
} else if (!strcmp("-P", *argv)) {
++argv, --argc;
if (argc == 0 || sscanf(*argv, "%d", &sched_priority) != 1) {
LOG_FATAL(LOGF_Main, "Bad scheduler priority");
}
} else if (!strcmp("-m", *argv)) {
lock_memory = 1;
} else if (!strcmp("-r", *argv)) { } else if (!strcmp("-r", *argv)) {
reload = 1; reload = 1;
} else if (!strcmp("-R", *argv)) {
restarted = 1;
} else if (!strcmp("-u", *argv)) {
++argv, --argc;
if (argc == 0) {
LOG_FATAL(LOGF_Main, "Missing user name");
} else {
user = *argv;
}
} else if (!strcmp("-s", *argv)) { } else if (!strcmp("-s", *argv)) {
do_init_rtc = 1; do_init_rtc = 1;
} else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) { } else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
/* This write to the terminal is OK, it comes before we turn into a daemon */ /* This write to the terminal is OK, it comes before we turn into a daemon */
printf("chronyd (chrony) version %s\n", CHRONY_VERSION); printf("chronyd (chrony) version %s\n", PROGRAM_VERSION_STRING);
exit(0); exit(0);
} else if (!strcmp("-n", *argv)) {
nofork = 1;
} else if (!strcmp("-d", *argv)) { } else if (!strcmp("-d", *argv)) {
debug++; debug = 1;
nofork = 1;
system_log = 0;
} else if (!strcmp("-q", *argv)) {
ref_mode = REF_ModeUpdateOnce;
nofork = 1;
system_log = 0;
} else if (!strcmp("-Q", *argv)) {
ref_mode = REF_ModePrintOnce;
nofork = 1;
system_log = 0;
} else if (!strcmp("-4", *argv)) {
address_family = IPADDR_INET4;
} else if (!strcmp("-6", *argv)) {
address_family = IPADDR_INET6;
} else if (*argv[0] == '-') {
LOG_FATAL(LOGF_Main, "Unrecognized command line option [%s]", *argv);
} else { } else {
/* Process remaining arguments and configuration lines */ LOG(LOGS_WARN, LOGF_Main, "Unrecognized command line option [%s]", *argv);
config_args = argc;
break;
} }
} }
#ifndef SYS_WINNT
if (getuid() != 0) { if (getuid() != 0) {
/* This write to the terminal is OK, it comes before we turn into a daemon */ /* This write to the terminal is OK, it comes before we turn into a daemon */
fprintf(stderr,"Not superuser\n"); fprintf(stderr,"Not superuser\n");
exit(1); exit(1);
} }
/* Turn into a daemon */ /* Turn into a daemon */
if (!nofork) { if (!debug) {
go_daemon(); LOG_GoDaemon();
}
if (system_log) {
LOG_OpenSystemLog();
}
LOG_SetDebugLevel(debug);
LOG(LOGS_INFO, LOGF_Main, "chronyd version %s starting", CHRONY_VERSION);
DNS_SetAddressFamily(address_family);
CNF_SetRestarted(restarted);
/* Parse the config file or the remaining command line arguments */
if (!config_args) {
CNF_ReadFile(conf_file);
} else {
do {
CNF_ParseLine(NULL, config_args - argc + 1, *argv);
} while (++argv, --argc);
} }
/* Check whether another chronyd may already be running. Do this after /* Check whether another chronyd may already be running. Do this after
@@ -446,64 +252,40 @@ int main
if (maybe_another_chronyd_running(&other_pid)) { if (maybe_another_chronyd_running(&other_pid)) {
LOG_FATAL(LOGF_Main, "Another chronyd may already be running (pid=%d), check lockfile (%s)", LOG_FATAL(LOGF_Main, "Another chronyd may already be running (pid=%d), check lockfile (%s)",
other_pid, CNF_GetPidFile()); other_pid, CNF_GetPidFile());
exit(1);
} }
/* Write our lockfile to prevent other chronyds running. This has *GOT* to /* Write our lockfile to prevent other chronyds running. This has *GOT* to
* be done *AFTER* the daemon-creation fork() */ * be done *AFTER* the daemon-creation fork() */
write_lockfile(); write_lockfile();
#endif
CNF_ReadFile(conf_file);
if (do_init_rtc) {
RTC_TimePreInit();
}
LCL_Initialise(); LCL_Initialise();
SCH_Initialise(); SCH_Initialise();
SYS_Initialise(); SYS_Initialise();
NIO_Initialise(address_family);
CAM_Initialise(address_family);
RTC_Initialise(do_init_rtc);
SRC_Initialise();
RCL_Initialise();
KEY_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) {
user = CNF_GetUser();
}
if (user && strcmp(user, "root")) {
SYS_DropRoot(user);
}
LOG_CreateLogFileDir();
REF_Initialise(); REF_Initialise();
SST_Initialise(); SST_Initialise();
SRC_Initialise();
BRD_Initialise(); BRD_Initialise();
NCR_Initialise(); NCR_Initialise();
NSR_Initialise(); NSR_Initialise();
NIO_Initialise();
CLG_Initialise(); CLG_Initialise();
KEY_Initialise();
CAM_Initialise();
ACQ_Initialise();
MNL_Initialise(); MNL_Initialise();
TMC_Initialise(); RTC_Initialise();
/* From now on, it is safe to do finalisation on exit */ /* From now on, it is safe to do finalisation on exit */
initialised = 1; initialised = 1;
CNF_SetupAccessRestrictions();
if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
ref_mode = REF_ModeInitStepSlew;
}
REF_SetModeEndHandler(reference_mode_end);
REF_SetMode(ref_mode);
if (do_init_rtc) { if (do_init_rtc) {
RTC_TimeInit(post_init_rtc_hook, NULL); RTC_TimeInit(post_init_rtc_hook, NULL);
} else { } else {
@@ -521,8 +303,6 @@ int main
the scheduler. */ the scheduler. */
SCH_MainLoop(); SCH_MainLoop();
LOG(LOGS_INFO, LOGF_Main, "chronyd exiting");
MAI_CleanupAndExit(); MAI_CleanupAndExit();
return 0; return 0;

6
main.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/main.h,v 1.8 2002/02/28 23:27:10 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************

View File

@@ -1,78 +1,52 @@
#!/bin/sh #!/usr/bin/env perl
LANG=C $tool = "chrony";
export LANG
if [ $# -ne 1 ]; then $version = shift || die "Usage : $0 <version>\n";
echo "Usage : $0 <version>" $subdir = "${tool}-${version}";
exit 2
fi
version=$1 unless (-d ".git") {
tag=$version die "No .git subdirectory?"
subdir=chrony-${version} }
mandate=$(date +'%B %Y')
umask 022 unless (-d "RELEASES") {
mkdir "RELEASES", 0755;
}
if [ ! -d .git ]; then system ("git-tag -s $version");
echo "No .git subdirectory?" die "git-tag failed" if ($? != 0);
exit 3 if (-d "RELEASES/$subdir") {
fi system ("rm -rf RELEASES/$subdir");
}
[ -d RELEASES ] || mkdir RELEASES system ("git-archive --format=tar --prefix=RELEASES/${subdir}/ $version | tar xf -");
die "git-tar-tree failed" if ($? != 0);
rm -rf RELEASES/$subdir chdir "RELEASES";
$here = qx/pwd/;
chomp $here;
chdir $subdir;
if [ $version != test ]; then open (OUT, ">version.txt");
git tag -s $tag || exit 1 print OUT $version."\n";
else close OUT;
tag=HEAD
fi
git archive --format=tar --prefix=RELEASES/${subdir}/ $tag | \ open (IN, "<${tool}.spec.sample");
tar xf - || exit 1 open (OUT, ">${tool}.spec");
while (<IN>) {
s/\@\@VERSION\@\@/$version/;
print OUT;
}
close (IN);
close (OUT);
cd RELEASES/$subdir || exit 1 system("makeinfo --no-headers --number-sections -o chrony.txt chrony.texi");
unlink "make_release";
unlink "${tool}.spec.sample";
unlink ".gitignore";
echo $version > version.txt chdir $here;
system ("tar cvf - $subdir | gzip -9 > ${subdir}.tar.gz");
system ("gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz");
sed -i -e "s%@@VERSION@@%${version}%" examples/chrony.spec
for m in chrony.1 chronyc.1.in chrony.conf.5.in chronyd.8.in; do
sed -e "s%@VERSION@%${version}%;s%@MAN_DATE@%${mandate}%" \
< $m > ${m}_
mv -f ${m}_ $m
done
./configure && make chrony.txt || exit 1
mv chrony.txt chrony.txt_
make distclean
mv chrony.txt_ chrony.txt
awk '/^[1-9] Installation$/{p=1}
/^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \
tail -n +4 > INSTALL
if [ $(wc -l < INSTALL) -gt 100 -o $(wc -l < INSTALL) -lt 85 ]; then
echo "INSTALL generated incorrectly?"
exit 3
fi
awk '/^[1-9] Frequently asked questions$/{p=1}
/^Appendix A GNU General Public License$/{exit}; p' chrony.txt | \
tail -n +4 | sed 's/^[1-9]\.\([1-9]\)/\1/' | sed 's/^----/--/' | \
sed 's/^====/==/' > FAQ
if [ $(wc -l < FAQ) -gt 400 -o $(wc -l < FAQ) -lt 200 ]; then
echo "FAQ generated incorrectly?"
exit 3
fi
rm -f config.h config.log make_release .gitignore
cd ..
tar cv --owner root --group root $subdir | gzip -9 > ${subdir}.tar.gz
[ $version != test ] && \
gpg -b -a -o ${subdir}-tar-gz-asc.txt ${subdir}.tar.gz

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/manual.c,v 1.21 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -30,9 +34,7 @@
*/ */
#include "config.h" #include <stddef.h>
#include "sysincl.h"
#include "manual.h" #include "manual.h"
#include "logging.h" #include "logging.h"
@@ -59,14 +61,22 @@ typedef struct {
static Sample samples[16]; static Sample samples[16];
static int n_samples; static int n_samples;
static int replace_margin;
static int error;
/* Eventually these constants need to be user-defined in conf file */
#define REPLACE_MARGIN 300
#define ERROR_MARGIN 0.2
/* ================================================== */ /* ================================================== */
static void static void
slew_samples(struct timeval *raw, slew_samples(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *not_used); void *not_used);
/* ================================================== */ /* ================================================== */
@@ -82,7 +92,12 @@ MNL_Initialise(void)
n_samples = 0; n_samples = 0;
replace_margin = REPLACE_MARGIN;
error = ERROR_MARGIN;
LCL_AddParameterChangeHandler(slew_samples, NULL); LCL_AddParameterChangeHandler(slew_samples, NULL);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -90,6 +105,7 @@ MNL_Initialise(void)
void void
MNL_Finalise(void) MNL_Finalise(void)
{ {
return;
} }
/* ================================================== */ /* ================================================== */
@@ -132,8 +148,6 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
} }
b1 = freq = 0.0; b1 = freq = 0.0;
found_freq = 0; found_freq = 0;
agos[0] = 0.0;
offsets[0] = b0;
} }
if (offset_provided) { if (offset_provided) {
@@ -144,7 +158,7 @@ estimate_and_set_system(struct timeval *now, int offset_provided, double offset,
if (found_freq) { if (found_freq) {
LOG(LOGS_INFO, LOGF_Manual, LOG(LOGS_INFO, LOGF_Manual,
"Making a frequency change of %.3f ppm and a slew of %.6f", "Making a frequency change of %.3fppm and a slew of %.6f\n",
1.0e6 * freq, slew_by); 1.0e6 * freq, slew_by);
REF_SetManualReference(now, REF_SetManualReference(now,
@@ -174,13 +188,14 @@ int
MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm) MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm)
{ {
struct timeval now; struct timeval now;
double local_clock_err;
double offset; double offset;
int i; int i;
if (enabled) { if (enabled) {
/* Check whether timestamp is within margin of old one */ /* Check whether timestamp is within margin of old one */
LCL_ReadCookedTime(&now, NULL); LCL_ReadCookedTime(&now, &local_clock_err);
UTI_DiffTimevalsToDouble(&offset, &now, ts); UTI_DiffTimevalsToDouble(&offset, &now, ts);
@@ -215,22 +230,20 @@ static void
slew_samples(struct timeval *raw, slew_samples(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *not_used) void *not_used)
{ {
double delta_time; double elapsed, delta_time;
int i; int i;
if (change_type == LCL_ChangeUnknownStep) {
MNL_Reset();
}
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time, UTI_DiffTimevalsToDouble(&elapsed, cooked, &samples[i].when);
dfreq, doffset); delta_time = elapsed * dfreq - doffset;
UTI_AddDoubleToTimeval(&samples[i].when, delta_time, &samples[i].when);
samples[i].offset += delta_time; samples[i].offset += delta_time;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -274,7 +287,7 @@ MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n)
} }
for (i=0; i<n_samples && i<max; i++) { for (i=0; i<n_samples && i<max; i++) {
report[i].when = samples[i].when; report[i].when = samples[i].when.tv_sec;
report[i].slewed_offset = samples[i].offset; report[i].slewed_offset = samples[i].offset;
report[i].orig_offset = samples[i].orig_offset; report[i].orig_offset = samples[i].orig_offset;
report[i].residual = samples[i].residual; report[i].residual = samples[i].residual;
@@ -290,6 +303,7 @@ MNL_DeleteSample(int index)
{ {
int i; int i;
struct timeval now; struct timeval now;
double local_clock_err;
if ((index < 0) || (index >= n_samples)) { if ((index < 0) || (index >= n_samples)) {
return 0; return 0;
@@ -305,7 +319,7 @@ MNL_DeleteSample(int index)
/* Now re-estimate. NULLs because we don't want the parameters back /* Now re-estimate. NULLs because we don't want the parameters back
in this case. */ in this case. */
LCL_ReadCookedTime(&now, NULL); LCL_ReadCookedTime(&now, &local_clock_err);
estimate_and_set_system(&now, 0, 0.0, NULL, NULL, NULL); estimate_and_set_system(&now, 0, 0.0, NULL, NULL, NULL);
return 1; return 1;

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/manual.h,v 1.12 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************

6
md5.h
View File

@@ -32,7 +32,11 @@
*********************************************************************** ***********************************************************************
*/ */
#include "sysincl.h" #ifdef HAS_STDINT_H
#include <stdint.h>
#elif defined(HAS_INTTYPES_H)
#include <inttypes.h>
#endif
/* typedef a 32-bit type */ /* typedef a 32-bit type */
typedef uint32_t UINT4; typedef uint32_t UINT4;

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/memory.h,v 1.7 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,6 +31,8 @@
#ifndef GOT_MEMORY_H #ifndef GOT_MEMORY_H
#define GOT_MEMORY_H #define GOT_MEMORY_H
#include <stdlib.h>
#define Malloc(x) malloc(x) #define Malloc(x) malloc(x)
#define MallocNew(T) ((T *) malloc(sizeof(T))) #define MallocNew(T) ((T *) malloc(sizeof(T)))
#define MallocArray(T, n) ((T *) malloc((n) * sizeof(T))) #define MallocArray(T, n) ((T *) malloc((n) * sizeof(T)))

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/mkdirpp.c,v 1.10 2002/11/03 22:49:17 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,8 +30,6 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "mkdirpp.h" #include "mkdirpp.h"
@@ -84,7 +86,6 @@ mkdir_and_parents(const char *path)
p[i] = 0; p[i] = 0;
if (do_dir(p) < 0) { if (do_dir(p) < 0) {
free(p);
return 0; return 0;
} }

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/mkdirpp.h,v 1.6 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************

15
mkversion Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
rm -f version.h
echo "#ifndef VERSION_H" > version.h
echo "#define VERSION_H 1" >> version.h
if [ -f version.txt ]; then
ver=`cat version.txt`
echo "#define PROGRAM_VERSION_STRING \"$ver\"" >> version.h
else
echo "#define PROGRAM_VERSION_STRING \"DEVELOPMENT\"" >> version.h
fi
echo "#endif /* VERSION_H */" >> version.h

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/nameserv.c,v 1.15 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2009-2011
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,157 +29,63 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "nameserv.h" #include "nameserv.h"
#include "util.h"
/* ================================================== */ /* ================================================== */
static int address_family = IPADDR_UNSPEC; unsigned long
DNS_Name2IPAddress(const char *name)
void
DNS_SetAddressFamily(int family)
{ {
address_family = family;
}
DNS_Status
DNS_Name2IPAddress(const char *name, IPAddr *addr)
{
#ifdef HAVE_GETADDRINFO
struct addrinfo hints, *res, *ai;
int result;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
result = getaddrinfo(name, NULL, &hints, &res);
if (result) {
#ifdef FORCE_DNSRETRY
return DNS_TryAgain;
#else
return result == EAI_AGAIN ? DNS_TryAgain : DNS_Failure;
#endif
}
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 ? DNS_Success : DNS_Failure;
#else
struct hostent *host; struct hostent *host;
unsigned char *address0;
unsigned long result;
host = gethostbyname(name); host = gethostbyname(name);
if (host == NULL) { if (host == NULL) {
if (h_errno == TRY_AGAIN) result = DNS_Failed_Address;
return DNS_TryAgain;
} else { } else {
addr->family = IPADDR_INET4; address0 = host->h_addr_list[0];
addr->addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[0]); result = ((((unsigned long)address0[0])<<24) |
return DNS_Success; (((unsigned long)address0[1])<<16) |
(((unsigned long)address0[2])<<8) |
(((unsigned long)address0[3])));
} }
#ifdef FORCE_DNSRETRY return result;
return DNS_TryAgain;
#else
return DNS_Failure;
#endif
#endif
} }
/* ================================================== */ /* ================================================== */
int const char *
DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len) DNS_IPAddress2Name(unsigned long ip_addr)
{ {
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; struct hostent *host;
uint32_t addr; static char buffer[16];
unsigned int a, b, c, d;
unsigned long addr;
switch (ip_addr->family) { addr = htonl(ip_addr);
case IPADDR_INET4: if (addr == 0UL) {
addr = htonl(ip_addr->addr.in4); /* Catch this as a special case that will never resolve to
host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET); anything */
break; strcpy(buffer, "0.0.0.0");
#ifdef HAVE_IPV6 return buffer;
case IPADDR_INET6: } else {
host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6); host = gethostbyaddr((const char *) &addr, sizeof(ip_addr), AF_INET);
break; if (!host) {
#endif a = (ip_addr >> 24) & 0xff;
default: b = (ip_addr >> 16) & 0xff;
host = NULL; 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;
}
} }
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;
}
/* ================================================== */
void
DNS_Reload(void)
{
res_init();
} }
/* ================================================== */ /* ================================================== */

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/nameserv.h,v 1.8 2002/02/28 23:27:11 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,22 +32,11 @@
#ifndef GOT_NAMESERV_H #ifndef GOT_NAMESERV_H
#define GOT_NAMESERV_H #define GOT_NAMESERV_H
#include "addressing.h" static const unsigned long DNS_Failed_Address = 0x0UL;
typedef enum { extern unsigned long DNS_Name2IPAddress(const char *name);
DNS_Success,
DNS_TryAgain,
DNS_Failure
} DNS_Status;
/* Resolve names only to selected address family */ const char *DNS_IPAddress2Name(unsigned long ip_addr);
extern void DNS_SetAddressFamily(int family);
extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *addr);
extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);
extern void DNS_Reload(void);
#endif /* GOT_NAMESERV_H */ #endif /* GOT_NAMESERV_H */

View File

@@ -1,144 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2014
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Functions to asynchronously convert name to IP address
*/
#include "config.h"
#include "sysincl.h"
#include "nameserv_async.h"
#include "logging.h"
#include "memory.h"
#include "sched.h"
#include "util.h"
#ifdef FEAT_ASYNCDNS
#ifdef USE_PTHREAD_ASYNCDNS
#include <pthread.h>
/* ================================================== */
struct DNS_Async_Instance {
const char *name;
DNS_Status status;
IPAddr addr;
DNS_NameResolveHandler handler;
void *arg;
pthread_t thread;
int pipe[2];
};
static int resolving_threads = 0;
/* ================================================== */
static void *
start_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
inst->status = DNS_Name2IPAddress(inst->name, &inst->addr);
/* Notify the main thread that the result is ready */
if (write(inst->pipe[1], "", 1) < 0)
;
return NULL;
}
/* ================================================== */
static void
end_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
if (pthread_join(inst->thread, NULL)) {
LOG_FATAL(LOGF_Nameserv, "pthread_join() failed");
}
resolving_threads--;
SCH_RemoveInputFileHandler(inst->pipe[0]);
close(inst->pipe[0]);
close(inst->pipe[1]);
(inst->handler)(inst->status, &inst->addr, inst->arg);
Free(inst);
}
/* ================================================== */
void
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
{
struct DNS_Async_Instance *inst;
inst = MallocNew(struct DNS_Async_Instance);
inst->name = name;
inst->handler = handler;
inst->arg = anything;
inst->status = DNS_Failure;
if (pipe(inst->pipe)) {
LOG_FATAL(LOGF_Nameserv, "pipe() failed");
}
resolving_threads++;
assert(resolving_threads <= 1);
if (pthread_create(&inst->thread, NULL, start_resolving, inst)) {
LOG_FATAL(LOGF_Nameserv, "pthread_create() failed");
}
SCH_AddInputFileHandler(inst->pipe[0], end_resolving, inst);
}
/* ================================================== */
#else
#error
#endif
#else
/* This is a blocking implementation used when nothing else is available */
void
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
{
IPAddr addr;
DNS_Status status;
status = DNS_Name2IPAddress(name, &addr);
(handler)(status, &addr, anything);
}
/* ================================================== */
#endif

View File

@@ -1,41 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2014
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Header for asynchronous nameserver functions
*/
#ifndef GOT_NAMESERV_ASYNC_H
#define GOT_NAMESERV_ASYNC_H
#include "nameserv.h"
/* Function type for callback to process the result */
typedef void (*DNS_NameResolveHandler)(DNS_Status status, IPAddr *ip_addr, void *anything);
/* Request resolving of a name to IP address. The handler will be
called when the result is available, but it may be also called
directly from this function call. */
extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything);
#endif

38
ntp.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/ntp.h,v 1.12 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,9 +31,11 @@
#ifndef GOT_NTP_H #ifndef GOT_NTP_H
#define GOT_NTP_H #define GOT_NTP_H
#include "sysincl.h" #ifdef HAS_STDINT_H
#include <stdint.h>
#include "hash.h" #elif defined(HAS_INTTYPES_H)
#include <inttypes.h>
#endif
typedef struct { typedef struct {
uint32_t hi; uint32_t hi;
@@ -38,7 +44,7 @@ typedef struct {
typedef uint32_t NTP_int32; typedef uint32_t NTP_int32;
#define MAX_NTP_AUTH_DATA_LEN MAX_HASH_LENGTH #define AUTH_DATA_LEN 16
/* Type definition for leap bits */ /* Type definition for leap bits */
typedef enum { typedef enum {
@@ -70,7 +76,7 @@ typedef struct {
NTP_int64 receive_ts; NTP_int64 receive_ts;
NTP_int64 transmit_ts; NTP_int64 transmit_ts;
NTP_int32 auth_keyid; NTP_int32 auth_keyid;
uint8_t auth_data[MAX_NTP_AUTH_DATA_LEN]; uint8_t auth_data[AUTH_DATA_LEN];
} NTP_Packet; } NTP_Packet;
/* We have to declare a buffer type to hold a datagram read from the /* We have to declare a buffer type to hold a datagram read from the
@@ -87,6 +93,24 @@ typedef union {
uint8_t arbitrary[MAX_NTP_MESSAGE_SIZE]; uint8_t arbitrary[MAX_NTP_MESSAGE_SIZE];
} ReceiveBuffer; } ReceiveBuffer;
#define NTP_NORMAL_PACKET_SIZE offsetof(NTP_Packet, auth_keyid) #define NTP_NORMAL_PACKET_SIZE (sizeof(NTP_Packet) - (sizeof(NTP_int32) + AUTH_DATA_LEN))
/* ================================================== */
inline static double
int32_to_double(NTP_int32 x)
{
return (double) ntohl(x) / 65536.0;
}
/* ================================================== */
inline static NTP_int32
double_to_int32(double x)
{
return htonl((NTP_int32)(0.5 + 65536.0 * x));
}
/* ================================================== */
#endif /* GOT_NTP_H */ #endif /* GOT_NTP_H */

1668
ntp_core.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/ntp_core.h,v 1.16 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -34,10 +38,6 @@
#include "ntp.h" #include "ntp.h"
#include "reports.h" #include "reports.h"
typedef enum {
NTP_SERVER, NTP_PEER
} NTP_Source_Type;
/* This is a private data type used for storing the instance record for /* This is a private data type used for storing the instance record for
each source that we are chiming with */ each source that we are chiming with */
typedef struct NCR_Instance_Record *NCR_Instance; typedef struct NCR_Instance_Record *NCR_Instance;
@@ -46,25 +46,31 @@ typedef struct NCR_Instance_Record *NCR_Instance;
extern void NCR_Initialise(void); extern void NCR_Initialise(void);
extern void NCR_Finalise(void); extern void NCR_Finalise(void);
/* Get a new instance for a server or peer */ /* Get a new instance for a server */
extern NCR_Instance NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params); extern NCR_Instance NCR_GetServerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Get a new instance for a peer */
extern NCR_Instance NCR_GetPeerInstance(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Destroy an instance */ /* Destroy an instance */
extern void NCR_DestroyInstance(NCR_Instance instance); extern void NCR_DestroyInstance(NCR_Instance instance);
/* Start an instance */
extern void NCR_StartInstance(NCR_Instance instance);
/* Reset an instance */
extern void NCR_ResetInstance(NCR_Instance inst);
/* This routine is called when a new packet arrives off the network, /* This routine is called when a new packet arrives off the network,
and it relates to a source we have an ongoing protocol exchange with */ and it relates to a source we have an ongoing protocol exchange with */
extern void NCR_ProcessKnown(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance data, int sock_fd, int length); extern void NCR_ProcessNoauthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
/* This routine is called when a new packet arrives off the network, /* This routine is called when a new packet arrives off the network,
and we do not recognize its source */ and we do not recognize its source */
extern void NCR_ProcessUnknown(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length); extern void NCR_ProcessNoauthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* This routine is called when a new authenticated packet arrives off
the network, and it relates to a source we have an ongoing protocol
exchange with */
extern void NCR_ProcessAuthKnown(NTP_Packet *message, struct timeval *now, NCR_Instance data);
/* This routine is called when a new authenticated packet arrives off
the network, and we do not recognize its source */
extern void NCR_ProcessAuthUnknown(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* Slew receive and transmit times in instance records */ /* Slew receive and transmit times in instance records */
extern void NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset); extern void NCR_SlewTimes(NCR_Instance inst, struct timeval *when, double dfreq, double doffset);
@@ -84,24 +90,16 @@ extern void NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay);
extern void NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio); extern void NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio);
extern void NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio);
extern void NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum);
extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples); extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now); extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timeval *now);
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all); extern int NCR_AddAccessRestriction(unsigned long ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr); extern int NCR_CheckAccessRestriction(unsigned long ip_addr);
extern void NCR_CycleLogFile(void);
extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline, extern void NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline,
int *burst_online, int *burst_offline); int *burst_online, int *burst_offline);
extern NTP_Remote_Address *NCR_GetRemoteAddress(NCR_Instance instance);
extern int NCR_IsSyncPeer(NCR_Instance instance);
#endif /* GOT_NTP_CORE_H */ #endif /* GOT_NTP_CORE_H */

718
ntp_io.c
View File

@@ -1,10 +1,12 @@
/* /*
$Header: /cvs/src/chrony/ntp_io.c,v 1.24 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Timo Teras 2009
* Copyright (C) Miroslav Lichvar 2009, 2013-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -17,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,8 +28,6 @@
This file deals with the IO aspects of reading and writing NTP packets This file deals with the IO aspects of reading and writing NTP packets
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "ntp_io.h" #include "ntp_io.h"
@@ -39,27 +39,10 @@
#include "conf.h" #include "conf.h"
#include "util.h" #include "util.h"
#define INVALID_SOCK_FD -1 #include <fcntl.h>
union sockaddr_in46 { /* The file descriptor for the socket */
struct sockaddr_in in4; static int sock_fd;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr u;
};
/* The server/peer and client sockets for IPv4 and IPv6 */
static int server_sock_fd4;
static int client_sock_fd4;
#ifdef HAVE_IPV6
static int server_sock_fd6;
static int client_sock_fd6;
#endif
/* Flag indicating we create a new connected client socket for each
server instead of sharing client_sock_fd4 and client_sock_fd6 */
static int separate_client_sockets;
/* Flag indicating that we have been initialised */ /* Flag indicating that we have been initialised */
static int initialised=0; static int initialised=0;
@@ -71,280 +54,105 @@ static void read_from_socket(void *anything);
/* ================================================== */ /* ================================================== */
static int static void
prepare_socket(int family, int port_number, int client_only) do_size_checks(void)
{ {
union sockaddr_in46 my_addr; /* Assertions to check the sizes of certain data types
socklen_t my_addr_len; and the positions of certain record fields */
int sock_fd;
IPAddr bind_address; /* Check that certain invariants are true */
assert(sizeof(NTP_int32) == 4);
assert(sizeof(NTP_int64) == 8);
/* Check offsets of all fields in the NTP packet format */
assert(offsetof(NTP_Packet, lvm) == 0);
assert(offsetof(NTP_Packet, stratum) == 1);
assert(offsetof(NTP_Packet, poll) == 2);
assert(offsetof(NTP_Packet, precision) == 3);
assert(offsetof(NTP_Packet, root_delay) == 4);
assert(offsetof(NTP_Packet, root_dispersion) == 8);
assert(offsetof(NTP_Packet, reference_id) == 12);
assert(offsetof(NTP_Packet, reference_ts) == 16);
assert(offsetof(NTP_Packet, originate_ts) == 24);
assert(offsetof(NTP_Packet, receive_ts) == 32);
assert(offsetof(NTP_Packet, transmit_ts) == 40);
}
/* ================================================== */
void
NIO_Initialise(void)
{
struct sockaddr_in my_addr;
unsigned short port_number;
unsigned long bind_address;
int on_off = 1; int on_off = 1;
assert(!initialised);
initialised = 1;
do_size_checks();
port_number = CNF_GetNTPPort();
/* Open Internet domain UDP socket for NTP message transmissions */ /* Open Internet domain UDP socket for NTP message transmissions */
sock_fd = socket(family, SOCK_DGRAM, 0); #if 0
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock_fd < 0) { #else
LOG(LOGS_ERR, LOGF_NtpIO, "Could not open %s NTP socket : %s", sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
return INVALID_SOCK_FD;
}
/* Close on exec */
UTI_FdSetCloexec(sock_fd);
/* Prepare local address */
memset(&my_addr, 0, sizeof (my_addr));
my_addr_len = 0;
switch (family) {
case AF_INET:
if (!client_only)
CNF_GetBindAddress(IPADDR_INET4, &bind_address);
else
CNF_GetBindAcquisitionAddress(IPADDR_INET4, &bind_address);
if (bind_address.family == IPADDR_INET4)
my_addr.in4.sin_addr.s_addr = htonl(bind_address.addr.in4);
else if (port_number)
my_addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
else
break;
my_addr.in4.sin_family = family;
my_addr.in4.sin_port = htons(port_number);
my_addr_len = sizeof (my_addr.in4);
break;
#ifdef HAVE_IPV6
case AF_INET6:
if (!client_only)
CNF_GetBindAddress(IPADDR_INET6, &bind_address);
else
CNF_GetBindAcquisitionAddress(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 if (port_number)
my_addr.in6.sin6_addr = in6addr_any;
else
break;
my_addr.in6.sin6_family = family;
my_addr.in6.sin6_port = htons(port_number);
my_addr_len = sizeof (my_addr.in6);
break;
#endif #endif
default: if (sock_fd < 0) {
assert(0); LOG_FATAL(LOGF_NtpIO, "Could not open socket : %s", strerror(errno));
} }
/* Make the socket capable of re-using an old address if binding to a specific port */ /* Make the socket capable of re-using an old address */
if (port_number && if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on_off, sizeof(on_off)) < 0) {
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set reuseaddr socket options"); LOG(LOGS_ERR, LOGF_NtpIO, "Could not set reuseaddr socket options");
/* Don't quit - we might survive anyway */ /* Don't quit - we might survive anyway */
} }
/* Make the socket capable of sending broadcast pkts - needed for NTP broadcast mode */ /* Make the socket capable of sending broadcast pkts - needed for NTP broadcast mode */
if (!client_only && if (setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&on_off, sizeof(on_off)) < 0) {
setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set broadcast socket options"); LOG(LOGS_ERR, LOGF_NtpIO, "Could not set broadcast socket options");
/* Don't quit - we might survive anyway */ /* Don't quit - we might survive anyway */
} }
#ifdef SO_TIMESTAMP /* Bind the port */
/* Enable receiving of timestamp control messages */ my_addr.sin_family = AF_INET;
if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMP, (char *)&on_off, sizeof(on_off)) < 0) { my_addr.sin_port = htons(port_number);
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set timestamp socket options");
/* Don't quit - we might survive anyway */ CNF_GetBindAddress(&bind_address);
if (bind_address != 0UL) {
my_addr.sin_addr.s_addr = htonl(bind_address);
} else {
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
} }
#if 0
LOG(LOGS_INFO, LOGF_NtpIO, "Initialising, socket fd=%d", sock_fd);
#endif #endif
#ifdef IP_FREEBIND if (bind(sock_fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
/* Allow binding to address that doesn't exist yet */ LOG_FATAL(LOGF_NtpIO, "Could not bind socket : %s", strerror(errno));
if (my_addr_len > 0 &&
setsockopt(sock_fd, IPPROTO_IP, IP_FREEBIND, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set free bind socket option");
}
#endif
if (family == AF_INET) {
#ifdef IP_PKTINFO
/* We want the local IP info on server sockets */
if (!client_only &&
setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set packet info 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 set IPV6_V6ONLY socket option");
}
#endif
if (!client_only) {
#ifdef IPV6_RECVPKTINFO
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set IPv6 packet info socket option");
}
#elif defined(IPV6_PKTINFO)
if (setsockopt(sock_fd, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not set IPv6 packet info socket option");
}
#endif
}
}
#endif
/* Bind the socket if a port or address was specified */
if (my_addr_len > 0 && bind(sock_fd, &my_addr.u, my_addr_len) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not bind %s NTP socket : %s",
family == AF_INET ? "IPv4" : "IPv6", strerror(errno));
close(sock_fd);
return INVALID_SOCK_FD;
} }
/* Register handler for read events on the socket */ /* Register handler for read events on the socket */
SCH_AddInputFileHandler(sock_fd, read_from_socket, (void *)(long)sock_fd); SCH_AddInputFileHandler(sock_fd, read_from_socket, NULL);
return sock_fd; #if 0
} if (fcntl(sock_fd, F_SETFL, O_NONBLOCK | O_NDELAY) < 0) {
LOG(LOGS_ERR, LOGF_NtpIO, "Could not make socket non-blocking");
/* ================================================== */
static int
prepare_separate_client_socket(int family)
{
switch (family) {
case IPADDR_INET4:
return prepare_socket(AF_INET, 0, 1);
#ifdef HAVE_IPV6
case IPADDR_INET6:
return prepare_socket(AF_INET6, 0, 1);
#endif
default:
return INVALID_SOCK_FD;
}
}
/* ================================================== */
static int
connect_socket(int sock_fd, NTP_Remote_Address *remote_addr)
{
union sockaddr_in46 addr;
socklen_t addr_len;
memset(&addr, 0, sizeof (addr));
switch (remote_addr->ip_addr.family) {
case IPADDR_INET4:
addr_len = sizeof (addr.in4);
addr.in4.sin_family = AF_INET;
addr.in4.sin_addr.s_addr = htonl(remote_addr->ip_addr.addr.in4);
addr.in4.sin_port = htons(remote_addr->port);
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
addr_len = sizeof (addr.in6);
addr.in6.sin6_family = AF_INET6;
memcpy(addr.in6.sin6_addr.s6_addr, remote_addr->ip_addr.addr.in6,
sizeof (addr.in6.sin6_addr.s6_addr));
addr.in6.sin6_port = htons(remote_addr->port);
break;
#endif
default:
assert(0);
} }
if (connect(sock_fd, &addr.u, addr_len) < 0) { if (ioctl(sock_fd, I_SETSIG, S_INPUT) < 0) {
DEBUG_LOG(LOGF_NtpIO, "Could not connect NTP socket to %s:%d : %s", LOG(LOGS_ERR, LOGF_NtpIO, "Could not enable signal");
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
strerror(errno));
return 0;
}
return 1;
}
/* ================================================== */
static void
close_socket(int sock_fd)
{
if (sock_fd == INVALID_SOCK_FD)
return;
SCH_RemoveInputFileHandler(sock_fd);
close(sock_fd);
}
/* ================================================== */
void
NIO_Initialise(int family)
{
int server_port, client_port;
assert(!initialised);
initialised = 1;
server_port = CNF_GetNTPPort();
client_port = CNF_GetAcquisitionPort();
/* Use separate connected sockets if client port is negative */
separate_client_sockets = client_port < 0;
if (client_port < 0)
client_port = 0;
server_sock_fd4 = INVALID_SOCK_FD;
client_sock_fd4 = INVALID_SOCK_FD;
#ifdef HAVE_IPV6
server_sock_fd6 = INVALID_SOCK_FD;
client_sock_fd6 = INVALID_SOCK_FD;
#endif
if (family == IPADDR_UNSPEC || family == IPADDR_INET4) {
if (server_port)
server_sock_fd4 = prepare_socket(AF_INET, server_port, 0);
if (!separate_client_sockets) {
if (client_port != server_port || !server_port)
client_sock_fd4 = prepare_socket(AF_INET, client_port, 1);
else
client_sock_fd4 = server_sock_fd4;
}
}
#ifdef HAVE_IPV6
if (family == IPADDR_UNSPEC || family == IPADDR_INET6) {
if (server_port)
server_sock_fd6 = prepare_socket(AF_INET6, server_port, 0);
if (!separate_client_sockets) {
if (client_port != server_port || !server_port)
client_sock_fd6 = prepare_socket(AF_INET6, client_port, 1);
else
client_sock_fd6 = server_sock_fd6;
}
} }
#endif #endif
if ((server_port && server_sock_fd4 == INVALID_SOCK_FD return;
#ifdef HAVE_IPV6
&& server_sock_fd6 == INVALID_SOCK_FD
#endif
) || (!separate_client_sockets && client_sock_fd4 == INVALID_SOCK_FD
#ifdef HAVE_IPV6
&& client_sock_fd6 == INVALID_SOCK_FD
#endif
)) {
LOG_FATAL(LOGF_NtpIO, "Could not open NTP sockets");
}
} }
/* ================================================== */ /* ================================================== */
@@ -352,88 +160,17 @@ NIO_Initialise(int family)
void void
NIO_Finalise(void) NIO_Finalise(void)
{ {
if (server_sock_fd4 != client_sock_fd4) if (sock_fd >= 0) {
close_socket(client_sock_fd4); SCH_RemoveInputFileHandler(sock_fd);
close_socket(server_sock_fd4); close(sock_fd);
server_sock_fd4 = client_sock_fd4 = INVALID_SOCK_FD; }
#ifdef HAVE_IPV6 sock_fd = -1;
if (server_sock_fd6 != client_sock_fd6)
close_socket(client_sock_fd6);
close_socket(server_sock_fd6);
server_sock_fd6 = client_sock_fd6 = INVALID_SOCK_FD;
#endif
initialised = 0; initialised = 0;
return;
} }
/* ================================================== */ /* ================================================== */
int
NIO_GetClientSocket(NTP_Remote_Address *remote_addr)
{
if (separate_client_sockets) {
int sock_fd = prepare_separate_client_socket(remote_addr->ip_addr.family);
if (sock_fd == INVALID_SOCK_FD)
return INVALID_SOCK_FD;
if (!connect_socket(sock_fd, remote_addr)) {
close_socket(sock_fd);
return INVALID_SOCK_FD;
}
return sock_fd;
} else {
switch (remote_addr->ip_addr.family) {
case IPADDR_INET4:
return client_sock_fd4;
#ifdef HAVE_IPV6
case IPADDR_INET6:
return client_sock_fd6;
#endif
default:
return INVALID_SOCK_FD;
}
}
}
/* ================================================== */
int
NIO_GetServerSocket(NTP_Remote_Address *remote_addr)
{
switch (remote_addr->ip_addr.family) {
case IPADDR_INET4:
return server_sock_fd4;
#ifdef HAVE_IPV6
case IPADDR_INET6:
return server_sock_fd6;
#endif
default:
return INVALID_SOCK_FD;
}
}
/* ================================================== */
void
NIO_CloseClientSocket(int sock_fd)
{
if (separate_client_sockets)
close_socket(sock_fd);
}
/* ================================================== */
int
NIO_IsServerSocket(int sock_fd)
{
return sock_fd != INVALID_SOCK_FD &&
(sock_fd == server_sock_fd4
#ifdef HAVE_IPV6
|| sock_fd == server_sock_fd6
#endif
);
}
/* ================================================== */ /* ================================================== */
@@ -443,35 +180,24 @@ read_from_socket(void *anything)
/* This should only be called when there is something /* This should only be called when there is something
to read, otherwise it will block. */ to read, otherwise it will block. */
int status, sock_fd; int status;
ReceiveBuffer message; ReceiveBuffer message;
union sockaddr_in46 where_from; int message_length;
struct sockaddr_in where_from;
socklen_t from_length;
unsigned int flags = 0; unsigned int flags = 0;
struct timeval now; struct timeval now;
double now_err;
NTP_Remote_Address remote_addr; NTP_Remote_Address remote_addr;
NTP_Local_Address local_addr; double local_clock_err;
char cmsgbuf[256];
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
assert(initialised); assert(initialised);
SCH_GetLastEventTime(&now, &now_err, NULL); from_length = sizeof(where_from);
message_length = sizeof(message);
iov.iov_base = message.arbitrary; LCL_ReadCookedTime(&now, &local_clock_err);
iov.iov_len = sizeof(message); status = recvfrom(sock_fd, (char *)&message, message_length, flags,
msg.msg_name = &where_from; (struct sockaddr *)&where_from, &from_length);
msg.msg_namelen = sizeof(where_from);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = (void *) cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = 0;
sock_fd = (long)anything;
status = recvmsg(sock_fd, &msg, flags);
/* Don't bother checking if read failed or why if it did. More /* Don't bother checking if read failed or why if it did. More
likely than not, it will be connection refused, resulting from a likely than not, it will be connection refused, resulting from a
@@ -481,73 +207,16 @@ read_from_socket(void *anything)
reponse on a subsequent recvfrom). */ reponse on a subsequent recvfrom). */
if (status > 0) { if (status > 0) {
if (msg.msg_namelen > sizeof (where_from)) remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
LOG_FATAL(LOGF_NtpIO, "Truncated source address"); remote_addr.port = ntohs(where_from.sin_port);
switch (where_from.u.sa_family) { if (status == NTP_NORMAL_PACKET_SIZE) {
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);
}
local_addr.ip_addr.family = IPADDR_UNSPEC; NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
local_addr.sock_fd = sock_fd;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { } else if (status == sizeof(NTP_Packet)) {
#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)); NSR_ProcessAuthenticatedReceive((NTP_Packet *) &message.ntp_pkt, &now, &remote_addr);
local_addr.ip_addr.addr.in4 = ntohl(ipi.ipi_spec_dst.s_addr);
local_addr.ip_addr.family = IPADDR_INET4;
}
#endif
#if defined(IPV6_PKTINFO) && defined(HAVE_IN6_PKTINFO)
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
struct in6_pktinfo ipi;
memcpy(&ipi, CMSG_DATA(cmsg), sizeof(ipi));
memcpy(&local_addr.ip_addr.addr.in6, &ipi.ipi6_addr.s6_addr,
sizeof (local_addr.ip_addr.addr.in6));
local_addr.ip_addr.family = IPADDR_INET6;
}
#endif
#ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
LCL_CookTime(&tv, &now, &now_err);
}
#endif
}
if (status > 0) {
DEBUG_LOG(LOGF_NtpIO, "Received %d bytes from %s:%d to %s fd %d",
status,
UTI_IPToString(&remote_addr.ip_addr), remote_addr.port,
UTI_IPToString(&local_addr.ip_addr), local_addr.sock_fd);
}
if (status >= NTP_NORMAL_PACKET_SIZE && status <= sizeof(NTP_Packet)) {
NSR_ProcessReceive((NTP_Packet *) &message.ntp_pkt, &now, now_err,
&remote_addr, &local_addr, status);
} else { } else {
@@ -555,145 +224,76 @@ read_from_socket(void *anything)
} }
} }
}
/* ================================================== */ return;
/* Send a packet to given address */
static int
send_packet(void *packet, int packetlen, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)
{
union sockaddr_in46 remote;
struct msghdr msg;
struct iovec iov;
char cmsgbuf[256];
int cmsglen;
socklen_t addrlen = 0;
assert(initialised);
if (local_addr->sock_fd == INVALID_SOCK_FD) {
DEBUG_LOG(LOGF_NtpIO, "No socket to send to %s:%d",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port);
return 0;
}
switch (remote_addr->ip_addr.family) {
case IPADDR_INET4:
/* Don't set address with connected socket */
if (local_addr->sock_fd != server_sock_fd4 && separate_client_sockets)
break;
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);
break;
#ifdef HAVE_IPV6
case IPADDR_INET6:
/* Don't set address with connected socket */
if (local_addr->sock_fd != server_sock_fd6 && separate_client_sockets)
break;
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));
break;
#endif
default:
return 0;
}
if (addrlen) {
msg.msg_name = &remote.u;
msg.msg_namelen = addrlen;
} else {
msg.msg_name = NULL;
msg.msg_namelen = 0;
}
iov.iov_base = packet;
iov.iov_len = packetlen;
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 (local_addr->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(local_addr->ip_addr.addr.in4);
}
#endif
#if defined(IPV6_PKTINFO) && defined(HAVE_IN6_PKTINFO)
if (local_addr->ip_addr.family == IPADDR_INET6) {
struct cmsghdr *cmsg;
struct in6_pktinfo *ipi;
cmsg = CMSG_FIRSTHDR(&msg);
memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
cmsglen += CMSG_SPACE(sizeof(struct in6_pktinfo));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
ipi = (struct in6_pktinfo *) CMSG_DATA(cmsg);
memcpy(&ipi->ipi6_addr.s6_addr, &local_addr->ip_addr.addr.in6,
sizeof(ipi->ipi6_addr.s6_addr));
}
#endif
msg.msg_controllen = cmsglen;
/* This is apparently required on some systems */
if (!cmsglen)
msg.msg_control = NULL;
if (sendmsg(local_addr->sock_fd, &msg, 0) < 0) {
DEBUG_LOG(LOGF_NtpIO, "Could not send to %s:%d from %s fd %d : %s",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
UTI_IPToString(&local_addr->ip_addr), local_addr->sock_fd,
strerror(errno));
return 0;
}
DEBUG_LOG(LOGF_NtpIO, "Sent to %s:%d from %s fd %d",
UTI_IPToString(&remote_addr->ip_addr), remote_addr->port,
UTI_IPToString(&local_addr->ip_addr), local_addr->sock_fd);
return 1;
} }
/* ================================================== */ /* ================================================== */
/* Send an unauthenticated packet to a given address */ /* Send an unauthenticated packet to a given address */
int void
NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr) NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{ {
return send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE, remote_addr, local_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_RateLimited()) {
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 an authenticated packet to a given address */ /* Send an authenticated packet to a given address */
int void
NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int auth_len) NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
{ {
return send_packet((void *) packet, NTP_NORMAL_PACKET_SIZE + auth_len, remote_addr, local_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_RateLimited()) {
LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
}
return;
}
/* ================================================== */
/* We ought to use getservbyname, but I can't really see this changing */
#define ECHO_PORT 7
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));
} }

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/ntp_io.h,v 1.9 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2002 * Copyright (C) Richard P. Curnow 1997-2002
* Copyright (C) Miroslav Lichvar 2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -33,27 +36,18 @@
#include "addressing.h" #include "addressing.h"
/* Function to initialise the module. */ /* Function to initialise the module. */
extern void NIO_Initialise(int family); extern void NIO_Initialise(void);
/* Function to finalise the module */ /* Function to finalise the module */
extern void NIO_Finalise(void); extern void NIO_Finalise(void);
/* Function to obtain a socket for sending client packets */
extern int NIO_GetClientSocket(NTP_Remote_Address *remote_addr);
/* Function to obtain a socket for sending server/peer packets */
extern int NIO_GetServerSocket(NTP_Remote_Address *remote_addr);
/* Function to close a socket returned by NIO_GetClientSocket() */
extern void NIO_CloseClientSocket(int sock_fd);
/* Function to check if socket is a server socket */
extern int NIO_IsServerSocket(int sock_fd);
/* Function to transmit a packet */ /* Function to transmit a packet */
extern int NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr); extern void NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
/* Function to transmit an authenticated packet */ /* Function to transmit an authenticated packet */
extern int NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int auth_len); extern void NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr);
/* Function to send a datagram to a remote machine's UDP echo port. */
extern void NIO_SendEcho(NTP_Remote_Address *remote_addr);
#endif /* GOT_NTP_IO_H */ #endif /* GOT_NTP_IO_H */

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/ntp_sources.c,v 1.18 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011-2012, 2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,8 +30,6 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "ntp_sources.h" #include "ntp_sources.h"
@@ -36,17 +37,14 @@
#include "util.h" #include "util.h"
#include "logging.h" #include "logging.h"
#include "local.h" #include "local.h"
#include "memory.h"
#include "nameserv_async.h"
#include "sched.h"
/* ================================================== */ /* ================================================== */
/* Record type private to this file, used to store information about /* Record type private to this file, used to store information about
particular sources */ particular sources */
typedef struct { typedef struct {
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL NTP_Remote_Address remote_addr; /* The address of this source */
means this slot in table is in use */ int in_use; /* Whether this slot in the table is in use */
NCR_Instance data; /* Data for the protocol engine for this source */ NCR_Instance data; /* Data for the protocol engine for this source */
} SourceRecord; } SourceRecord;
@@ -62,39 +60,15 @@ static int n_sources;
/* The largest number of sources we want to have stored in the hash table */ /* The largest number of sources we want to have stored in the hash table */
#define MAX_SOURCES 64 #define MAX_SOURCES 64
/* Flag indicating new sources will be started automatically when added */
static int auto_start_sources = 0;
/* Source with unknown address (which may be resolved later) */
struct UnresolvedSource {
char *name;
int port;
NTP_Source_Type type;
SourceParameters params;
struct UnresolvedSource *next;
};
#define RESOLVE_INTERVAL_UNIT 7
#define MIN_RESOLVE_INTERVAL 2
#define MAX_RESOLVE_INTERVAL 9
static struct UnresolvedSource *unresolved_sources = NULL;
static int resolving_interval = 0;
static SCH_TimeoutID resolving_id;
static struct UnresolvedSource *resolving_source = NULL;
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
static void resolve_sources(void *arg);
static void static void
slew_sources(struct timeval *raw, slew_sources(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *anything); void *anything);
/* ================================================== */ /* ================================================== */
@@ -109,12 +83,14 @@ NSR_Initialise(void)
{ {
int i; int i;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
records[i].remote_addr = NULL; records[i].in_use = 0;
} }
n_sources = 0; n_sources = 0;
initialised = 1; initialised = 1;
LCL_AddParameterChangeHandler(slew_sources, NULL); LCL_AddParameterChangeHandler(slew_sources, NULL);
return;
} }
/* ================================================== */ /* ================================================== */
@@ -123,6 +99,7 @@ void
NSR_Finalise(void) NSR_Finalise(void)
{ {
initialised = 0; initialised = 0;
return; /* Nothing to do yet */
} }
/* ================================================== */ /* ================================================== */
@@ -143,42 +120,23 @@ static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found) find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{ {
unsigned long hash; unsigned long hash;
unsigned long ip; unsigned long ip = remote_addr->ip_addr;
unsigned short port; unsigned short port = remote_addr->port;
uint8_t *ip6;
assert(N_RECORDS == 256); assert(N_RECORDS == 256);
switch (remote_addr->ip_addr.family) {
case IPADDR_INET6:
ip6 = remote_addr->ip_addr.addr.in6;
ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
(ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
(ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
(ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
break;
case IPADDR_INET4:
ip = remote_addr->ip_addr.addr.in4;
break;
default:
*found = *slot = 0;
return;
}
port = remote_addr->port;
/* Compute hash value just by xor'ing the 4 bytes of the address together */ /* Compute hash value just by xor'ing the 4 bytes of the address together */
hash = ip ^ (ip >> 16); hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff; hash = (hash ^ (hash >> 8)) & 0xff;
while (records[hash].remote_addr && while ((records[hash].in_use) &&
UTI_CompareIPs(&records[hash].remote_addr->ip_addr, (records[hash].remote_addr.ip_addr != ip)) {
&remote_addr->ip_addr, NULL)) {
hash++; hash++;
if (hash == 256) hash = 0; if (hash == 256) hash = 0;
} }
if (records[hash].remote_addr) { if (records[hash].in_use) {
if (records[hash].remote_addr->port == port) { if (records[hash].remote_addr.port == port) {
*found = 2; *found = 2;
} else { } else {
*found = 1; *found = 1;
@@ -188,18 +146,25 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
*found = 0; *found = 0;
*slot = hash; *slot = hash;
} }
return;
} }
/* ================================================== */ /* ================================================== */
/* Procedure to add a new source */ /* Procedure to add a new server source (to which this machine will be
a client) */
NSR_Status NSR_Status
NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params) NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params)
{ {
int slot, found; int slot, found;
assert(initialised); assert(initialised);
#if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long)remote_addr->ip_addr, remote_addr->port);
#endif
/* Find empty bin & check that we don't have the address already */ /* Find empty bin & check that we don't have the address already */
find_slot(remote_addr, &slot, &found); find_slot(remote_addr, &slot, &found);
if (found) { if (found) {
@@ -207,15 +172,11 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
} else { } else {
if (n_sources == MAX_SOURCES) { if (n_sources == MAX_SOURCES) {
return NSR_TooManySources; return NSR_TooManySources;
} else if (remote_addr->ip_addr.family != IPADDR_INET4 &&
remote_addr->ip_addr.family != IPADDR_INET6) {
return NSR_InvalidAF;
} else { } else {
n_sources++; n_sources++;
records[slot].data = NCR_GetInstance(remote_addr, type, params); /* Will need params passing through */ records[slot].remote_addr = *remote_addr;
records[slot].remote_addr = NCR_GetRemoteAddress(records[slot].data); records[slot].in_use = 1;
if (auto_start_sources) records[slot].data = NCR_GetServerInstance(remote_addr, params); /* Will need params passing through */
NCR_StartInstance(records[slot].data);
return NSR_Success; return NSR_Success;
} }
} }
@@ -223,166 +184,37 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
/* ================================================== */ /* ================================================== */
static void /* Procedure to add a new peer. */
name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything) NSR_Status
NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params)
{ {
struct UnresolvedSource *us, **i, *next; int slot, found;
NTP_Remote_Address address;
us = (struct UnresolvedSource *)anything; assert(initialised);
assert(us == resolving_source); #if 0
LOG(LOGS_INFO, LOGF_NtpSources, "IP=%08lx port=%d", (unsigned long) remote_addr->ip_addr, remote_addr->port);
#endif
switch (status) { /* Find empty bin & check that we don't have the address already */
case DNS_TryAgain: find_slot(remote_addr, &slot, &found);
break; if (found) {
case DNS_Success: return NSR_AlreadyInUse;
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(ip_addr));
address.ip_addr = *ip_addr;
address.port = us->port;
NSR_AddSource(&address, us->type, &us->params);
break;
case DNS_Failure:
LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name);
break;
default:
assert(0);
}
next = us->next;
if (status != DNS_TryAgain) {
/* Remove the source from the list */
for (i = &unresolved_sources; *i; i = &(*i)->next) {
if (*i == us) {
*i = us->next;
Free(us->name);
Free(us);
break;
}
}
}
resolving_source = next;
if (next) {
/* Continue with the next source in the list */
DEBUG_LOG(LOGF_NtpSources, "resolving %s", next->name);
DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next);
} else { } else {
/* This was the last source in the list. If some sources couldn't if (n_sources == MAX_SOURCES) {
be resolved, try again in exponentially increasing interval. */ return NSR_TooManySources;
if (unresolved_sources) {
if (resolving_interval < MIN_RESOLVE_INTERVAL)
resolving_interval = MIN_RESOLVE_INTERVAL;
else if (resolving_interval < MAX_RESOLVE_INTERVAL)
resolving_interval++;
resolving_id = SCH_AddTimeoutByDelay(RESOLVE_INTERVAL_UNIT *
(1 << resolving_interval), resolve_sources, NULL);
} else { } else {
resolving_interval = 0; 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 */
return NSR_Success;
} }
/* This round of resolving is done */
if (resolving_end_handler)
(resolving_end_handler)();
} }
} }
/* ================================================== */ /* ================================================== */
static void
resolve_sources(void *arg)
{
struct UnresolvedSource *us;
assert(!resolving_source);
DNS_Reload();
/* Start with the first source in the list, name_resolve_handler
will iterate over the rest */
us = unresolved_sources;
resolving_source = us;
DEBUG_LOG(LOGF_NtpSources, "resolving %s", us->name);
DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us);
}
/* ================================================== */
/* Procedure to add a new server or peer source, but instead of an IP address
only a name is provided */
void
NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params)
{
struct UnresolvedSource *us, **i;
us = MallocNew(struct UnresolvedSource);
us->name = name;
us->port = port;
us->type = type;
us->params = *params;
us->next = NULL;
for (i = &unresolved_sources; *i; i = &(*i)->next)
;
*i = us;
}
/* ================================================== */
void
NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
{
resolving_end_handler = handler;
}
/* ================================================== */
void
NSR_ResolveSources(void)
{
/* Try to resolve unresolved sources now */
if (unresolved_sources) {
/* Make sure no resolving is currently running */
if (!resolving_source) {
if (resolving_interval) {
SCH_RemoveTimeout(resolving_id);
resolving_interval--;
}
resolve_sources(NULL);
}
} else {
/* No unresolved sources, we are done */
if (resolving_end_handler)
(resolving_end_handler)();
}
}
/* ================================================== */
void NSR_StartSources(void)
{
int i;
for (i = 0; i < N_RECORDS; i++) {
if (!records[i].remote_addr)
continue;
NCR_StartInstance(records[i].data);
}
}
/* ================================================== */
void NSR_AutoStartSources(void)
{
auto_start_sources = 1;
}
/* ================================================== */
/* Procedure to remove a source. We don't bother whether the port /* Procedure to remove a source. We don't bother whether the port
address is matched - we're only interested in removing a record for address is matched - we're only interested in removing a record for
the right IP address. Thus the caller can specify the port number the right IP address. Thus the caller can specify the port number
@@ -390,75 +222,60 @@ void NSR_AutoStartSources(void)
NSR_Status NSR_Status
NSR_RemoveSource(NTP_Remote_Address *remote_addr) NSR_RemoveSource(NTP_Remote_Address *remote_addr)
{ {
int i, slot, found; int slot, found;
SourceRecord temp_records[N_RECORDS];
assert(initialised); assert(initialised);
find_slot(remote_addr, &slot, &found); find_slot(remote_addr, &slot, &found);
if (!found) { if (!found) {
return NSR_NoSuchSource; return NSR_NoSuchSource;
} else {
n_sources--;
records[slot].in_use = 0;
NCR_DestroyInstance(records[slot].data);
return NSR_Success;
} }
n_sources--;
records[slot].remote_addr = NULL;
NCR_DestroyInstance(records[slot].data);
/* Rehash the table to make sure there are no broken probe sequences.
This is costly, but it's not expected to happen frequently. */
memcpy(temp_records, records, sizeof (records));
for (i = 0; i < N_RECORDS; i++) {
records[i].remote_addr = NULL;
}
for (i = 0; i < N_RECORDS; i++) {
if (!temp_records[i].remote_addr)
continue;
find_slot(temp_records[i].remote_addr, &slot, &found);
assert(!found);
records[slot].remote_addr = temp_records[i].remote_addr;
records[slot].data = temp_records[i].data;
}
return NSR_Success;
} }
/* ================================================== */ /* ================================================== */
/* This routine is called by ntp_io when a new packet arrives off the network.*/
void void
NSR_RemoveAllSources(void) NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr)
{ {
int i; int slot, found;
for (i = 0; i < N_RECORDS; i++) { assert(initialised);
if (!records[i].remote_addr)
continue; #if 0
NCR_DestroyInstance(records[i].data); LOG(LOGS_INFO, LOGF_NtpSources, "from (%s,%d) at %s",
records[i].remote_addr = NULL; UTI_IPToDottedQuad(remote_addr->ip_addr),
remote_addr->port, UTI_TimevalToString(now));
#endif
find_slot(remote_addr, &slot, &found);
if (found == 2) { /* Must match IP address AND port number */
NCR_ProcessNoauthKnown(message, now, records[slot].data);
} else {
NCR_ProcessNoauthUnknown(message, now, remote_addr);
} }
} }
/* ================================================== */ /* ================================================== */
/* This routine is called by ntp_io when a new packet arrives off the network, /* This routine is called by ntp_io when a new packet with an authentication tail arrives off the network */
possibly with an authentication tail */
void void
NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length) NSR_ProcessAuthenticatedReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr)
{ {
int slot, found; int slot, found;
assert(initialised); assert(initialised);
find_slot(remote_addr, &slot, &found); find_slot(remote_addr, &slot, &found);
if (found == 2) { /* Must match IP address AND port number */ if (found == 2) {
NCR_ProcessKnown(message, now, now_err, records[slot].data, NCR_ProcessAuthKnown(message, now, records[slot].data);
local_addr->sock_fd, length);
} else { } else {
NCR_ProcessUnknown(message, now, now_err, remote_addr, local_addr, length); NCR_ProcessAuthUnknown(message, now, remote_addr);
} }
} }
@@ -468,104 +285,80 @@ static void
slew_sources(struct timeval *raw, slew_sources(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *anything) void *anything)
{ {
int i; int i;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) { if (records[i].in_use) {
if (change_type == LCL_ChangeUnknownStep) { #if 0
NCR_ResetInstance(records[i].data); LOG(LOGS_INFO, LOGF_Sources, "IP=%s dfreq=%f doff=%f",
} else { UTI_IPToDottedQuad(records[i].remote_addr.ip_addr), dfreq, doffset);
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset); #endif
}
NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
} }
} }
} }
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address) NSR_TakeSourcesOnline(unsigned long mask, unsigned long address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
NSR_ResolveSources();
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) { if (records[i].in_use) {
if (address->family == IPADDR_UNSPEC || ip = records[i].remote_addr.ip_addr;
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) { if ((ip & mask) == address) {
any = 1; any = 1;
NCR_TakeSourceOnline(records[i].data); NCR_TakeSourceOnline(records[i].data);
} }
} }
} }
if (address->family == IPADDR_UNSPEC) {
struct UnresolvedSource *us;
for (us = unresolved_sources; us; us = us->next) {
any = 1;
us->params.online = 1;
}
}
return any; return any;
} }
/* ================================================== */ /* ================================================== */
int int
NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address) NSR_TakeSourcesOffline(unsigned long mask, unsigned long address)
{ {
int i, any, syncpeer; int i;
int any;
unsigned long ip;
any = 0; any = 0;
syncpeer = -1;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) { if (records[i].in_use) {
if (address->family == IPADDR_UNSPEC || ip = records[i].remote_addr.ip_addr;
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) { if ((ip & mask) == address) {
any = 1; any = 1;
if (NCR_IsSyncPeer(records[i].data)) {
syncpeer = i;
continue;
}
NCR_TakeSourceOffline(records[i].data); NCR_TakeSourceOffline(records[i].data);
} }
} }
} }
/* Take sync peer offline as last to avoid reference switching */
if (syncpeer >= 0) {
NCR_TakeSourceOffline(records[syncpeer].data);
}
if (address->family == IPADDR_UNSPEC) {
struct UnresolvedSource *us;
for (us = unresolved_sources; us; us = us->next) {
any = 1;
us->params.online = 0;
}
}
return any; return any;
} }
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMinpoll(IPAddr *address, int new_minpoll) NSR_ModifyMinpoll(unsigned long address, int new_minpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = *address; addr.ip_addr = address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -580,11 +373,11 @@ NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll) NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = *address; addr.ip_addr = address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -599,11 +392,11 @@ NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay) NSR_ModifyMaxdelay(unsigned long address, double new_max_delay)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = *address; addr.ip_addr = address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -618,11 +411,11 @@ NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
/* ================================================== */ /* ================================================== */
int int
NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio) NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio)
{ {
int slot, found; int slot, found;
NTP_Remote_Address addr; NTP_Remote_Address addr;
addr.ip_addr = *address; addr.ip_addr = address;
addr.port = 0; addr.port = 0;
find_slot(&addr, &slot, &found); find_slot(&addr, &slot, &found);
@@ -636,75 +429,19 @@ NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
/* ================================================== */ /* ================================================== */
int
NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_dev_ratio)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyMaxdelaydevratio(records[slot].data, new_max_delay_dev_ratio);
return 1;
}
}
/* ================================================== */
int
NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyMinstratum(records[slot].data, new_min_stratum);
return 1;
}
}
/* ================================================== */
int
NSR_ModifyPolltarget(IPAddr *address, int new_poll_target)
{
int slot, found;
NTP_Remote_Address addr;
addr.ip_addr = *address;
addr.port = 0;
find_slot(&addr, &slot, &found);
if (found == 0) {
return 0;
} else {
NCR_ModifyPolltarget(records[slot].data, new_poll_target);
return 1;
}
}
/* ================================================== */
int int
NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
IPAddr *mask, IPAddr *address) unsigned long mask, unsigned long address)
{ {
int i; int i;
int any; int any;
unsigned long ip;
any = 0; any = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) { if (records[i].in_use) {
if (address->family == IPADDR_UNSPEC || ip = records[i].remote_addr.ip_addr;
!UTI_CompareIPs(&records[i].remote_addr->ip_addr, address, mask)) { if ((ip & mask) == address) {
any = 1; any = 1;
NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples); NCR_InitiateSampleBurst(records[i].data, n_good_samples, n_total_samples);
} }
@@ -742,7 +479,6 @@ void
NSR_GetActivityReport(RPT_ActivityReport *report) NSR_GetActivityReport(RPT_ActivityReport *report)
{ {
int i; int i;
struct UnresolvedSource *us;
report->online = 0; report->online = 0;
report->offline = 0; report->offline = 0;
@@ -750,17 +486,12 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
report->burst_offline = 0; report->burst_offline = 0;
for (i=0; i<N_RECORDS; i++) { for (i=0; i<N_RECORDS; i++) {
if (records[i].remote_addr) { if (records[i].in_use) {
NCR_IncrementActivityCounters(records[i].data, &report->online, &report->offline, NCR_IncrementActivityCounters(records[i].data, &report->online, &report->offline,
&report->burst_online, &report->burst_offline); &report->burst_online, &report->burst_offline);
} }
} }
return;
report->unresolved = 0;
for (us = unresolved_sources; us; us = us->next) {
report->unresolved++;
}
} }

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/ntp_sources.h,v 1.12 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2002 * Copyright (C) Richard P. Curnow 1997-2002
* Copyright (C) Miroslav Lichvar 2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -42,43 +45,26 @@
typedef enum { typedef enum {
NSR_Success, /* Operation successful */ NSR_Success, /* Operation successful */
NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */ NSR_NoSuchSource, /* Remove - attempt to remove a source that is not known */
NSR_AlreadyInUse, /* AddSource - attempt to add a source that is already known */ NSR_AlreadyInUse, /* AddServer, AddPeer - attempt to add a source that is already known */
NSR_TooManySources, /* AddSource - too many sources already present */ NSR_TooManySources /* AddServer, AddPeer - too many sources already present */
NSR_InvalidAF /* AddSource - attempt to add a source with invalid address family */
} NSR_Status; } NSR_Status;
/* Procedure to add a new server or peer source. */ /* Procedure to add a new server source (to which this machine will be
extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params); a client) */
extern NSR_Status NSR_AddServer(NTP_Remote_Address *remote_addr, SourceParameters *params);
/* Procedure to add a new server or peer source with currently unknown address. /* Procedure to add a new peer source. We will use symmetric active
The name will be periodically resolved in exponentially increasing intervals mode packets when communicating with this source */
until it succeeds or fails with a non-temporary error. */ extern NSR_Status NSR_AddPeer(NTP_Remote_Address *remote_addr, SourceParameters *params);
extern void NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params);
/* Function type for handlers to be called back when an attempt
* (possibly unsuccessful) to resolve unresolved sources ends */
typedef void (*NSR_SourceResolvingEndHandler)(void);
/* Set the handler, or NULL to disable the notification */
extern void NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler);
/* Procedure to start resolving unresolved sources */
extern void NSR_ResolveSources(void);
/* Procedure to start all sources */
extern void NSR_StartSources(void);
/* Start new sources automatically */
extern void NSR_AutoStartSources(void);
/* Procedure to remove a source */ /* Procedure to remove a source */
extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr); extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr);
/* Procedure to remove all sources */
extern void NSR_RemoveAllSources(void);
/* This routine is called by ntp_io when a new packet arrives off the network */ /* This routine is called by ntp_io when a new packet arrives off the network */
extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, double now_err, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length); extern void NSR_ProcessReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* This routine is called by ntp_io when a new packet with an authentication tail arrives off the network */
extern void NSR_ProcessAuthenticatedReceive(NTP_Packet *message, struct timeval *now, NTP_Remote_Address *remote_addr);
/* Initialisation function */ /* Initialisation function */
extern void NSR_Initialise(void); extern void NSR_Initialise(void);
@@ -89,28 +75,22 @@ extern void NSR_Finalise(void);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set online again. Returns a match a particular subnet should be set online again. Returns a
flag indicating whether any hosts matched the address */ flag indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address); extern int NSR_TakeSourcesOnline(unsigned long mask, unsigned long address);
/* This routine is used to indicate that sources whose IP addresses /* This routine is used to indicate that sources whose IP addresses
match a particular subnet should be set offline. Returns a flag match a particular subnet should be set offline. Returns a flag
indicating whether any hosts matched the address */ indicating whether any hosts matched the address */
extern int NSR_TakeSourcesOffline(IPAddr *mask, IPAddr *address); extern int NSR_TakeSourcesOffline(unsigned long mask, unsigned long address);
extern int NSR_ModifyMinpoll(IPAddr *address, int new_minpoll); extern int NSR_ModifyMinpoll(unsigned long address, int new_minpoll);
extern int NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll); extern int NSR_ModifyMaxpoll(unsigned long address, int new_maxpoll);
extern int NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay); extern int NSR_ModifyMaxdelay(unsigned long address, double new_max_delay);
extern int NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio); extern int NSR_ModifyMaxdelayratio(unsigned long address, double new_max_delay_ratio);
extern int NSR_ModifyMaxdelaydevratio(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_ModifyMinstratum(IPAddr *address, int new_min_stratum);
extern int NSR_ModifyPolltarget(IPAddr *address, int new_poll_target);
extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAddr *mask, IPAddr *address);
extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now); extern void NSR_ReportSource(RPT_SourceReport *report, struct timeval *now);

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/pktlength.c,v 1.12 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,8 +30,6 @@
integer endianness within the structures. integer endianness within the structures.
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "util.h" #include "util.h"
@@ -35,8 +37,8 @@
/* ================================================== */ /* ================================================== */
static int int
command_unpadded_length(CMD_Request *r) PKL_CommandLength(CMD_Request *r)
{ {
int type; int type;
type = ntohs(r->command); type = ntohs(r->command);
@@ -63,8 +65,6 @@ command_unpadded_length(CMD_Request *r)
return offsetof(CMD_Request, data.modify_maxdelay.EOR); return offsetof(CMD_Request, data.modify_maxdelay.EOR);
case REQ_MODIFY_MAXDELAYRATIO: case REQ_MODIFY_MAXDELAYRATIO:
return offsetof(CMD_Request, data.modify_maxdelayratio.EOR); return offsetof(CMD_Request, data.modify_maxdelayratio.EOR);
case REQ_MODIFY_MAXDELAYDEVRATIO:
return offsetof(CMD_Request, data.modify_maxdelaydevratio.EOR);
case REQ_MODIFY_MAXUPDATESKEW: case REQ_MODIFY_MAXUPDATESKEW:
return offsetof(CMD_Request, data.modify_maxupdateskew.EOR); return offsetof(CMD_Request, data.modify_maxupdateskew.EOR);
case REQ_LOGON : case REQ_LOGON :
@@ -124,9 +124,19 @@ command_unpadded_length(CMD_Request *r)
case REQ_CYCLELOGS : case REQ_CYCLELOGS :
return offsetof(CMD_Request, data.cyclelogs.EOR); return offsetof(CMD_Request, data.cyclelogs.EOR);
case REQ_SUBNETS_ACCESSED : case REQ_SUBNETS_ACCESSED :
{
unsigned long ns;
ns = ntohl(r->data.subnets_accessed.n_subnets);
return (offsetof(CMD_Request, data.subnets_accessed.subnets) +
ns * sizeof(REQ_SubnetsAccessed_Subnet));
}
case REQ_CLIENT_ACCESSES: case REQ_CLIENT_ACCESSES:
/* No longer supported */ {
return 0; unsigned long nc;
nc = ntohl(r->data.client_accesses.n_clients);
return (offsetof(CMD_Request, data.client_accesses.client_ips) +
nc * sizeof(unsigned long));
}
case REQ_CLIENT_ACCESSES_BY_INDEX: case REQ_CLIENT_ACCESSES_BY_INDEX:
return offsetof(CMD_Request, data.client_accesses_by_index.EOR); return offsetof(CMD_Request, data.client_accesses_by_index.EOR);
case REQ_MANUAL_LIST: case REQ_MANUAL_LIST:
@@ -137,14 +147,6 @@ command_unpadded_length(CMD_Request *r)
return offsetof(CMD_Request, data.make_step.EOR); return offsetof(CMD_Request, data.make_step.EOR);
case REQ_ACTIVITY: case REQ_ACTIVITY:
return offsetof(CMD_Request, data.activity.EOR); return offsetof(CMD_Request, data.activity.EOR);
case REQ_RESELECT:
return offsetof(CMD_Request, data.reselect.EOR);
case REQ_RESELECTDISTANCE:
return offsetof(CMD_Request, data.reselect_distance.EOR);
case REQ_MODIFY_MINSTRATUM:
return offsetof(CMD_Request, data.modify_minstratum.EOR);
case REQ_MODIFY_POLLTARGET:
return offsetof(CMD_Request, data.modify_polltarget.EOR);
default: default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */ /* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0); assert(0);
@@ -157,149 +159,6 @@ command_unpadded_length(CMD_Request *r)
} }
/* ================================================== */
int
PKL_CommandLength(CMD_Request *r)
{
int command_length;
command_length = command_unpadded_length(r);
if (!command_length)
return 0;
return command_length + PKL_CommandPaddingLength(r);
}
/* ================================================== */
#define PADDING_LENGTH_(request_length, reply_length) \
((request_length) < (reply_length) ? (reply_length) - (request_length) : 0)
#define PADDING_LENGTH(request_data, reply_data) \
PADDING_LENGTH_(offsetof(CMD_Request, request_data), offsetof(CMD_Reply, reply_data))
int
PKL_CommandPaddingLength(CMD_Request *r)
{
int type;
if (r->version < PROTO_VERSION_PADDING)
return 0;
type = ntohs(r->command);
if (type < 0 || type >= N_REQUEST_TYPES)
return 0;
switch (type) {
case REQ_NULL:
return PADDING_LENGTH(data, data.null.EOR);
case REQ_ONLINE:
return PADDING_LENGTH(data.online.EOR, data.null.EOR);
case REQ_OFFLINE:
return PADDING_LENGTH(data.offline.EOR, data.null.EOR);
case REQ_BURST:
return PADDING_LENGTH(data.burst.EOR, data.null.EOR);
case REQ_MODIFY_MINPOLL:
return PADDING_LENGTH(data.modify_minpoll.EOR, data.null.EOR);
case REQ_MODIFY_MAXPOLL:
return PADDING_LENGTH(data.modify_maxpoll.EOR, data.null.EOR);
case REQ_DUMP:
return PADDING_LENGTH(data.dump.EOR, data.null.EOR);
case REQ_MODIFY_MAXDELAY:
return PADDING_LENGTH(data.modify_maxdelay.EOR, data.null.EOR);
case REQ_MODIFY_MAXDELAYRATIO:
return PADDING_LENGTH(data.modify_maxdelayratio.EOR, data.null.EOR);
case REQ_MODIFY_MAXDELAYDEVRATIO:
return PADDING_LENGTH(data.modify_maxdelaydevratio.EOR, data.null.EOR);
case REQ_MODIFY_MAXUPDATESKEW:
return PADDING_LENGTH(data.modify_maxupdateskew.EOR, data.null.EOR);
case REQ_LOGON:
return PADDING_LENGTH(data.logon.EOR, data.null.EOR);
case REQ_SETTIME:
return PADDING_LENGTH(data.settime.EOR, data.manual_timestamp.EOR);
case REQ_LOCAL:
return PADDING_LENGTH(data.local.EOR, data.null.EOR);
case REQ_MANUAL:
return PADDING_LENGTH(data.manual.EOR, data.null.EOR);
case REQ_N_SOURCES:
return PADDING_LENGTH(data.n_sources.EOR, data.n_sources.EOR);
case REQ_SOURCE_DATA:
return PADDING_LENGTH(data.source_data.EOR, data.source_data.EOR);
case REQ_REKEY:
return PADDING_LENGTH(data.rekey.EOR, data.null.EOR);
case REQ_ALLOW:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_ALLOWALL:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_DENY:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_DENYALL:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_CMDALLOW:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_CMDALLOWALL:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_CMDDENY:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_CMDDENYALL:
return PADDING_LENGTH(data.allow_deny.EOR, data.null.EOR);
case REQ_ACCHECK:
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
case REQ_CMDACCHECK:
return PADDING_LENGTH(data.ac_check.EOR, data.null.EOR);
case REQ_ADD_SERVER:
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
case REQ_ADD_PEER:
return PADDING_LENGTH(data.ntp_source.EOR, data.null.EOR);
case REQ_DEL_SOURCE:
return PADDING_LENGTH(data.del_source.EOR, data.null.EOR);
case REQ_WRITERTC:
return PADDING_LENGTH(data.writertc.EOR, data.null.EOR);
case REQ_DFREQ:
return PADDING_LENGTH(data.dfreq.EOR, data.null.EOR);
case REQ_DOFFSET:
return PADDING_LENGTH(data.doffset.EOR, data.null.EOR);
case REQ_TRACKING:
return PADDING_LENGTH(data.tracking.EOR, data.tracking.EOR);
case REQ_SOURCESTATS:
return PADDING_LENGTH(data.sourcestats.EOR, data.sourcestats.EOR);
case REQ_RTCREPORT:
return PADDING_LENGTH(data.rtcreport.EOR, data.rtc.EOR);
case REQ_TRIMRTC:
return PADDING_LENGTH(data.trimrtc.EOR, data.null.EOR);
case REQ_CYCLELOGS:
return PADDING_LENGTH(data.cyclelogs.EOR, data.null.EOR);
case REQ_SUBNETS_ACCESSED:
case REQ_CLIENT_ACCESSES:
/* No longer supported */
return 0;
case REQ_CLIENT_ACCESSES_BY_INDEX:
return PADDING_LENGTH(data.client_accesses_by_index.EOR, data.client_accesses_by_index.EOR);
case REQ_MANUAL_LIST:
return PADDING_LENGTH(data.manual_list.EOR, data.manual_list.EOR);
case REQ_MANUAL_DELETE:
return PADDING_LENGTH(data.manual_delete.EOR, data.null.EOR);
case REQ_MAKESTEP:
return PADDING_LENGTH(data.make_step.EOR, data.null.EOR);
case REQ_ACTIVITY:
return PADDING_LENGTH(data.activity.EOR, data.activity.EOR);
case REQ_RESELECT:
return PADDING_LENGTH(data.reselect.EOR, data.null.EOR);
case REQ_RESELECTDISTANCE:
return PADDING_LENGTH(data.reselect_distance.EOR, data.null.EOR);
case REQ_MODIFY_MINSTRATUM:
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
case REQ_MODIFY_POLLTARGET:
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0);
return 0;
}
}
/* ================================================== */ /* ================================================== */
int int
@@ -327,15 +186,29 @@ PKL_ReplyLength(CMD_Reply *r)
case RPY_RTC: case RPY_RTC:
return offsetof(CMD_Reply, data.rtc.EOR); return offsetof(CMD_Reply, data.rtc.EOR);
case RPY_SUBNETS_ACCESSED : case RPY_SUBNETS_ACCESSED :
{
unsigned long ns = ntohl(r->data.subnets_accessed.n_subnets);
if (r->status == htons(STT_SUCCESS)) {
return (offsetof(CMD_Reply, data.subnets_accessed.subnets) +
ns * sizeof(RPY_SubnetsAccessed_Subnet));
} else {
return offsetof(CMD_Reply, data);
}
}
case RPY_CLIENT_ACCESSES: case RPY_CLIENT_ACCESSES:
/* No longer supported */ {
return 0; unsigned long nc = ntohl(r->data.client_accesses.n_clients);
if (r->status == htons(STT_SUCCESS)) {
return (offsetof(CMD_Reply, data.client_accesses.clients) +
nc * sizeof(RPY_ClientAccesses_Client));
} else {
return offsetof(CMD_Reply, data);
}
}
case RPY_CLIENT_ACCESSES_BY_INDEX: case RPY_CLIENT_ACCESSES_BY_INDEX:
{ {
unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients); unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
if (r->status == htons(STT_SUCCESS)) { if (r->status == htons(STT_SUCCESS)) {
if (nc > MAX_CLIENT_ACCESSES)
return 0;
return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) + return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
nc * sizeof(RPY_ClientAccesses_Client)); nc * sizeof(RPY_ClientAccesses_Client));
} else { } else {
@@ -345,8 +218,6 @@ PKL_ReplyLength(CMD_Reply *r)
case RPY_MANUAL_LIST: case RPY_MANUAL_LIST:
{ {
unsigned long ns = ntohl(r->data.manual_list.n_samples); unsigned long ns = ntohl(r->data.manual_list.n_samples);
if (ns > MAX_MANUAL_LIST_SAMPLES)
return 0;
if (r->status == htons(STT_SUCCESS)) { if (r->status == htons(STT_SUCCESS)) {
return (offsetof(CMD_Reply, data.manual_list.samples) + return (offsetof(CMD_Reply, data.manual_list.samples) +
ns * sizeof(RPY_ManualListSample)); ns * sizeof(RPY_ManualListSample));

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/pktlength.h,v 1.4 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -33,8 +37,6 @@
extern int PKL_CommandLength(CMD_Request *r); extern int PKL_CommandLength(CMD_Request *r);
extern int PKL_CommandPaddingLength(CMD_Request *r);
extern int PKL_ReplyLength(CMD_Reply *r); extern int PKL_ReplyLength(CMD_Reply *r);
#endif /* GOT_PKTLENGTH_H */ #endif /* GOT_PKTLENGTH_H */

View File

@@ -1,929 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2009-2011, 2013-2014
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Routines implementing reference clocks.
*/
#include "config.h"
#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 "regress.h"
#include "sched.h"
/* list of refclock drivers */
extern RefclockDriver RCL_SHM_driver;
extern RefclockDriver RCL_SOCK_driver;
extern RefclockDriver RCL_PPS_driver;
extern RefclockDriver RCL_PHC_driver;
struct FilterSample {
double offset;
double dispersion;
struct timeval sample_time;
};
struct MedianFilter {
int length;
int index;
int used;
int last;
int avg_var_n;
double avg_var;
double max_var;
struct FilterSample *samples;
int *selected;
double *x_data;
double *y_data;
double *w_data;
};
struct RCL_Instance_Record {
RefclockDriver *driver;
void *data;
char *driver_parameter;
int driver_parameter_length;
int driver_poll;
int driver_polled;
int poll;
int leap_status;
int pps_rate;
int pps_active;
struct MedianFilter filter;
uint32_t ref_id;
uint32_t lock_ref;
double offset;
double delay;
double precision;
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;
static LOG_FileID logfileid;
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 doffset, LCL_ChangeType change_type, void *anything);
static void add_dispersion(double dispersion, void *anything);
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
static void filter_init(struct MedianFilter *filter, int length, double max_dispersion);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion);
static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
static int filter_select_samples(struct MedianFilter *filter);
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);
static void filter_add_dispersion(struct MedianFilter *filter, double dispersion);
void
RCL_Initialise(void)
{
CNF_AddRefclocks();
if (n_sources > 0) {
LCL_AddParameterChangeHandler(slew_samples, NULL);
LCL_AddDispersionNotifyHandler(add_dispersion, NULL);
}
logfileid = CNF_GetLogRefclocks() ? LOG_FileOpen("refclocks",
" Date (UTC) Time Refid DP L P Raw offset Cooked offset Disp.")
: -1;
}
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);
LCL_RemoveDispersionNotifyHandler(add_dispersion, NULL);
}
}
int
RCL_AddRefclock(RefclockParameters *params)
{
int pps_source = 0;
RCL_Instance inst = &refclocks[n_sources];
if (n_sources == MAX_RCL_SOURCES)
return 0;
if (strcmp(params->driver_name, "SHM") == 0) {
inst->driver = &RCL_SHM_driver;
inst->precision = 1e-6;
} else if (strcmp(params->driver_name, "SOCK") == 0) {
inst->driver = &RCL_SOCK_driver;
inst->precision = 1e-9;
pps_source = 1;
} else if (strcmp(params->driver_name, "PPS") == 0) {
inst->driver = &RCL_PPS_driver;
inst->precision = 1e-9;
pps_source = 1;
} else if (strcmp(params->driver_name, "PHC") == 0) {
inst->driver = &RCL_PHC_driver;
inst->precision = 1e-9;
} 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->driver_polled = 0;
inst->leap_status = LEAP_Normal;
inst->pps_rate = params->pps_rate;
inst->pps_active = 0;
inst->lock_ref = params->lock_ref_id;
inst->offset = params->offset;
inst->delay = params->delay;
if (params->precision > 0.0)
inst->precision = params->precision;
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 (params->ref_id)
inst->ref_id = params->ref_id;
else {
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
snprintf((char *)ref, 5, "%3.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->poll) {
int max_samples;
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
max_samples = 1 << (inst->poll - inst->driver_poll);
if (max_samples < params->filter_length) {
if (max_samples < 4) {
LOG(LOGS_WARN, LOGF_Refclock, "Setting filter length for %s to %d",
UTI_RefidToString(inst->ref_id), max_samples);
}
params->filter_length = max_samples;
}
}
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, params->max_dispersion);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
DEBUG_LOG(LOGF_Refclock, "refclock %s added poll=%d dpoll=%d filter=%d",
params->driver_name, inst->poll, inst->driver_poll, params->filter_length);
n_sources++;
Free(params->driver_name);
return 1;
}
void
RCL_StartRefclocks(void)
{
int i, j;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
SRC_SetSelectable(inst->source);
SRC_SetActive(inst->source);
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;
}
}
void
RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
{
int i;
uint32_t 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, int leap)
{
double correction, dispersion;
struct timeval cooked_time;
LCL_GetOffsetCorrection(sample_time, &correction, &dispersion);
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
dispersion += instance->precision;
if (!valid_sample_time(instance, sample_time))
return 0;
filter_add_sample(&instance->filter, &cooked_time, offset - correction + instance->offset, dispersion);
switch (leap) {
case LEAP_Normal:
case LEAP_InsertSecond:
case LEAP_DeleteSecond:
instance->leap_status = leap;
break;
default:
instance->leap_status = LEAP_Unsynchronised;
break;
}
instance->pps_active = 0;
log_sample(instance, &cooked_time, 0, 0, offset, offset - correction + instance->offset, dispersion);
/* for logging purposes */
if (!instance->driver->poll)
instance->driver_polled++;
return 1;
}
int
RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
{
double correction, dispersion, offset;
struct timeval cooked_time;
int rate;
NTP_Leap leap;
leap = LEAP_Normal;
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
dispersion += instance->precision;
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, ref_dispersion, shift;
if (!filter_get_last_sample(&refclocks[instance->lock_ref].filter,
&ref_sample_time, &ref_offset, &ref_dispersion)) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored no ref sample");
return 0;
}
ref_dispersion += filter_get_avg_sample_dispersion(&refclocks[instance->lock_ref].filter);
UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
if (fabs(sample_diff) >= 2.0 / rate) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored samplediff=%.9f",
sample_diff);
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) + ref_dispersion + dispersion >= 0.2 / rate) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored offdiff=%.9f refdisp=%.9f disp=%.9f",
ref_offset - offset, ref_dispersion, dispersion);
return 0;
}
leap = refclocks[instance->lock_ref].leap_status;
DEBUG_LOG(LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
second, offset, ref_offset - offset, sample_diff);
} else {
struct timeval ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
uint32_t ref_id;
/* 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) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored second=%.9f sync=%d dist=%.9f",
second, is_synchronised, distance);
/* Drop also all stored samples */
filter_reset(&instance->filter);
return 0;
}
}
filter_add_sample(&instance->filter, &cooked_time, offset, dispersion);
instance->leap_status = leap;
instance->pps_active = 1;
log_sample(instance, &cooked_time, 0, 1, offset + correction - instance->offset, offset, dispersion);
/* for logging purposes */
if (!instance->driver->poll)
instance->driver_polled++;
return 1;
}
static double
poll_interval(int poll)
{
if (poll >= 0)
return 1 << poll;
else
return 1.0 / (1 << -poll);
}
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 > poll_interval(instance->poll + 1)) {
DEBUG_LOG(LOGF_Refclock, "refclock sample not valid age=%.6f tv=%s",
diff, UTI_TimevalToString(tv));
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;
uint32_t 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_active && refclocks[i].lock_ref == -1)
return stratum - 1;
}
return 0;
}
static void
poll_timeout(void *arg)
{
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);
inst->driver_polled = 0;
if (sample_ok) {
if (inst->pps_active && inst->lock_ref == -1)
/* Handle special case when PPS is used with local stratum */
stratum = pps_stratum(inst, &sample_time);
else
stratum = 0;
SRC_UpdateReachability(inst->source, 1);
SRC_AccumulateSample(inst->source, &sample_time, offset,
inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
SRC_SelectSource(inst->source);
log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
} else {
SRC_UpdateReachability(inst->source, 0);
}
}
inst->timeout_id = SCH_AddTimeoutByDelay(poll_interval(poll), poll_timeout, arg);
}
static void
slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
int i;
for (i = 0; i < n_sources; i++) {
if (change_type == LCL_ChangeUnknownStep)
filter_reset(&refclocks[i].filter);
else
filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset);
}
}
static void
add_dispersion(double dispersion, void *anything)
{
int i;
for (i = 0; i < n_sources; i++)
filter_add_dispersion(&refclocks[i].filter, dispersion);
}
static void
log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
{
char sync_stats[4] = {'N', '+', '-', '?'};
if (logfileid == -1)
return;
if (!filtered) {
LOG_FileWrite(logfileid, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e %10.3e",
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,
dispersion);
} else {
LOG_FileWrite(logfileid, "%s.%06d %-5s - %1c - - %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
(int)sample_time->tv_usec,
UTI_RefidToString(instance->ref_id),
sync_stats[instance->leap_status],
cooked_offset,
dispersion);
}
}
static void
filter_init(struct MedianFilter *filter, int length, double max_dispersion)
{
if (length < 1)
length = 1;
filter->length = length;
filter->index = -1;
filter->used = 0;
filter->last = -1;
/* set first estimate to system precision */
filter->avg_var_n = 0;
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
filter->max_var = max_dispersion * max_dispersion;
filter->samples = MallocArray(struct FilterSample, filter->length);
filter->selected = MallocArray(int, filter->length);
filter->x_data = MallocArray(double, filter->length);
filter->y_data = MallocArray(double, filter->length);
filter->w_data = MallocArray(double, filter->length);
}
static void
filter_fini(struct MedianFilter *filter)
{
Free(filter->samples);
Free(filter->selected);
Free(filter->x_data);
Free(filter->y_data);
Free(filter->w_data);
}
static void
filter_reset(struct MedianFilter *filter)
{
filter->index = -1;
filter->used = 0;
}
static double
filter_get_avg_sample_dispersion(struct MedianFilter *filter)
{
return sqrt(filter->avg_var);
}
static void
filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion)
{
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;
filter->samples[filter->index].dispersion = dispersion;
DEBUG_LOG(LOGF_Refclock, "filter sample %d t=%s offset=%.9f dispersion=%.9f",
filter->index, UTI_TimevalToString(sample_time), offset, dispersion);
}
static int
filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
{
if (filter->last < 0)
return 0;
*sample_time = filter->samples[filter->last].sample_time;
*offset = filter->samples[filter->last].offset;
*dispersion = filter->samples[filter->last].dispersion;
return 1;
}
static const struct FilterSample *tmp_sorted_array;
static int
sample_compare(const void *a, const void *b)
{
const struct FilterSample *s1, *s2;
s1 = &tmp_sorted_array[*(int *)a];
s2 = &tmp_sorted_array[*(int *)b];
if (s1->offset < s2->offset)
return -1;
else if (s1->offset > s2->offset)
return 1;
return 0;
}
int
filter_select_samples(struct MedianFilter *filter)
{
int i, j, k, o, from, to, *selected;
double min_dispersion;
if (filter->used < 1)
return 0;
/* for lengths below 4 require full filter,
for 4 and above require at least 4 samples */
if ((filter->length < 4 && filter->used != filter->length) ||
(filter->length >= 4 && filter->used < 4))
return 0;
selected = filter->selected;
if (filter->used > 4) {
/* select samples with dispersion better than 1.5 * minimum */
for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
if (min_dispersion > filter->samples[i].dispersion)
min_dispersion = filter->samples[i].dispersion;
}
for (i = j = 0; i < filter->used; i++) {
if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
selected[j++] = i;
}
} else {
j = 0;
}
if (j < 4) {
/* select all samples */
for (j = 0; j < filter->used; j++)
selected[j] = j;
}
/* and sort their indices by offset */
tmp_sorted_array = filter->samples;
qsort(selected, j, sizeof (int), sample_compare);
/* select 60 percent of the samples closest to the median */
if (j > 2) {
from = j / 5;
if (from < 1)
from = 1;
to = j - from;
} else {
from = 0;
to = j;
}
/* mark unused samples and sort the rest from oldest to newest */
o = filter->used - filter->index - 1;
for (i = 0; i < from; i++)
selected[i] = -1;
for (; i < to; i++)
selected[i] = (selected[i] + o) % filter->used;
for (; i < filter->used; i++)
selected[i] = -1;
for (i = from; i < to; i++) {
j = selected[i];
selected[i] = -1;
while (j != -1 && selected[j] != j) {
k = selected[j];
selected[j] = j;
j = k;
}
}
for (i = j = 0, k = -1; i < filter->used; i++) {
if (selected[i] != -1)
selected[j++] = (selected[i] + filter->used - o) % filter->used;
}
return j;
}
static int
filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
{
struct FilterSample *s, *ls;
int i, n, dof;
double x, y, d, e, var, prev_avg_var;
n = filter_select_samples(filter);
if (n < 1)
return 0;
ls = &filter->samples[filter->selected[n - 1]];
/* prepare data */
for (i = 0; i < n; i++) {
s = &filter->samples[filter->selected[i]];
UTI_DiffTimevalsToDouble(&filter->x_data[i], &s->sample_time, &ls->sample_time);
filter->y_data[i] = s->offset;
filter->w_data[i] = s->dispersion;
}
/* mean offset, sample time and sample dispersion */
for (i = 0, x = y = e = 0.0; i < n; i++) {
x += filter->x_data[i];
y += filter->y_data[i];
e += filter->w_data[i];
}
x /= n;
y /= n;
e /= n;
if (n >= 4) {
double b0, b1, s2, sb0, sb1;
/* set y axis to the mean sample time */
for (i = 0; i < n; i++)
filter->x_data[i] -= x;
/* make a linear fit and use the estimated standard deviation of intercept
as dispersion */
RGR_WeightedRegression(filter->x_data, filter->y_data, filter->w_data, n,
&b0, &b1, &s2, &sb0, &sb1);
var = s2;
d = sb0;
dof = n - 2;
} else if (n >= 2) {
for (i = 0, d = 0.0; i < n; i++)
d += (filter->y_data[i] - y) * (filter->y_data[i] - y);
var = d / (n - 1);
d = sqrt(var);
dof = n - 1;
} else {
var = filter->avg_var;
d = sqrt(var);
dof = 1;
}
/* avoid having zero dispersion */
if (var < 1e-20) {
var = 1e-20;
d = sqrt(var);
}
/* drop the sample if variance is larger than allowed maximum */
if (filter->max_var > 0.0 && var > filter->max_var) {
DEBUG_LOG(LOGF_Refclock, "filter dispersion too large disp=%.9f max=%.9f",
sqrt(var), sqrt(filter->max_var));
return 0;
}
prev_avg_var = filter->avg_var;
/* update exponential moving average of the variance */
if (filter->avg_var_n > 50) {
filter->avg_var += dof / (dof + 50.0) * (var - filter->avg_var);
} else {
filter->avg_var = (filter->avg_var * filter->avg_var_n + var * dof) /
(dof + filter->avg_var_n);
if (filter->avg_var_n == 0)
prev_avg_var = filter->avg_var;
filter->avg_var_n += dof;
}
/* reduce noise in sourcestats weights by using the long-term average
instead of the estimated variance if it's not significantly lower */
if (var * dof / RGR_GetChi2Coef(dof) < prev_avg_var)
d = sqrt(filter->avg_var) * d / sqrt(var);
if (d < e)
d = e;
UTI_AddDoubleToTimeval(&ls->sample_time, x, sample_time);
*offset = y;
*dispersion = d;
filter_reset(filter);
return 1;
}
static void
filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset)
{
int i;
double delta_time;
struct timeval *sample;
for (i = 0; i < filter->used; i++) {
sample = &filter->samples[i].sample_time;
UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
filter->samples[i].offset -= delta_time;
}
}
static void
filter_add_dispersion(struct MedianFilter *filter, double dispersion)
{
int i;
for (i = 0; i < filter->used; i++) {
filter->samples[i].dispersion += dispersion;
}
}

View File

@@ -1,72 +0,0 @@
/*
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;
char *driver_parameter;
int driver_poll;
int poll;
int filter_length;
int pps_rate;
uint32_t ref_id;
uint32_t lock_ref_id;
double offset;
double delay;
double precision;
double max_dispersion;
SRC_SelectOption sel_option;
} 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_ReportSource(RPT_SourceReport *report, struct timeval *now);
/* 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, int leap);
extern int RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second);
#endif

View File

@@ -1,193 +0,0 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2013
*
* 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.
*
**********************************************************************
=======================================================================
PTP hardware clock (PHC) refclock driver.
*/
#include "config.h"
#include "refclock.h"
#ifdef FEAT_PHC
#include "sysincl.h"
#include <linux/ptp_clock.h>
#include "refclock.h"
#include "logging.h"
#include "util.h"
/* From linux/include/linux/posix-timers.h */
#define CPUCLOCK_MAX 3
#define CLOCKFD CPUCLOCK_MAX
#define CLOCKFD_MASK (CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
#define NUM_READINGS 10
static int no_sys_offset_ioctl = 0;
struct phc_reading {
struct timespec sys_ts1;
struct timespec phc_ts;;
struct timespec sys_ts2;
};
static double diff_ts(struct timespec *ts1, struct timespec *ts2)
{
return (ts1->tv_sec - ts2->tv_sec) + (ts1->tv_nsec - ts2->tv_nsec) / 1e9;
}
static int read_phc_ioctl(struct phc_reading *readings, int phc_fd, int n)
{
#if defined(PTP_SYS_OFFSET) && NUM_READINGS <= PTP_MAX_SAMPLES
struct ptp_sys_offset sys_off;
int i;
/* Silence valgrind */
memset(&sys_off, 0, sizeof (sys_off));
sys_off.n_samples = n;
if (ioctl(phc_fd, PTP_SYS_OFFSET, &sys_off)) {
LOG(LOGS_ERR, LOGF_Refclock, "ioctl(PTP_SYS_OFFSET) failed : %s", strerror(errno));
return 0;
}
for (i = 0; i < n; i++) {
readings[i].sys_ts1.tv_sec = sys_off.ts[i * 2].sec;
readings[i].sys_ts1.tv_nsec = sys_off.ts[i * 2].nsec;
readings[i].phc_ts.tv_sec = sys_off.ts[i * 2 + 1].sec;
readings[i].phc_ts.tv_nsec = sys_off.ts[i * 2 + 1].nsec;
readings[i].sys_ts2.tv_sec = sys_off.ts[i * 2 + 2].sec;
readings[i].sys_ts2.tv_nsec = sys_off.ts[i * 2 + 2].nsec;
}
return 1;
#else
/* Not available */
return 0;
#endif
}
static int read_phc_user(struct phc_reading *readings, int phc_fd, int n)
{
clockid_t phc_id;
int i;
phc_id = FD_TO_CLOCKID(phc_fd);
for (i = 0; i < n; i++) {
if (clock_gettime(CLOCK_REALTIME, &readings[i].sys_ts1) ||
clock_gettime(phc_id, &readings[i].phc_ts) ||
clock_gettime(CLOCK_REALTIME, &readings[i].sys_ts2)) {
LOG(LOGS_ERR, LOGF_Refclock, "clock_gettime() failed : %s", strerror(errno));
return 0;
}
}
return 1;
}
static int phc_initialise(RCL_Instance instance)
{
struct ptp_clock_caps caps;
int phc_fd;
char *path;
path = RCL_GetDriverParameter(instance);
phc_fd = open(path, O_RDONLY);
if (phc_fd < 0) {
LOG_FATAL(LOGF_Refclock, "open() failed on %s", path);
return 0;
}
/* Make sure it is a PHC */
if (ioctl(phc_fd, PTP_CLOCK_GETCAPS, &caps)) {
LOG_FATAL(LOGF_Refclock, "ioctl(PTP_CLOCK_GETCAPS) failed : %s", strerror(errno));
return 0;
}
UTI_FdSetCloexec(phc_fd);
RCL_SetDriverData(instance, (void *)(long)phc_fd);
return 1;
}
static void phc_finalise(RCL_Instance instance)
{
close((long)RCL_GetDriverData(instance));
}
static int phc_poll(RCL_Instance instance)
{
struct phc_reading readings[NUM_READINGS];
struct timeval tv;
double offset = 0.0, delay, best_delay = 0.0;
int i, phc_fd, best;
phc_fd = (long)RCL_GetDriverData(instance);
if (!no_sys_offset_ioctl) {
if (!read_phc_ioctl(readings, phc_fd, NUM_READINGS)) {
no_sys_offset_ioctl = 1;
return 0;
}
} else {
if (!read_phc_user(readings, phc_fd, NUM_READINGS))
return 0;
}
/* Find the fastest reading */
for (i = 0; i < NUM_READINGS; i++) {
delay = diff_ts(&readings[i].sys_ts2, &readings[i].sys_ts1);
if (!i || best_delay > delay) {
best = i;
best_delay = delay;
}
}
offset = diff_ts(&readings[best].phc_ts, &readings[best].sys_ts2) + best_delay / 2.0;
tv.tv_sec = readings[best].sys_ts2.tv_sec;
tv.tv_usec = readings[best].sys_ts2.tv_nsec / 1000;
DEBUG_LOG(LOGF_Refclock, "PHC offset: %+.9f delay: %.9f", offset, best_delay);
return RCL_AddSample(instance, &tv, offset, LEAP_Normal);
}
RefclockDriver RCL_PHC_driver = {
phc_initialise,
phc_finalise,
phc_poll
};
#else
RefclockDriver RCL_PHC_driver = { NULL, NULL, NULL };
#endif

View File

@@ -1,172 +0,0 @@
/*
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 "config.h"
#include "refclock.h"
#if HAVE_PPSAPI
#if defined(HAVE_SYS_TIMEPPS_H)
#include <sys/timepps.h>
#elif defined(HAVE_TIMEPPS_H)
#include <timepps.h>
#endif
#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;
}
UTI_FdSetCloexec(fd);
if (time_pps_create(fd, &handle) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_create() failed on %s", path);
return 0;
}
if (time_pps_getcap(handle, &mode) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_getcap() failed on %s", path);
return 0;
}
if (time_pps_getparams(handle, &params) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_getparams() failed on %s", path);
return 0;
}
if (!edge_clear) {
if (!(mode & PPS_CAPTUREASSERT)) {
LOG_FATAL(LOGF_Refclock, "CAPTUREASSERT not supported on %s", path);
return 0;
}
params.mode |= PPS_CAPTUREASSERT;
params.mode &= ~PPS_CAPTURECLEAR;
} else {
if (!(mode & PPS_CAPTURECLEAR)) {
LOG_FATAL(LOGF_Refclock, "CAPTURECLEAR not supported on %s", path);
return 0;
}
params.mode |= PPS_CAPTURECLEAR;
params.mode &= ~PPS_CAPTUREASSERT;
}
if (time_pps_setparams(handle, &params) < 0) {
LOG_FATAL(LOGF_Refclock, "time_pps_setparams() failed on %s", path);
return 0;
}
pps = MallocNew(struct pps_instance);
pps->handle = handle;
pps->last_seq = 0;
pps->edge_clear = edge_clear;
RCL_SetDriverData(instance, pps);
return 1;
}
static void pps_finalise(RCL_Instance instance)
{
struct pps_instance *pps;
pps = (struct pps_instance *)RCL_GetDriverData(instance);
time_pps_destroy(pps->handle);
Free(pps);
}
static int pps_poll(RCL_Instance instance)
{
struct pps_instance *pps;
struct timespec ts;
struct timeval tv;
pps_info_t pps_info;
pps_seq_t seq;
pps = (struct pps_instance *)RCL_GetDriverData(instance);
ts.tv_sec = 0;
ts.tv_nsec = 0;
if (time_pps_fetch(pps->handle, PPS_TSFMT_TSPEC, &pps_info, &ts) < 0) {
LOG(LOGS_ERR, LOGF_Refclock, "time_pps_fetch() failed : %s", strerror(errno));
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)) {
DEBUG_LOG(LOGF_Refclock, "PPS sample ignored seq=%lu ts=%lu.%09lu",
seq, ts.tv_sec, ts.tv_nsec);
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

View File

@@ -1,127 +0,0 @@
/*
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 "config.h"
#include "sysincl.h"
#include "refclock.h"
#include "logging.h"
#include "util.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
*/
volatile int count;
time_t clockTimeStampSec;
int clockTimeStampUSec;
time_t receiveTimeStampSec;
int receiveTimeStampUSec;
int leap;
int precision;
int nsamples;
volatile int valid;
int clockTimeStampNSec;
int receiveTimeStampNSec;
int dummy[8];
};
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 tv;
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) {
DEBUG_LOG(LOGF_Refclock, "SHM sample ignored mode=%d count=%d valid=%d",
t.mode, t.count, t.valid);
return 0;
}
shm->valid = 0;
tv.tv_sec = t.receiveTimeStampSec;
tv.tv_usec = t.receiveTimeStampUSec;
offset = t.clockTimeStampSec - t.receiveTimeStampSec;
if (t.clockTimeStampNSec / 1000 == t.clockTimeStampUSec &&
t.receiveTimeStampNSec / 1000 == t.receiveTimeStampUSec)
offset += (t.clockTimeStampNSec - t.receiveTimeStampNSec) * 1e-9;
else
offset += (t.clockTimeStampUSec - t.receiveTimeStampUSec) * 1e-6;
return RCL_AddSample(instance, &tv, offset, t.leap);
}
RefclockDriver RCL_SHM_driver = {
shm_initialise,
shm_finalise,
shm_poll
};

View File

@@ -1,130 +0,0 @@
/*
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 "config.h"
#include "sysincl.h"
#include "refclock.h"
#include "logging.h"
#include "util.h"
#include "sched.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) {
LOG(LOGS_ERR, LOGF_Refclock, "Could not read SOCK sample : %s",
strerror(errno));
return;
}
if (s != sizeof (sample)) {
LOG(LOGS_WARN, LOGF_Refclock, "Unexpected length of SOCK sample : %d != %ld",
s, (long)sizeof (sample));
return;
}
if (sample.magic != SOCK_MAGIC) {
LOG(LOGS_WARN, LOGF_Refclock, "Unexpected magic number in SOCK sample : %x != %x",
sample.magic, SOCK_MAGIC);
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;
}
UTI_FdSetCloexec(sockfd);
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
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/reference.h,v 1.13 2002/02/28 23:27:12 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2002 * Copyright (C) Richard P. Curnow 1997-2002
* Copyright (C) Miroslav Lichvar 2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -41,26 +44,6 @@ extern void REF_Initialise(void);
/* Fini function */ /* Fini function */
extern void REF_Finalise(void); extern void REF_Finalise(void);
typedef enum {
REF_ModeNormal,
REF_ModeInitStepSlew,
REF_ModeUpdateOnce,
REF_ModePrintOnce,
REF_ModeIgnore,
} REF_Mode;
/* Set reference update mode */
extern void REF_SetMode(REF_Mode mode);
/* Get reference update mode */
extern REF_Mode REF_GetMode(void);
/* Function type for handlers to be called back when mode ends */
typedef void (*REF_ModeEndHandler)(int result);
/* Set the handler for being notified of mode ending */
extern void REF_SetModeEndHandler(REF_ModeEndHandler handler);
/* Function which takes a local cooked time and returns the estimated /* Function which takes a local cooked time and returns the estimated
time of the reference. It also returns the other parameters time of the reference. It also returns the other parameters
required for forming the outgoing NTP packet. required for forming the outgoing NTP packet.
@@ -92,7 +75,7 @@ extern void REF_GetReferenceParams
int *is_synchronised, int *is_synchronised,
NTP_Leap *leap, NTP_Leap *leap,
int *stratum, int *stratum,
uint32_t *ref_id, unsigned long *ref_id,
struct timeval *ref_time, struct timeval *ref_time,
double *root_delay, double *root_delay,
double *root_dispersion double *root_dispersion
@@ -126,12 +109,9 @@ extern void REF_SetReference
( (
int stratum, int stratum,
NTP_Leap leap, NTP_Leap leap,
int combined_sources, unsigned long ref_id,
uint32_t ref_id,
IPAddr *ref_ip,
struct timeval *ref_time, struct timeval *ref_time,
double offset, double offset,
double offset_sd,
double frequency, double frequency,
double skew, double skew,
double root_delay, double root_delay,
@@ -150,7 +130,7 @@ extern void REF_SetManualReference
extern void extern void
REF_SetUnsynchronised(void); REF_SetUnsynchronised(void);
/* Return the current stratum of this host or 16 if the host is not /* Return the current stratum of this host or zero if the host is not
synchronised */ synchronised */
extern int REF_GetOurStratum(void); extern int REF_GetOurStratum(void);
@@ -159,12 +139,9 @@ extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
extern void REF_EnableLocal(int stratum); extern void REF_EnableLocal(int stratum);
extern void REF_DisableLocal(void); extern void REF_DisableLocal(void);
extern int REF_IsLocalActive(void);
/* Check if current raw or cooked time is close to a leap second
and is better to discard any measurements */
extern int REF_IsLeapSecondClose(void);
extern void REF_GetTrackingReport(RPT_TrackingReport *rep); extern void REF_GetTrackingReport(RPT_TrackingReport *rep);
extern void REF_CycleLogFile(void);
#endif /* GOT_REFERENCE_H */ #endif /* GOT_REFERENCE_H */

149
regress.c
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/regress.c,v 1.32 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,9 +29,11 @@
*/ */
#include "config.h" #include <assert.h>
#include <math.h>
#include "sysincl.h" #include <stdio.h>
#include <string.h>
#include "regress.h" #include "regress.h"
#include "logging.h" #include "logging.h"
@@ -64,7 +69,9 @@ RGR_WeightedRegression
double u, ui, aa; double u, ui, aa;
int i; int i;
assert(n >= 3); if (n<3) {
CROAK("Insufficient points");
}
W = U = 0; W = U = 0;
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
@@ -99,6 +106,8 @@ RGR_WeightedRegression
*sb0 = sqrt(*s2 / W + aa * aa); *sb0 = sqrt(*s2 / W + aa * aa);
*s2 *= (n / W); /* Giving weighted average of variances */ *s2 *= (n / W); /* Giving weighted average of variances */
return;
} }
/* ================================================== */ /* ================================================== */
@@ -126,30 +135,6 @@ RGR_GetTCoef(int dof)
} }
} }
/* ================================================== */
/* Get 90% quantile of chi-square distribution */
double
RGR_GetChi2Coef(int dof)
{
static double coefs[] = {
2.706, 4.605, 6.251, 7.779, 9.236, 10.645, 12.017, 13.362,
14.684, 15.987, 17.275, 18.549, 19.812, 21.064, 22.307, 23.542,
24.769, 25.989, 27.204, 28.412, 29.615, 30.813, 32.007, 33.196,
34.382, 35.563, 36.741, 37.916, 39.087, 40.256, 41.422, 42.585,
43.745, 44.903, 46.059, 47.212, 48.363, 49.513, 50.660, 51.805,
52.949, 54.090, 55.230, 56.369, 57.505, 58.641, 59.774, 60.907,
62.038, 63.167, 64.295, 65.422, 66.548, 67.673, 68.796, 69.919,
71.040, 72.160, 73.279, 74.397, 75.514, 76.630, 77.745, 78.860
};
if (dof <= 64) {
return coefs[dof-1];
} else {
return 1.2 * dof; /* Until I can be bothered to do something better */
}
}
/* ================================================== */ /* ================================================== */
/* Structure used for holding results of each regression */ /* Structure used for holding results of each regression */
@@ -165,23 +150,23 @@ typedef struct {
} RegressionResult; } RegressionResult;
/* ================================================== */ /* ================================================== */
/* Critical value for number of runs of residuals with same sign. /* Critical value for number of runs of residuals with same sign. 10%
5% critical region for now. */ critical region for now */
static char critical_runs[] = { static int critical_runs10[] =
0, 0, 0, 0, 0, 0, 0, 0, 2, 3, { 0, 0, 0, 0, 0, 0, 0, 0, 3, 3,
3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7,
7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11,
11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16,
15, 16, 16, 17, 17, 18, 18, 18, 19, 19, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20,
20, 20, 21, 21, 21, 22, 22, 23, 23, 24,
24, 25, 25, 26, 26, 26, 27, 27, 28, 28, /* Note that 66 onwards are bogus - I haven't worked out the
29, 29, 30, 30, 30, 31, 31, 32, 32, 33, critical values */
33, 34, 34, 35, 35, 35, 36, 36, 37, 37, 21, 21, 22, 22, 23, 23, 23, 24, 24, 25,
38, 38, 39, 39, 40, 40, 40, 41, 41, 42, 25, 26, 26, 27, 27, 28, 28, 28, 28, 28,
42, 43, 43, 44, 44, 45, 45, 46, 46, 46, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
52, 52, 52, 53, 53, 54, 54, 55, 55, 56 28, 28, 28, 28, 28, 28, 28, 28, 28, 28
}; };
/* ================================================== */ /* ================================================== */
@@ -209,6 +194,9 @@ n_runs_from_residuals(double *resid, int n)
/* Return a boolean indicating whether we had enough points for /* Return a boolean indicating whether we had enough points for
regression */ regression */
#define RESID_SIZE 1024
#define MIN_SAMPLES_FOR_REGRESS 3
int int
RGR_FindBestRegression RGR_FindBestRegression
(double *x, /* independent variable */ (double *x, /* independent variable */
@@ -217,12 +205,6 @@ RGR_FindBestRegression
less reliable) */ less reliable) */
int n, /* number of data points */ int n, /* number of data points */
int m, /* number of extra samples in x and y arrays
(negative index) which can be used to
extend runs test */
int min_samples, /* minimum number of samples to be kept after
changing the starting index to pass the runs
test */
/* And now the results */ /* And now the results */
@@ -246,16 +228,13 @@ RGR_FindBestRegression
) )
{ {
double P, Q, U, V, W; /* total */ double P, Q, U, V, W; /* total */
double resid[MAX_POINTS * REGRESS_RUNS_RATIO]; double resid[RESID_SIZE];
double ss; double ss;
double a, b, u, ui, aa; double a, b, u, ui, aa;
int start, resid_start, nruns, npoints; int start, nruns, npoints, npoints_left;
int i; int i;
assert(n <= MAX_POINTS && m >= 0);
assert(n * REGRESS_RUNS_RATIO < sizeof (critical_runs) / sizeof (critical_runs[0]));
if (n < MIN_SAMPLES_FOR_REGRESS) { if (n < MIN_SAMPLES_FOR_REGRESS) {
return 0; return 0;
} }
@@ -279,28 +258,20 @@ RGR_FindBestRegression
V += ui * ui / w[i]; V += ui * ui / w[i];
} }
npoints = n - start;
b = Q / V; b = Q / V;
a = (P / W) - (b * u); a = (P / W) - (b * u);
/* Get residuals also for the extra samples before start */ for (i=start; i<n; i++) {
resid_start = n - (n - start) * REGRESS_RUNS_RATIO; resid[i] = y[i] - a - b*x[i];
if (resid_start < -m)
resid_start = -m;
for (i=resid_start; i<n; i++) {
resid[i - resid_start] = y[i] - a - b*x[i];
} }
/* Count number of runs */ /* Count number of runs */
nruns = n_runs_from_residuals(resid, n - resid_start); nruns = n_runs_from_residuals(resid + start, npoints);
if (nruns > critical_runs[n - resid_start] || npoints_left = n - start - 1;
n - start <= MIN_SAMPLES_FOR_REGRESS ||
n - start <= min_samples) { if ((nruns > critical_runs10[npoints]) || (npoints_left < MIN_SAMPLES_FOR_REGRESS)) {
if (start != resid_start) {
/* Ignore extra samples in returned nruns */
nruns = n_runs_from_residuals(resid - resid_start + start, n - start);
}
break; break;
} else { } else {
/* Try dropping one sample at a time until the runs test passes. */ /* Try dropping one sample at a time until the runs test passes. */
@@ -315,7 +286,7 @@ RGR_FindBestRegression
ss = 0.0; ss = 0.0;
for (i=start; i<n; i++) { for (i=start; i<n; i++) {
ss += resid[i - resid_start]*resid[i - resid_start] / w[i]; ss += resid[i]*resid[i] / w[i];
} }
npoints = n - start; npoints = n - start;
@@ -361,7 +332,9 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
double piv; double piv;
int pivind; int pivind;
assert(index >= 0); if (index < 0) {
CROAK("Negative index");
}
/* If this bit of the array is already sorted, simple! */ /* If this bit of the array is already sorted, simple! */
if (flags[index]) { if (flags[index]) {
@@ -390,7 +363,7 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
l = u + 1; l = u + 1;
r = v; r = v;
do { do {
while (l < v && x[l] < piv) l++; while (x[l] < piv) l++;
while (x[r] > piv) r--; while (x[r] > piv) r--;
if (r <= l) break; if (r <= l) break;
EXCH(x[l], x[r]); EXCH(x[l], x[r]);
@@ -405,6 +378,8 @@ find_ordered_entry_with_flags(double *x, int n, int index, int *flags)
v = r - 1; v = r - 1;
} else if (index > r) { } else if (index > r) {
u = l; u = l;
} else {
CROAK("Impossible");
} }
} }
} while (1); } while (1);
@@ -419,7 +394,7 @@ find_ordered_entry(double *x, int n, int index)
{ {
int flags[MAX_POINTS]; int flags[MAX_POINTS];
memset(flags, 0, n * sizeof(int)); bzero(flags, n * sizeof(int));
return find_ordered_entry_with_flags(x, n, index, flags); return find_ordered_entry_with_flags(x, n, index, flags);
} }
#endif #endif
@@ -523,8 +498,6 @@ RGR_FindBestRobustRegression
double mx, dx, my, dy; double mx, dx, my, dy;
int nruns = 0; int nruns = 0;
assert(n < MAX_POINTS);
if (n < 2) { if (n < 2) {
return 0; return 0;
} else if (n == 2) { } else if (n == 2) {
@@ -570,6 +543,11 @@ RGR_FindBestRobustRegression
b = X / V; b = X / V;
a = my - b*mx; a = my - b*mx;
#if 0
printf("my=%20.12f mx=%20.12f a=%20.12f b=%20.12f\n", my, mx, a, b);
#endif
s2 = 0.0; s2 = 0.0;
for (i=start; i<n; i++) { for (i=start; i<n; i++) {
resid = y[i] - a - b * x[i]; resid = y[i] - a - b * x[i];
@@ -580,7 +558,7 @@ RGR_FindBestRobustRegression
Estimate standard deviation of b and expand range about b based Estimate standard deviation of b and expand range about b based
on that. */ on that. */
sb = sqrt(s2 * W/V); sb = sqrt(s2 * W/V);
if (sb > tol) { if (sb > 0.0) {
incr = 3.0 * sb; incr = 3.0 * sb;
} else { } else {
incr = 3.0 * tol; incr = 3.0 * tol;
@@ -590,11 +568,6 @@ RGR_FindBestRobustRegression
bhi = b; bhi = b;
do { do {
/* Make sure incr is significant to blo and bhi */
while (bhi + incr == bhi || blo - incr == blo) {
incr *= 2;
}
blo -= incr; blo -= incr;
bhi += incr; bhi += incr;
@@ -602,8 +575,8 @@ RGR_FindBestRobustRegression
eval_robust_residual(x + start, y + start, n_points, blo, &a, &rlo); eval_robust_residual(x + start, y + start, n_points, blo, &a, &rlo);
eval_robust_residual(x + start, y + start, n_points, bhi, &a, &rhi); eval_robust_residual(x + start, y + start, n_points, bhi, &a, &rhi);
} while (rlo * rhi >= 0.0); /* fn vals have same sign or one is zero, } while (rlo * rhi > 0.0); /* fn vals have same sign, i.e. root not
i.e. root not in interval (rlo, rhi). */ in interval. */
/* OK, so the root for b lies in (blo, bhi). Start bisecting */ /* OK, so the root for b lies in (blo, bhi). Start bisecting */
do { do {
@@ -618,9 +591,9 @@ RGR_FindBestRobustRegression
bhi = bmid; bhi = bmid;
rhi = rmid; rhi = rmid;
} else { } else {
assert(0); CROAK("Impossible");
} }
} while ((bhi - blo) > tol && (bmid - blo) * (bhi - bmid) > 0.0); } while ((bhi - blo) > tol);
*b0 = a; *b0 = a;
*b1 = bmid; *b1 = bmid;
@@ -637,7 +610,7 @@ RGR_FindBestRobustRegression
nruns = n_runs_from_residuals(resids + start, n_points); nruns = n_runs_from_residuals(resids + start, n_points);
if (nruns > critical_runs[n_points]) { if (nruns > critical_runs10[n_points]) {
break; break;
} else { } else {
start++; start++;

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/regress.h,v 1.13 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -57,18 +61,6 @@ RGR_WeightedRegression
extern double RGR_GetTCoef(int dof); extern double RGR_GetTCoef(int dof);
/* Return the value to apply to the variance to make an upper one-sided
test assuming a chi-square distribution. */
extern double RGR_GetChi2Coef(int dof);
/* Maximum ratio of number of points used for runs test to number of regression
points */
#define REGRESS_RUNS_RATIO 2
/* Minimum number of samples for regression */
#define MIN_SAMPLES_FOR_REGRESS 3
/* Return a status indicating whether there were enough points to /* Return a status indicating whether there were enough points to
carry out the regression */ carry out the regression */
@@ -80,12 +72,6 @@ RGR_FindBestRegression
less reliable) */ less reliable) */
int n, /* number of data points */ int n, /* number of data points */
int m, /* number of extra samples in x and y arrays
(negative index) which can be used to
extend runs test */
int min_samples, /* minimum number of samples to be kept after
changing the starting index to pass the runs
test */
/* And now the results */ /* And now the results */

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/reports.h,v 1.17 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,57 +32,50 @@
#define GOT_REPORTS_H #define GOT_REPORTS_H
#include "sysincl.h" #include "sysincl.h"
#include "addressing.h"
#define REPORT_INVALID_OFFSET 0x80000000 #define REPORT_INVALID_OFFSET 0x80000000
typedef struct { typedef struct {
IPAddr ip_addr; unsigned long ip_addr;
int stratum; int stratum;
int poll; int poll;
enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode;
enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE, RPT_OUTLIER} state; enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_OTHER} state;
enum {RPT_NORMAL, RPT_PREFER, RPT_NOSELECT} sel_option;
int reachability;
unsigned long latest_meas_ago; /* seconds */ unsigned long latest_meas_ago; /* seconds */
double orig_latest_meas; /* seconds */ long orig_latest_meas; /* microseconds (us) */
double latest_meas; /* seconds */ long latest_meas; /* us */
double latest_meas_err; /* seconds */ 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 */
} RPT_SourceReport ; } RPT_SourceReport ;
typedef struct { typedef struct {
uint32_t ref_id; unsigned long ref_id;
IPAddr ip_addr;
unsigned long stratum; unsigned long stratum;
unsigned long leap_status;
struct timeval ref_time; struct timeval ref_time;
double current_correction; struct timeval current_correction;
double last_offset;
double rms_offset;
double freq_ppm; double freq_ppm;
double resid_freq_ppm; double resid_freq_ppm;
double skew_ppm; double skew_ppm;
double root_delay; double root_delay;
double root_dispersion; double root_dispersion;
double last_update_interval;
} RPT_TrackingReport; } RPT_TrackingReport;
typedef struct { typedef struct {
uint32_t ref_id; unsigned long ip_addr;
IPAddr ip_addr;
unsigned long n_samples; unsigned long n_samples;
unsigned long n_runs; unsigned long n_runs;
unsigned long span_seconds; unsigned long span_seconds;
double resid_freq_ppm; double resid_freq_ppm;
double skew_ppm; double skew_ppm;
double sd; double sd_us;
double est_offset;
double est_offset_err;
} RPT_SourcestatsReport; } RPT_SourcestatsReport;
typedef struct { typedef struct {
struct timeval ref_time; unsigned long ref_time;
unsigned short n_samples; unsigned short n_samples;
unsigned short n_runs; unsigned short n_runs;
unsigned long span_seconds; unsigned long span_seconds;
@@ -97,7 +94,7 @@ typedef struct {
} RPT_ClientAccess_Report; } RPT_ClientAccess_Report;
typedef struct { typedef struct {
IPAddr ip_addr; unsigned long ip_addr;
unsigned long client_hits; unsigned long client_hits;
unsigned long peer_hits; unsigned long peer_hits;
unsigned long cmd_hits_auth; unsigned long cmd_hits_auth;
@@ -108,7 +105,7 @@ typedef struct {
} RPT_ClientAccessByIndex_Report; } RPT_ClientAccessByIndex_Report;
typedef struct { typedef struct {
struct timeval when; time_t when;
double slewed_offset; double slewed_offset;
double orig_offset; double orig_offset;
double residual; double residual;
@@ -119,7 +116,6 @@ typedef struct {
int offline; int offline;
int burst_online; int burst_online;
int burst_offline; int burst_offline;
int unresolved;
} RPT_ActivityReport; } RPT_ActivityReport;
#endif /* GOT_REPORTS_H */ #endif /* GOT_REPORTS_H */

104
rtc.c
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/rtc.c,v 1.14 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -23,12 +27,9 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "rtc.h" #include "rtc.h"
#include "local.h"
#include "logging.h" #include "logging.h"
#include "conf.h" #include "conf.h"
@@ -43,12 +44,13 @@ static int driver_initialised = 0;
static struct { static struct {
int (*init)(void); int (*init)(void);
void (*fini)(void); void (*fini)(void);
int (*time_pre_init)(void); void (*time_pre_init)(void);
void (*time_init)(void (*after_hook)(void*), void *anything); void (*time_init)(void (*after_hook)(void*), void *anything);
void (*start_measurements)(void); void (*start_measurements)(void);
int (*write_parameters)(void); int (*write_parameters)(void);
int (*get_report)(RPT_RTC_Report *report); int (*get_report)(RPT_RTC_Report *report);
int (*trim)(void); int (*trim)(void);
void (*cycle_logfile)(void);
} driver = } driver =
{ {
#if defined LINUX && defined FEAT_RTC #if defined LINUX && defined FEAT_RTC
@@ -59,7 +61,8 @@ static struct {
RTC_Linux_StartMeasurements, RTC_Linux_StartMeasurements,
RTC_Linux_WriteParameters, RTC_Linux_WriteParameters,
RTC_Linux_GetReport, RTC_Linux_GetReport,
RTC_Linux_Trim RTC_Linux_Trim,
RTC_Linux_CycleLogFile
#else #else
NULL, NULL,
NULL, NULL,
@@ -68,73 +71,47 @@ static struct {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
#endif #endif
}; };
/* ================================================== */
/* Set the system clock to the time of last modification of driftfile
if it's in the future */
static void
fallback_time_init(void)
{
struct timeval now;
struct stat buf;
char *drift_file;
drift_file = CNF_GetDriftFile();
if (!drift_file)
return;
if (stat(drift_file, &buf))
return;
LCL_ReadCookedTime(&now, NULL);
if (now.tv_sec < buf.st_mtime) {
LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
LOG(LOGS_INFO, LOGF_Rtc,
"System clock set from driftfile %s", drift_file);
}
}
/* ================================================== */ /* ================================================== */
void void
RTC_Initialise(int initial_set) RTC_Initialise(void)
{ {
char *file_name; char *file_name;
int ok;
/* Do an initial read of the RTC and set the system time to it. This
is analogous to what /sbin/hwclock -s would do on Linux. If that fails
or RTC is not supported, set the clock to the time of the last
modification of driftfile, so we at least get closer to the truth. */
if (initial_set) {
if (!driver.time_pre_init || !driver.time_pre_init()) {
fallback_time_init();
}
}
driver_initialised = 0;
/* This is how we tell whether the user wants to load the RTC /* This is how we tell whether the user wants to load the RTC
driver, if he is on a machine where it is an option. */ driver, if he is on a machine where it is an option. */
file_name = CNF_GetRtcFile(); file_name = CNF_GetRtcFile();
if (file_name) { if (file_name) {
if (CNF_GetRtcSync()) {
LOG_FATAL(LOGF_Rtc, "rtcfile directive cannot be used with rtcsync");
}
if (driver.init) { if (driver.init) {
if ((driver.init)()) { if ((driver.init)()) {
driver_initialised = 1; ok = 1;
} else {
ok = 0;
} }
} else { } else {
LOG(LOGS_ERR, LOGF_Rtc, "RTC not supported on this operating system"); ok = 0;
} }
if (ok) {
driver_initialised = 1;
} else {
driver_initialised = 0;
LOG(LOGS_ERR, LOGF_Rtc, "Real time clock not supported on this operating system");
}
} else {
driver_initialised = 0;
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -164,10 +141,23 @@ RTC_TimeInit(void (*after_hook)(void *), void *anything)
if (driver_initialised) { if (driver_initialised) {
(driver.time_init)(after_hook, anything); (driver.time_init)(after_hook, anything);
} else { } else {
LOG(LOGS_ERR, LOGF_Rtc, "Can't initialise from real time clock, driver not loaded");
(after_hook)(anything); (after_hook)(anything);
} }
} }
/* ================================================== */
/* Do an initial read of the RTC and set the system time to it. This
is analogous to what /sbin/clock -s -u would do on Linux. */
void
RTC_TimePreInit(void)
{
if (driver.time_pre_init) {
(driver.time_pre_init)();
}
}
/* ================================================== */ /* ================================================== */
/* Start the RTC measurement process */ /* Start the RTC measurement process */
@@ -220,3 +210,13 @@ RTC_Trim(void)
/* ================================================== */ /* ================================================== */
void
RTC_CycleLogFile(void)
{
if (driver_initialised) {
(driver.cycle_logfile)();
}
}
/* ================================================== */

11
rtc.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/rtc.h,v 1.9 2002/02/28 23:27:13 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,8 +32,9 @@
#include "reports.h" #include "reports.h"
extern void RTC_Initialise(int initial_set); extern void RTC_Initialise(void);
extern void RTC_Finalise(void); extern void RTC_Finalise(void);
extern void RTC_TimePreInit(void);
extern void RTC_TimeInit(void (*after_hook)(void *), void *anything); extern void RTC_TimeInit(void (*after_hook)(void *), void *anything);
extern void RTC_StartMeasurements(void); extern void RTC_StartMeasurements(void);
extern int RTC_GetReport(RPT_RTC_Report *report); extern int RTC_GetReport(RPT_RTC_Report *report);
@@ -42,4 +47,6 @@ extern int RTC_WriteParameters(void);
extern int RTC_Trim(void); extern int RTC_Trim(void);
extern void RTC_CycleLogFile(void);
#endif /* GOT_RTC_H */ #endif /* GOT_RTC_H */

View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/rtc_linux.c,v 1.32 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2012-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -27,23 +30,50 @@
*/ */
#include "config.h" #if defined LINUX
#include "sysincl.h" #ifdef sparc
#define __KERNEL__
#endif
#include <linux/rtc.h> #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "logging.h" #include "logging.h"
#include "sched.h" #include "sched.h"
#include "local.h" #include "local.h"
#include "util.h" #include "util.h"
#include "sys_linux.h" #include "sys_linux.h"
#include "reference.h"
#include "regress.h" #include "regress.h"
#include "rtc.h" #include "rtc.h"
#include "rtc_linux.h" #include "rtc_linux.h"
#include "io_linux.h"
#include "conf.h" #include "conf.h"
#include "memory.h" #include "memory.h"
#include "mkdirpp.h"
struct rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
/* ================================================== */ /* ================================================== */
/* Forward prototypes */ /* Forward prototypes */
@@ -68,15 +98,15 @@ static int fd = -1;
#define LOWEST_MEASUREMENT_PERIOD 15 #define LOWEST_MEASUREMENT_PERIOD 15
#define HIGHEST_MEASUREMENT_PERIOD 480 #define HIGHEST_MEASUREMENT_PERIOD 480
#define N_SAMPLES_PER_REGRESSION 1
/* Try to avoid doing regression after _every_ sample we accumulate */
#define N_SAMPLES_PER_REGRESSION 4
static int measurement_period = LOWEST_MEASUREMENT_PERIOD; static int measurement_period = LOWEST_MEASUREMENT_PERIOD;
static int timeout_running = 0; static int timeout_running = 0;
static SCH_TimeoutID timeout_id; static SCH_TimeoutID timeout_id;
static int skip_interrupts;
/* ================================================== */ /* ================================================== */
/* Maximum number of samples held */ /* Maximum number of samples held */
@@ -124,9 +154,6 @@ static double coef_gain_rate;
RTC data file once we have reacquired its offset after the step */ RTC data file once we have reacquired its offset after the step */
static double saved_coef_gain_rate; static double saved_coef_gain_rate;
/* Threshold for automatic RTC trimming in seconds, zero when disabled */
static double autotrim_threshold;
/* Filename supplied by config file where RTC coefficients are /* Filename supplied by config file where RTC coefficients are
stored. */ stored. */
static char *coefs_file_name; static char *coefs_file_name;
@@ -151,7 +178,11 @@ static int rtc_on_utc = 1;
/* ================================================== */ /* ================================================== */
static LOG_FileID logfileid; static FILE *logfile=NULL;
static char *logfilename = NULL;
static unsigned long logwrites=0;
#define RTC_LOG "rtc.log"
/* ================================================== */ /* ================================================== */
@@ -165,7 +196,12 @@ discard_samples(int new_first)
{ {
int n_to_save; int n_to_save;
assert(new_first >= 0 && new_first < n_samples); if (!(new_first < n_samples)) {
CROAK("new_first should be < n_samples");
}
if (!(new_first >= 0)) {
CROAK("new_first should be non-negative");
}
n_to_save = n_samples - new_first; n_to_save = n_samples - new_first;
@@ -174,6 +210,7 @@ discard_samples(int new_first)
memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timeval)); memmove(system_times, system_times + new_first, n_to_save * sizeof(struct timeval));
n_samples = n_to_save; n_samples = n_to_save;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -201,6 +238,8 @@ accumulate_sample(time_t rtc, struct timeval *sys)
++n_samples_since_regression; ++n_samples_since_regression;
} }
++n_samples; ++n_samples;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -217,12 +256,14 @@ run_regression(int new_sample,
{ {
double rtc_rel[MAX_SAMPLES]; /* Relative times on RTC axis */ double rtc_rel[MAX_SAMPLES]; /* Relative times on RTC axis */
double offsets[MAX_SAMPLES]; /* How much the RTC is fast of the system clock */ double offsets[MAX_SAMPLES]; /* How much the RTC is fast of the system clock */
int i; int i, n;
double est_intercept, est_slope; double est_intercept, est_slope;
int best_new_start; int best_new_start;
if (n_samples > 0) { if (n_samples > 0) {
n = n_samples - 1;
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
rtc_rel[i] = rtc_trim[i] + (double)(rtc_sec[i] - rtc_ref); rtc_rel[i] = rtc_trim[i] + (double)(rtc_sec[i] - rtc_ref);
offsets[i] = ((double) (rtc_ref - system_times[i].tv_sec) - offsets[i] = ((double) (rtc_ref - system_times[i].tv_sec) -
@@ -264,23 +305,27 @@ run_regression(int new_sample,
static void static void
slew_samples slew_samples
(struct timeval *raw, struct timeval *cooked, (struct timeval *raw, struct timeval *cooked,
double dfreq, double dfreq, double afreq_ppm,
double doffset, double doffset, int is_step_change,
LCL_ChangeType change_type,
void *anything) void *anything)
{ {
int i; int i;
double elapsed;
double new_freq;
double old_freq;
double delta_time; double delta_time;
double old_seconds_fast, old_gain_rate; double old_seconds_fast, old_gain_rate;
if (change_type == LCL_ChangeUnknownStep) { new_freq = 1.0e-6 * afreq_ppm;
/* Drop all samples. */ old_freq = (new_freq - dfreq) / (1.0 - dfreq);
n_samples = 0;
}
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
UTI_AdjustTimeval(system_times + i, cooked, system_times + i, &delta_time, UTI_DiffTimevalsToDouble(&elapsed, cooked, system_times + i);
dfreq, doffset);
delta_time = -(elapsed * dfreq) - doffset;
UTI_AddDoubleToTimeval(system_times + i, delta_time, system_times + i);
} }
old_seconds_fast = coef_seconds_fast; old_seconds_fast = coef_seconds_fast;
@@ -288,13 +333,16 @@ slew_samples
if (coefs_valid) { if (coefs_valid) {
coef_seconds_fast += doffset; coef_seconds_fast += doffset;
coef_gain_rate += dfreq * (1.0 - coef_gain_rate); coef_gain_rate = 1.0 - ((1.0 + new_freq) / (1.0 + old_freq)) * (1.0 - coef_gain_rate);
} }
DEBUG_LOG(LOGF_RtcLinux, "dfreq=%.8f doffset=%.6f old_fast=%.6f old_rate=%.3f new_fast=%.6f new_rate=%.3f", #if 0
dfreq, doffset, LOG(LOGS_INFO, LOGF_RtcLinux, "dfreq=%.8f doffset=%.6f new_freq=%.3f old_freq=%.3f old_fast=%.6f old_rate=%.3f new_fast=%.6f new_rate=%.3f",
dfreq, doffset, 1.0e6*new_freq, 1.0e6*old_freq,
old_seconds_fast, 1.0e6 * old_gain_rate, old_seconds_fast, 1.0e6 * old_gain_rate,
coef_seconds_fast, 1.0e6 * coef_gain_rate); coef_seconds_fast, 1.0e6 * coef_gain_rate);
#endif
} }
/* ================================================== */ /* ================================================== */
@@ -372,55 +420,14 @@ t_from_rtc(struct tm *stm) {
/* ================================================== */ /* ================================================== */
static void
read_hwclock_file(const char *hwclock_file)
{
FILE *in;
char line[256];
int i;
if (!hwclock_file)
return;
in = fopen(hwclock_file, "r");
if (!in) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not open hwclockfile %s",
hwclock_file);
return;
}
/* Read third line from the file. */
for (i = 0; i < 3; i++) {
if (!fgets(line, sizeof(line), in))
break;
}
fclose(in);
if (i == 3 && !strncmp(line, "LOCAL", 5)) {
rtc_on_utc = 0;
} else if (i == 3 && !strncmp(line, "UTC", 3)) {
rtc_on_utc = 1;
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read LOCAL/UTC setting from hwclockfile %s",
hwclock_file);
}
}
/* ================================================== */
static void static void
setup_config(void) setup_config(void)
{ {
if (CNF_GetRtcOnUtc()) { if (CNF_GetRTCOnUTC()) {
rtc_on_utc = 1; rtc_on_utc = 1;
} else { } else {
rtc_on_utc = 0; rtc_on_utc = 0;
} }
read_hwclock_file(CNF_GetHwclockFile());
autotrim_threshold = CNF_GetRtcAutotrim();
} }
/* ================================================== */ /* ================================================== */
@@ -431,6 +438,7 @@ static void
read_coefs_from_file(void) read_coefs_from_file(void)
{ {
FILE *in; FILE *in;
char line[256];
if (!tried_to_load_coefs) { if (!tried_to_load_coefs) {
@@ -438,17 +446,26 @@ read_coefs_from_file(void)
tried_to_load_coefs = 1; tried_to_load_coefs = 1;
if (coefs_file_name && (in = fopen(coefs_file_name, "r"))) { in = fopen(coefs_file_name, "r");
if (fscanf(in, "%d%ld%lf%lf", if (in) {
&valid_coefs_from_file, if (fgets(line, sizeof(line), in)) {
&file_ref_time, if (sscanf(line, "%d%ld%lf%lf",
&file_ref_offset, &valid_coefs_from_file,
&file_rate_ppm) == 4) { &file_ref_time,
&file_ref_offset,
&file_rate_ppm) == 4) {
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not parse coefficients line from RTC file %s",
coefs_file_name);
}
} else { } else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read coefficients from RTC file %s", LOG(LOGS_WARN, LOGF_RtcLinux, "Could not read first line from RTC file %s",
coefs_file_name); coefs_file_name);
} }
fclose(in); fclose(in);
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not open RTC file %s for reading",
coefs_file_name);
} }
} }
} }
@@ -463,7 +480,6 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
struct stat buf; struct stat buf;
char *temp_coefs_file_name; char *temp_coefs_file_name;
FILE *out; FILE *out;
int r1, r2;
/* Create a temporary file with a '.tmp' extension. */ /* Create a temporary file with a '.tmp' extension. */
@@ -485,25 +501,16 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
} }
/* Gain rate is written out in ppm */ /* Gain rate is written out in ppm */
r1 = fprintf(out, "%1d %ld %.6f %.3f\n", fprintf(out, "%1d %ld %.6f %.3f\n",
valid, ref_time, offset, 1.0e6 * rate); valid,ref_time, offset, 1.0e6 * rate);
r2 = fclose(out);
if (r1 < 0 || r2) { fclose(out);
Free(temp_coefs_file_name);
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not write to temporary RTC file %s.tmp",
coefs_file_name);
return RTC_ST_BADFILE;
}
/* Clone the file attributes from the existing file if there is one. */ /* Clone the file attributes from the existing file if there is one. */
if (!stat(coefs_file_name,&buf)) { if (!stat(coefs_file_name,&buf)) {
if (chown(temp_coefs_file_name,buf.st_uid,buf.st_gid) || chown(temp_coefs_file_name,buf.st_uid,buf.st_gid);
chmod(temp_coefs_file_name,buf.st_mode & 0777)) { chmod(temp_coefs_file_name,buf.st_mode&0777);
LOG(LOGS_WARN, LOGF_RtcLinux,
"Could not change ownership or permissions of temporary RTC file %s.tmp",
coefs_file_name);
}
} }
/* Rename the temporary file to the correct location (see rename(2) for details). */ /* Rename the temporary file to the correct location (see rename(2) for details). */
@@ -530,6 +537,63 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate)
int int
RTC_Linux_Initialise(void) RTC_Linux_Initialise(void)
{ {
int major, minor, patch;
char *direc;
/* Check whether we can support the real time clock.
Linux 1.2.x - haven't checked yet
Linux 1.3.x - don't know, haven't got a system to look at
Linux 2.0.x - For x<=31, using any variant of the adjtimex() call
sets the kernel into a mode where the RTC was updated every 11
minutes. The only way to escape this is to use settimeofday().
Since we need to have sole control over the RTC to be able to
measure its drift rate, and there is no 'notify' callback to warn
you that the kernel is going to do this, I can't see a way to
support this.
Linux 2.0.x - For x>=32 the adjtimex()/RTC behaviour was
modified, so that as long as the STA_UNSYNC flag is set the RTC
is left alone. This is the mode we exploit here, so that the RTC
continues to go its own sweet way, unless we make updates to it
from this module.
Linux 2.1.x - don't know, haven't got a system to look at.
Linux 2.2.x, 2.3.x and 2.4.x are believed to be OK for all
patch levels
*/
SYS_Linux_GetKernelVersion(&major, &minor, &patch);
/* Obviously this test can get more elaborate when we know about
more system types. */
if (major != 2) {
return 0;
} else {
switch (minor) {
case 0:
if (patch <= 31) {
return 0;
}
break;
case 1:
return 0;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
break; /* OK for all patch levels */
}
}
/* Setup details depending on configuration options */ /* Setup details depending on configuration options */
setup_config(); setup_config();
@@ -540,14 +604,10 @@ RTC_Linux_Initialise(void)
fd = open (CNF_GetRtcDevice(), O_RDWR); fd = open (CNF_GetRtcDevice(), O_RDWR);
if (fd < 0) { if (fd < 0) {
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not open RTC device %s : %s", LOG(LOGS_ERR, LOGF_RtcLinux, "Could not open %s, %s", CNF_GetRtcDevice(), strerror(errno));
CNF_GetRtcDevice(), strerror(errno));
return 0; return 0;
} }
/* Close on exec */
UTI_FdSetCloexec(fd);
n_samples = 0; n_samples = 0;
n_samples_since_regression = 0; n_samples_since_regression = 0;
n_runs = 0; n_runs = 0;
@@ -563,9 +623,23 @@ RTC_Linux_Initialise(void)
/* Register slew handler */ /* Register slew handler */
LCL_AddParameterChangeHandler(slew_samples, NULL); LCL_AddParameterChangeHandler(slew_samples, NULL);
logfileid = CNF_GetLogRtc() ? LOG_FileOpen("rtc", if (CNF_GetLogRtc()) {
" Date (UTC) Time RTC fast (s) Val Est fast (s) Slope (ppm) Ns Nr Meas") direc = CNF_GetLogDir();
: -1; 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);
}
}
}
return 1; return 1;
} }
@@ -588,6 +662,11 @@ RTC_Linux_Finalise(void)
(void) RTC_Linux_WriteParameters(); (void) RTC_Linux_WriteParameters();
} }
if (logfile) {
fclose(logfile);
}
} }
/* ================================================== */ /* ================================================== */
@@ -603,7 +682,6 @@ switch_interrupts(int onoff)
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno)); LOG(LOGS_ERR, LOGF_RtcLinux, "Could not start measurement : %s", strerror(errno));
return; return;
} }
skip_interrupts = 1;
} else { } else {
status = ioctl(fd, RTC_UIE_OFF, 0); status = ioctl(fd, RTC_UIE_OFF, 0);
if (status < 0) { if (status < 0) {
@@ -639,9 +717,6 @@ set_rtc(time_t new_rtc_time)
rtc_raw.tm_mday = rtc_tm.tm_mday; rtc_raw.tm_mday = rtc_tm.tm_mday;
rtc_raw.tm_mon = rtc_tm.tm_mon; rtc_raw.tm_mon = rtc_tm.tm_mon;
rtc_raw.tm_year = rtc_tm.tm_year; rtc_raw.tm_year = rtc_tm.tm_year;
rtc_raw.tm_wday = rtc_tm.tm_wday;
rtc_raw.tm_yday = rtc_tm.tm_yday;
rtc_raw.tm_isdst = rtc_tm.tm_isdst;
status = ioctl(fd, RTC_SET_TIME, &rtc_raw); status = ioctl(fd, RTC_SET_TIME, &rtc_raw);
if (status < 0) { if (status < 0) {
@@ -688,7 +763,7 @@ handle_initial_trim(void)
sys_error_now = rtc_error_now - coef_seconds_fast; sys_error_now = rtc_error_now - coef_seconds_fast;
LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now); LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now);
LCL_AccumulateOffset(sys_error_now, 0.0); LCL_AccumulateOffset(sys_error_now);
} else { } else {
LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time"); LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time");
} }
@@ -698,6 +773,8 @@ handle_initial_trim(void)
(after_init_hook)(after_init_hook_arg); (after_init_hook)(after_init_hook_arg);
operating_mode = OM_NORMAL; operating_mode = OM_NORMAL;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -709,7 +786,6 @@ handle_relock_after_trim(void)
time_t ref; time_t ref;
double fast, slope; double fast, slope;
valid = 0;
run_regression(1, &valid, &ref, &fast, &slope); run_regression(1, &valid, &ref, &fast, &slope);
if (valid) { if (valid) {
@@ -718,7 +794,6 @@ handle_relock_after_trim(void)
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not do regression after trim"); LOG(LOGS_WARN, LOGF_RtcLinux, "Could not do regression after trim");
} }
coefs_valid = 0;
n_samples = 0; n_samples = 0;
n_samples_since_regression = 0; n_samples_since_regression = 0;
operating_mode = OM_NORMAL; operating_mode = OM_NORMAL;
@@ -727,25 +802,8 @@ handle_relock_after_trim(void)
/* ================================================== */ /* ================================================== */
static void /* Day number of 1 Jan 1970 */
maybe_autotrim(void) #define MJD_1970 40587
{
/* Trim only when in normal mode, the coefficients are fresh, the current
offset is above the threshold and the system clock is synchronized */
if (operating_mode != OM_NORMAL || !coefs_valid || n_samples_since_regression)
return;
if (autotrim_threshold <= 0.0 || fabs(coef_seconds_fast) < autotrim_threshold)
return;
if (REF_GetOurStratum() >= 16)
return;
RTC_Linux_Trim();
}
/* ================================================== */
static void static void
process_reading(time_t rtc_time, struct timeval *system_time) process_reading(time_t rtc_time, struct timeval *system_time)
@@ -757,10 +815,9 @@ process_reading(time_t rtc_time, struct timeval *system_time)
switch (operating_mode) { switch (operating_mode) {
case OM_NORMAL: case OM_NORMAL:
if (n_samples_since_regression >= N_SAMPLES_PER_REGRESSION) { if (n_samples_since_regression >= /* 4 */ 1 ) {
run_regression(1, &coefs_valid, &coef_ref_time, &coef_seconds_fast, &coef_gain_rate); run_regression(1, &coefs_valid, &coef_ref_time, &coef_seconds_fast, &coef_gain_rate);
n_samples_since_regression = 0; n_samples_since_regression = 0;
maybe_autotrim();
} }
break; break;
@@ -775,19 +832,28 @@ process_reading(time_t rtc_time, struct timeval *system_time)
} }
break; break;
default: default:
assert(0); CROAK("Impossible");
break; break;
} }
if (logfileid != -1) { if (logfile) {
rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec; rtc_fast = (double)(rtc_time - system_time->tv_sec) - 1.0e-6 * (double) system_time->tv_usec;
LOG_FileWrite(logfileid, "%s %14.6f %1d %14.6f %12.3f %2d %2d %4d", if (((logwrites++) % 32) == 0) {
fprintf(logfile,
"===============================================================================\n"
" Date (UTC) Time RTC fast (s) Val Est fast (s) Slope (ppm) Ns Nr Meas\n"
"===============================================================================\n");
}
fprintf(logfile, "%s %14.6f %1d %14.6f %12.3f %2d %2d %4d\n",
UTI_TimeToLogForm(system_time->tv_sec), UTI_TimeToLogForm(system_time->tv_sec),
rtc_fast, rtc_fast,
coefs_valid, coefs_valid,
coef_seconds_fast, coef_gain_rate * 1.0e6, n_samples, n_runs, measurement_period); coef_seconds_fast, coef_gain_rate * 1.0e6, n_samples, n_runs, measurement_period);
fflush(logfile);
} }
} }
@@ -803,34 +869,35 @@ read_from_device(void *any)
struct rtc_time rtc_raw; struct rtc_time rtc_raw;
struct tm rtc_tm; struct tm rtc_tm;
time_t rtc_t; time_t rtc_t;
double read_err;
int error = 0; int error = 0;
status = read(fd, &data, sizeof(data)); status = read(fd, &data, sizeof(data));
if (operating_mode == OM_NORMAL)
status = read(fd, &data, sizeof(data));
if (status < 0) { if (status < 0) {
/* This looks like a bad error : the file descriptor was indicating it was /* This looks like a bad error : the file descriptor was indicating it was
* ready to read but we couldn't read anything. Give up. */ * ready to read but we couldn't read anything. Give up. */
LOG(LOGS_ERR, LOGF_RtcLinux, "Could not read flags %s : %s", CNF_GetRtcDevice(), strerror(errno)); LOG(LOGS_ERR, LOGF_RtcLinux, "Could not read flags %s : %s", CNF_GetRtcDevice(), strerror(errno));
error = 1;
SCH_RemoveInputFileHandler(fd); SCH_RemoveInputFileHandler(fd);
switch_interrupts(0); /* Likely to raise error too, but just to be sure... */ switch_interrupts(0); /* Likely to raise error too, but just to be sure... */
close(fd); close(fd);
fd = -1; fd = -1;
if (logfile) {
fclose(logfile);
logfile = NULL;
}
return; return;
} }
if (skip_interrupts > 0) { if ((data & RTC_UIE) == RTC_UIE) {
/* Wait for the next interrupt, this one may be bogus */
skip_interrupts--;
return;
}
if ((data & RTC_UF) == RTC_UF) {
/* Update interrupt detected */ /* Update interrupt detected */
/* Read RTC time, sandwiched between two polls of the system clock /* Read RTC time, sandwiched between two polls of the system clock
so we can bound any error. */ so we can bound any error. */
SCH_GetLastEventTime(&sys_time, NULL, NULL); LCL_ReadCookedTime(&sys_time, &read_err);
status = ioctl(fd, RTC_RD_TIME, &rtc_raw); status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status < 0) { if (status < 0) {
@@ -909,7 +976,7 @@ turn_off_interrupt:
break; break;
default: default:
assert(0); CROAK("Impossible");
break; break;
} }
@@ -962,19 +1029,20 @@ RTC_Linux_WriteParameters(void)
/* ================================================== */ /* ================================================== */
/* Try to set the system clock from the RTC, in the same manner as /* Try to set the system clock from the RTC, in the same manner as
/sbin/hwclock -s would do. We're not as picky about OS version /sbin/clock -s -u would do. We're not as picky about OS version
etc in this case, since we have fewer requirements regarding the etc in this case, since we have fewer requirements regarding the
RTC behaviour than we do for the rest of the module. */ RTC behaviour than we do for the rest of the module. */
int void
RTC_Linux_TimePreInit(void) RTC_Linux_TimePreInit(void)
{ {
int fd, status; int fd, status;
struct rtc_time rtc_raw, rtc_raw_retry; struct rtc_time rtc_raw;
struct tm rtc_tm; struct tm rtc_tm;
time_t rtc_t; time_t rtc_t, estimated_correct_rtc_t;
double accumulated_error, sys_offset; long interval;
struct timeval new_sys_time, old_sys_time; double accumulated_error = 0.0;
struct timeval new_sys_time;
coefs_file_name = CNF_GetRtcFile(); coefs_file_name = CNF_GetRtcFile();
@@ -984,23 +1052,10 @@ RTC_Linux_TimePreInit(void)
fd = open(CNF_GetRtcDevice(), O_RDONLY); fd = open(CNF_GetRtcDevice(), O_RDONLY);
if (fd < 0) { if (fd < 0) {
return 0; /* Can't open it, and won't be able to later */ return; /* Can't open it, and won't be able to later */
} }
/* Retry reading the rtc until both read attempts give the same sec value. status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
This way the race condition is prevented that the RTC has updated itself
during the first read operation. */
do {
status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
if (status >= 0) {
status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry);
}
} while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec);
/* Read system clock */
LCL_ReadCookedTime(&old_sys_time, NULL);
close(fd);
if (status >= 0) { if (status >= 0) {
/* Convert to seconds since 1970 */ /* Convert to seconds since 1970 */
@@ -1018,35 +1073,30 @@ RTC_Linux_TimePreInit(void)
/* Work out approximatation to correct time (to about the /* Work out approximatation to correct time (to about the
nearest second) */ nearest second) */
if (valid_coefs_from_file) { if (valid_coefs_from_file) {
accumulated_error = file_ref_offset + interval = rtc_t - file_ref_time;
(rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm; accumulated_error = file_ref_offset + (double)(interval) * 1.0e-6 * file_rate_ppm;
} else {
accumulated_error = 0.0;
}
/* Correct time */ /* Correct time */
new_sys_time.tv_sec = rtc_t;
/* Average error in the RTC reading */
new_sys_time.tv_usec = 500000;
UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time);
UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time);
/* Set system time only if the step is larger than 1 second */
if (fabs(sys_offset) >= 1.0) {
LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f", LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
accumulated_error); accumulated_error);
LCL_ApplyStepOffset(sys_offset); estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
} else {
estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
}
new_sys_time.tv_sec = estimated_correct_rtc_t;
new_sys_time.tv_usec = 0;
/* Tough luck if this fails */
if (settimeofday(&new_sys_time, NULL) < 0) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not settimeofday");
} }
} else { } else {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970"); LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
return 0;
} }
} }
return 1; close(fd);
} }
/* ================================================== */ /* ================================================== */
@@ -1054,8 +1104,7 @@ RTC_Linux_TimePreInit(void)
int int
RTC_Linux_GetReport(RPT_RTC_Report *report) RTC_Linux_GetReport(RPT_RTC_Report *report)
{ {
report->ref_time.tv_sec = coef_ref_time; report->ref_time = (unsigned long) coef_ref_time;
report->ref_time.tv_usec = 0;
report->n_samples = n_samples; report->n_samples = n_samples;
report->n_runs = n_runs; report->n_runs = n_runs;
if (n_samples > 1) { if (n_samples > 1) {
@@ -1075,6 +1124,7 @@ int
RTC_Linux_Trim(void) RTC_Linux_Trim(void)
{ {
struct timeval now; struct timeval now;
double local_clock_err;
/* Remember the slope coefficient - we won't be able to determine a /* Remember the slope coefficient - we won't be able to determine a
@@ -1093,7 +1143,7 @@ RTC_Linux_Trim(void)
want |E| <= 0.5, which implies R <= S <= R+1, i.e. R is just want |E| <= 0.5, which implies R <= S <= R+1, i.e. R is just
the rounded down part of S, i.e. the seconds part. */ the rounded down part of S, i.e. the seconds part. */
LCL_ReadCookedTime(&now, NULL); LCL_ReadCookedTime(&now, &local_clock_err);
set_rtc(now.tv_sec); set_rtc(now.tv_sec);
@@ -1102,11 +1152,6 @@ RTC_Linux_Trim(void)
n_samples = 0; n_samples = 0;
operating_mode = OM_AFTERTRIM; operating_mode = OM_AFTERTRIM;
/* Estimate the offset in case writertc is called or chronyd
is terminated during rapid sampling */
coef_seconds_fast = -now.tv_usec / 1e6 + 0.5;
coef_ref_time = now.tv_sec;
/* And start rapid sampling, interrupts on now */ /* And start rapid sampling, interrupts on now */
if (timeout_running) { if (timeout_running) {
SCH_RemoveTimeout(timeout_id); SCH_RemoveTimeout(timeout_id);
@@ -1118,3 +1163,22 @@ RTC_Linux_Trim(void)
return 1; return 1;
} }
/* ================================================== */
void
RTC_Linux_CycleLogFile(void)
{
if (logfile && logfilename) {
fclose(logfile);
logfile = fopen(logfilename, "a");
if (!logfile) {
LOG(LOGS_WARN, LOGF_RtcLinux, "Could not reopen logfile %s", logfilename);
}
logwrites = 0;
}
}
/* ================================================== */
#endif /* defined LINUX */

View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/rtc_linux.h,v 1.13 2002/02/28 23:27:13 richard Exp $
======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -28,9 +32,11 @@
#include "reports.h" #include "reports.h"
#if defined LINUX
extern int RTC_Linux_Initialise(void); extern int RTC_Linux_Initialise(void);
extern void RTC_Linux_Finalise(void); extern void RTC_Linux_Finalise(void);
extern int RTC_Linux_TimePreInit(void); extern void RTC_Linux_TimePreInit(void);
extern void RTC_Linux_TimeInit(void (*after_hook)(void *), void *anything); extern void RTC_Linux_TimeInit(void (*after_hook)(void *), void *anything);
extern void RTC_Linux_StartMeasurements(void); extern void RTC_Linux_StartMeasurements(void);
@@ -42,4 +48,6 @@ extern int RTC_Linux_Trim(void);
extern void RTC_Linux_CycleLogFile(void); extern void RTC_Linux_CycleLogFile(void);
#endif /* defined LINUX */
#endif /* _GOT_RTC_LINUX_H */ #endif /* _GOT_RTC_LINUX_H */

331
sched.c
View File

@@ -1,9 +1,12 @@
/* /*
$Header: /cvs/src/chrony/sched.c,v 1.17 2003/09/22 21:22:30 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Richard P. Curnow 1997-2003
* Copyright (C) Miroslav Lichvar 2011, 2013-2014
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@@ -16,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -26,8 +29,6 @@
*/ */
#include "config.h"
#include "sysincl.h" #include "sysincl.h"
#include "sched.h" #include "sched.h"
@@ -57,22 +58,18 @@ static unsigned int n_read_fds;
/* One more than the highest file descriptor that is registered */ /* One more than the highest file descriptor that is registered */
static unsigned int one_highest_fd; static unsigned int one_highest_fd;
#ifndef FD_SETSIZE /* This assumes that fd_set is implemented as a fixed size array of
/* If FD_SETSIZE is not defined, assume that fd_set is implemented bits, possibly embedded inside a record. It might therefore
as a fixed size array of bits, possibly embedded inside a record */ somewhat non-portable. */
#define FD_SETSIZE (sizeof(fd_set) * 8)
#endif #define FD_SET_SIZE (sizeof(fd_set) * 8)
typedef struct { typedef struct {
SCH_FileHandler handler; SCH_FileHandler handler;
SCH_ArbitraryArgument arg; SCH_ArbitraryArgument arg;
} FileHandlerEntry; } FileHandlerEntry;
static FileHandlerEntry file_handlers[FD_SETSIZE]; static FileHandlerEntry file_handlers[FD_SET_SIZE];
/* Timestamp when last select() returned */
static struct timeval last_select_ts, last_select_ts_raw;
static double last_select_ts_err;
/* ================================================== */ /* ================================================== */
@@ -109,9 +106,6 @@ static SCH_TimeoutID next_tqe_id;
/* Pointer to head of free list */ /* Pointer to head of free list */
static TimerQueueEntry *tqe_free_list = NULL; static TimerQueueEntry *tqe_free_list = NULL;
/* Timestamp when was last timeout dispatched for each class */
static struct timeval last_class_dispatch[SCH_NumberOfClasses];
/* ================================================== */ /* ================================================== */
static int need_to_exit; static int need_to_exit;
@@ -122,8 +116,9 @@ static void
handle_slew(struct timeval *raw, handle_slew(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *anything); void *anything);
/* ================================================== */ /* ================================================== */
@@ -131,6 +126,7 @@ handle_slew(struct timeval *raw,
void void
SCH_Initialise(void) SCH_Initialise(void)
{ {
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
n_read_fds = 0; n_read_fds = 0;
@@ -144,12 +140,9 @@ SCH_Initialise(void)
LCL_AddParameterChangeHandler(handle_slew, NULL); LCL_AddParameterChangeHandler(handle_slew, NULL);
LCL_ReadRawTime(&last_select_ts_raw);
last_select_ts = last_select_ts_raw;
srandom(last_select_ts.tv_sec << 16 ^ last_select_ts.tv_usec);
initialised = 1; initialised = 1;
return;
} }
@@ -158,6 +151,7 @@ SCH_Initialise(void)
void void
SCH_Finalise(void) { SCH_Finalise(void) {
initialised = 0; initialised = 0;
return; /* Nothing to do for now */
} }
/* ================================================== */ /* ================================================== */
@@ -167,15 +161,16 @@ SCH_AddInputFileHandler
(int fd, SCH_FileHandler handler, SCH_ArbitraryArgument arg) (int fd, SCH_FileHandler handler, SCH_ArbitraryArgument arg)
{ {
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
if (fd >= FD_SETSIZE) }
LOG_FATAL(LOGF_Scheduler, "Too many file descriptors");
/* Don't want to allow the same fd to register a handler more than /* Don't want to allow the same fd to register a handler more than
once without deleting a previous association - this suggests once without deleting a previous association - this suggests
a bug somewhere else in the program. */ a bug somewhere else in the program. */
assert(!FD_ISSET(fd, &read_fds)); if (FD_ISSET(fd, &read_fds)) {
CROAK("File handler already registered");
}
++n_read_fds; ++n_read_fds;
@@ -187,6 +182,8 @@ SCH_AddInputFileHandler
if ((fd + 1) > one_highest_fd) { if ((fd + 1) > one_highest_fd) {
one_highest_fd = fd + 1; one_highest_fd = fd + 1;
} }
return;
} }
@@ -197,10 +194,14 @@ SCH_RemoveInputFileHandler(int fd)
{ {
int fds_left, fd_to_check; int fds_left, fd_to_check;
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
}
/* Check that a handler was registered for the fd in question */ /* Check that a handler was registered for the fd in question */
assert(FD_ISSET(fd, &read_fds)); if (!FD_ISSET(fd, &read_fds)) {
CROAK("File handler not registered");
}
--n_read_fds; --n_read_fds;
@@ -217,20 +218,9 @@ SCH_RemoveInputFileHandler(int fd)
} }
one_highest_fd = fd_to_check; one_highest_fd = fd_to_check;
}
/* ================================================== */ return;
void
SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw)
{
if (cooked) {
*cooked = last_select_ts;
if (err)
*err = last_select_ts_err;
}
if (raw)
*raw = last_select_ts_raw;
} }
/* ================================================== */ /* ================================================== */
@@ -264,6 +254,7 @@ release_tqe(TimerQueueEntry *node)
{ {
node->next = tqe_free_list; node->next = tqe_free_list;
tqe_free_list = node; tqe_free_list = node;
return;
} }
/* ================================================== */ /* ================================================== */
@@ -274,7 +265,9 @@ SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler handler, SCH_ArbitraryArgu
TimerQueueEntry *new_tqe; TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
}
new_tqe = allocate_tqe(); new_tqe = allocate_tqe();
@@ -315,8 +308,9 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
{ {
struct timeval now, then; struct timeval now, then;
assert(initialised); if (!initialised) {
assert(delay >= 0.0); CROAK("Should be initialised");
}
LCL_ReadRawTime(&now); LCL_ReadRawTime(&now);
UTI_AddDoubleToTimeval(&now, delay, &then); UTI_AddDoubleToTimeval(&now, delay, &then);
@@ -327,35 +321,23 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg
/* ================================================== */ /* ================================================== */
SCH_TimeoutID SCH_TimeoutID
SCH_AddTimeoutInClass(double min_delay, double separation, double randomness, SCH_AddTimeoutInClass(double min_delay, double separation,
SCH_TimeoutClass class, SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg) SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
{ {
TimerQueueEntry *new_tqe; TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
struct timeval now; struct timeval now;
double diff, r; double diff;
double new_min_delay; double new_min_delay;
assert(initialised); if (!initialised) {
assert(min_delay >= 0.0); CROAK("Should be initialised");
assert(class < SCH_NumberOfClasses);
if (randomness > 0.0) {
r = random() % 0xffff / (0xffff - 1.0) * randomness + 1.0;
min_delay *= r;
separation *= r;
} }
LCL_ReadRawTime(&now); LCL_ReadRawTime(&now);
new_min_delay = min_delay; new_min_delay = min_delay;
/* Check the separation from the last dispatched timeout */
UTI_DiffTimevalsToDouble(&diff, &now, &last_class_dispatch[class]);
if (diff < separation && diff >= 0.0 && diff + new_min_delay < separation) {
new_min_delay = separation - diff;
}
/* Scan through list for entries in the same class and increase min_delay /* Scan through list for entries in the same class and increase min_delay
if necessary to keep at least the separation away */ if necessary to keep at least the separation away */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) { for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
@@ -365,7 +347,8 @@ SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
if (new_min_delay - diff < separation) { if (new_min_delay - diff < separation) {
new_min_delay = diff + separation; new_min_delay = diff + separation;
} }
} else { }
if (new_min_delay < diff) {
if (diff - new_min_delay < separation) { if (diff - new_min_delay < separation) {
new_min_delay = diff + separation; new_min_delay = diff + separation;
} }
@@ -404,8 +387,13 @@ void
SCH_RemoveTimeout(SCH_TimeoutID id) SCH_RemoveTimeout(SCH_TimeoutID id)
{ {
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
int ok;
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
}
ok = 0;
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) { for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
@@ -422,57 +410,48 @@ SCH_RemoveTimeout(SCH_TimeoutID id)
/* Release memory back to the operating system */ /* Release memory back to the operating system */
release_tqe(ptr); release_tqe(ptr);
ok = 1;
break; break;
} }
} }
assert(ok);
} }
/* ================================================== */ /* ================================================== */
/* Try to dispatch any timeouts that have already gone by, and /* The current time (now) has to be passed in from the
keep going until all are done. (The earlier ones may take so caller to avoid race conditions */
long to do that the later ones come around by the time they are
completed). */
static void static int
dispatch_timeouts(struct timeval *now) { dispatch_timeouts(struct timeval *now) {
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
SCH_TimeoutHandler handler; int n_done = 0;
SCH_ArbitraryArgument arg;
int n_done = 0, n_entries_on_start = n_timer_queue_entries;
while (1) {
LCL_ReadRawTime(now);
if (!(n_timer_queue_entries > 0 &&
UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
break;
}
while ((n_timer_queue_entries > 0) &&
(UTI_CompareTimevals(now, &(timer_queue.next->tv)) >= 0)) {
ptr = timer_queue.next; ptr = timer_queue.next;
last_class_dispatch[ptr->class] = *now;
handler = ptr->handler;
arg = ptr->arg;
SCH_RemoveTimeout(ptr->id);
/* Dispatch the handler */ /* Dispatch the handler */
(handler)(arg); (ptr->handler)(ptr->arg);
/* Increment count of timeouts handled */ /* Increment count of timeouts handled */
++n_done; ++n_done;
/* If more timeouts were handled than there were in the timer queue on /* Unlink entry from the queue */
start and there are now, assume some code is scheduling timeouts with ptr->prev->next = ptr->next;
negative delays and abort. Make the actual limit higher in case the ptr->next->prev = ptr->prev;
machine is temporarily overloaded and dispatching the handlers takes
more time than was delay of a scheduled timeout. */ /* Decrement count of entries in queue */
if (n_done > n_timer_queue_entries * 4 && --n_timer_queue_entries;
n_done > n_entries_on_start * 4) {
LOG_FATAL(LOGF_Scheduler, "Possible infinite loop in scheduling"); /* Delete entry */
} release_tqe(ptr);
} }
return n_done;
} }
/* ================================================== */ /* ================================================== */
@@ -505,85 +484,25 @@ static void
handle_slew(struct timeval *raw, handle_slew(struct timeval *raw,
struct timeval *cooked, struct timeval *cooked,
double dfreq, double dfreq,
double afreq,
double doffset, double doffset,
LCL_ChangeType change_type, int is_step_change,
void *anything) void *anything)
{ {
TimerQueueEntry *ptr; TimerQueueEntry *ptr;
double delta; struct timeval T1;
int i;
if (change_type != LCL_ChangeAdjust) { if (is_step_change) {
/* Make sure this handler is invoked first in order to not shift new timers /* We're not interested in anything else - it won't affect the
added from other handlers */ functionality of timer event dispatching. If a step change
assert(LCL_IsFirstParameterChangeHandler(handle_slew)); occurs, just shift all the timeouts by the offset */
/* If a step change occurs, just shift all raw time stamps by the offset */
for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) { for (ptr = timer_queue.next; ptr != &timer_queue; ptr = ptr->next) {
UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &ptr->tv); UTI_AddDoubleToTimeval(&ptr->tv, -doffset, &T1);
ptr->tv = T1;
} }
for (i = 0; i < SCH_NumberOfClasses; i++) {
UTI_AddDoubleToTimeval(&last_class_dispatch[i], -doffset, &last_class_dispatch[i]);
}
UTI_AddDoubleToTimeval(&last_select_ts_raw, -doffset, &last_select_ts_raw);
} }
UTI_AdjustTimeval(&last_select_ts, cooked, &last_select_ts, &delta, dfreq, doffset);
}
/* ================================================== */
#define JUMP_DETECT_THRESHOLD 10
static int
check_current_time(struct timeval *prev_raw, struct timeval *raw, int timeout,
struct timeval *orig_select_tv,
struct timeval *rem_select_tv)
{
struct timeval elapsed_min, elapsed_max;
double step, elapsed;
/* Get an estimate of the time spent waiting in the select() call. On some
systems (e.g. Linux) the timeout timeval is modified to return the
remaining time, use that information. */
if (timeout) {
elapsed_max = elapsed_min = *orig_select_tv;
} else if (rem_select_tv && rem_select_tv->tv_sec >= 0 &&
rem_select_tv->tv_sec <= orig_select_tv->tv_sec &&
(rem_select_tv->tv_sec != orig_select_tv->tv_sec ||
rem_select_tv->tv_usec != orig_select_tv->tv_usec)) {
UTI_DiffTimevals(&elapsed_min, orig_select_tv, rem_select_tv);
elapsed_max = elapsed_min;
} else {
if (rem_select_tv)
elapsed_max = *orig_select_tv;
else
UTI_DiffTimevals(&elapsed_max, raw, prev_raw);
elapsed_min.tv_sec = 0;
elapsed_min.tv_usec = 0;
}
if (last_select_ts_raw.tv_sec + elapsed_min.tv_sec >
raw->tv_sec + JUMP_DETECT_THRESHOLD) {
LOG(LOGS_WARN, LOGF_Scheduler, "Backward time jump detected!");
} else if (prev_raw->tv_sec + elapsed_max.tv_sec + JUMP_DETECT_THRESHOLD <
raw->tv_sec) {
LOG(LOGS_WARN, LOGF_Scheduler, "Forward time jump detected!");
} else {
return 1;
}
UTI_DiffTimevalsToDouble(&step, &last_select_ts_raw, raw);
UTI_TimevalToDouble(&elapsed_min, &elapsed);
step += elapsed;
/* Cooked time may no longer be valid after dispatching the handlers */
LCL_NotifyExternalTimeStep(raw, raw, step, fabs(step));
return 0;
} }
/* ================================================== */ /* ================================================== */
@@ -591,75 +510,70 @@ check_current_time(struct timeval *prev_raw, struct timeval *raw, int timeout,
void void
SCH_MainLoop(void) SCH_MainLoop(void)
{ {
fd_set rd; fd_set rd, wr, ex;
int status, errsv; int status;
struct timeval tv, saved_tv, *ptv; struct timeval tv, *ptv;
struct timeval now, saved_now, cooked; struct timeval now;
double err;
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
}
while (!need_to_exit) { while (!need_to_exit) {
/* Dispatch timeouts and fill now with current raw time */
dispatch_timeouts(&now);
saved_now = now;
/* The timeout handlers may request quit */ /* Copy current set of read file descriptors */
if (need_to_exit) memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
break;
/* 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
completed). */
do {
LCL_ReadRawTime(&now);
} while (dispatch_timeouts(&now) > 0);
/* Check whether there is a timeout and set it up */ /* Check whether there is a timeout and set it up */
if (n_timer_queue_entries > 0) { if (n_timer_queue_entries > 0) {
UTI_DiffTimevals(&tv, &(timer_queue.next->tv), &now); UTI_DiffTimevals(&tv, &(timer_queue.next->tv), &now);
ptv = &tv; ptv = &tv;
assert(tv.tv_sec > 0 || tv.tv_usec > 0);
saved_tv = tv;
} else { } else {
ptv = NULL; ptv = NULL;
/* This is needed to fix a compiler warning */
saved_tv.tv_sec = 0;
} }
/* if there are no file descriptors being waited on and no /* if there are no file descriptors being waited on and no
timeout set, this is clearly ridiculous, so stop the run */ timeout set, this is clearly ridiculous, so stop the run */
if (!ptv && !n_read_fds) {
LOG_FATAL(LOGF_Scheduler, "Nothing to do"); if (!ptv && (n_read_fds == 0)) {
LOG_FATAL(LOGF_Scheduler, "No descriptors or timeout to wait for");
} }
/* Copy current set of read file descriptors */ status = select(one_highest_fd, &rd, &wr, &ex, ptv);
memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
status = select(one_highest_fd, &rd, NULL, NULL, ptv);
errsv = errno;
LCL_ReadRawTime(&now);
LCL_CookTime(&now, &cooked, &err);
/* Check if the time didn't jump unexpectedly */
if (!check_current_time(&saved_now, &now, status == 0, &saved_tv, ptv)) {
/* Cook the time again after handling the step */
LCL_CookTime(&now, &cooked, &err);
}
last_select_ts_raw = now;
last_select_ts = cooked;
last_select_ts_err = err;
if (status < 0) { if (status < 0) {
if (!need_to_exit && errsv != EINTR) { CROAK("Status < 0 after select");
LOG_FATAL(LOGF_Scheduler, "select() failed : %s", strerror(errsv));
}
} else if (status > 0) { } else if (status > 0) {
/* A file descriptor is ready to read */ /* A file descriptor is ready to read */
dispatch_filehandlers(status, &rd); dispatch_filehandlers(status, &rd);
} else { } else {
if (status != 0) {
CROAK("Unexpected value from select");
}
/* No descriptors readable, timeout must have elapsed. /* No descriptors readable, timeout must have elapsed.
Therefore, tv must be non-null */ Therefore, tv must be non-null */
assert(ptv); if (!ptv) {
CROAK("No descriptors or timeout?");
}
/* There's nothing to do here, since the timeouts /* There's nothing to do here, since the timeouts
will be dispatched at the top of the next loop will be dispatched at the top of the next loop
@@ -667,6 +581,9 @@ SCH_MainLoop(void)
} }
} }
return;
} }
/* ================================================== */ /* ================================================== */
@@ -674,7 +591,9 @@ SCH_MainLoop(void)
void void
SCH_QuitProgram(void) SCH_QuitProgram(void)
{ {
assert(initialised); if (!initialised) {
CROAK("Should be initialised");
}
need_to_exit = 1; need_to_exit = 1;
} }

24
sched.h
View File

@@ -1,4 +1,8 @@
/* /*
$Header: /cvs/src/chrony/sched.h,v 1.10 2002/02/28 23:27:14 richard Exp $
=======================================================================
chronyd/chronyc - Programs for keeping computer clocks accurate. chronyd/chronyc - Programs for keeping computer clocks accurate.
********************************************************************** **********************************************************************
@@ -15,7 +19,7 @@
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
********************************************************************** **********************************************************************
@@ -31,12 +35,10 @@
typedef unsigned long SCH_TimeoutID; typedef unsigned long SCH_TimeoutID;
typedef enum { typedef unsigned long SCH_TimeoutClass;
SCH_ReservedTimeoutValue = 0, static const SCH_TimeoutClass SCH_ReservedTimeoutValue = 0;
SCH_NtpSamplingClass, static const SCH_TimeoutClass SCH_NtpSamplingClass = 1;
SCH_NtpBroadcastClass, static const SCH_TimeoutClass SCH_NtpBroadcastClass = 2;
SCH_NumberOfClasses /* needs to be last */
} SCH_TimeoutClass;
typedef void* SCH_ArbitraryArgument; typedef void* SCH_ArbitraryArgument;
typedef void (*SCH_FileHandler)(SCH_ArbitraryArgument); typedef void (*SCH_FileHandler)(SCH_ArbitraryArgument);
@@ -58,9 +60,6 @@ extern void SCH_AddInputFileHandler
); );
extern void SCH_RemoveInputFileHandler(int fd); extern void SCH_RemoveInputFileHandler(int fd);
/* Get the time stamp taken after a file descriptor became ready or a timeout expired */
extern void SCH_GetLastEventTime(struct timeval *cooked, double *err, struct timeval *raw);
/* This queues a timeout to elapse at a given (raw) local time */ /* This queues a timeout to elapse at a given (raw) local time */
extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument); extern SCH_TimeoutID SCH_AddTimeout(struct timeval *tv, SCH_TimeoutHandler, SCH_ArbitraryArgument);
@@ -69,9 +68,8 @@ extern SCH_TimeoutID SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler, SCH
/* This queues a timeout in a particular class, ensuring that the /* This queues a timeout in a particular class, ensuring that the
expiry time is at least a given separation away from any other expiry time is at least a given separation away from any other
timeout in the same class, given randomness is added to the delay timeout in the same class */
and separation */ extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation,
extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
SCH_TimeoutClass class, SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument); SCH_TimeoutHandler handler, SCH_ArbitraryArgument);

782
sources.c

File diff suppressed because it is too large Load Diff

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