aboutsummaryrefslogtreecommitdiff
path: root/contrib/xntpd
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/xntpd')
-rw-r--r--contrib/xntpd/COPYRIGHT6
-rw-r--r--contrib/xntpd/Makefile.inc4
-rw-r--r--contrib/xntpd/README.FreeBSD76
-rw-r--r--contrib/xntpd/RELNOTES6
-rw-r--r--contrib/xntpd/VERSION2
-rw-r--r--contrib/xntpd/authstuff/authspeed.c2
-rw-r--r--contrib/xntpd/compilers/.keep_me0
-rw-r--r--contrib/xntpd/conf/Config.local4
-rw-r--r--contrib/xntpd/conf/Config.plain190
-rw-r--r--contrib/xntpd/doc/README.kern2015
-rw-r--r--contrib/xntpd/doc/notes.txt2
-rw-r--r--contrib/xntpd/gadget/.keep_me0
-rw-r--r--contrib/xntpd/hints/.keep_me0
-rw-r--r--contrib/xntpd/include/l_stdlib.h8
-rw-r--r--contrib/xntpd/include/ntp.h30
-rw-r--r--contrib/xntpd/include/ntp_control.h1
-rw-r--r--contrib/xntpd/include/ntp_if.h4
-rwxr-xr-xcontrib/xntpd/include/ntp_in.h259
-rw-r--r--contrib/xntpd/include/ntp_io.h1
-rw-r--r--contrib/xntpd/include/ntp_machine.h82
-rw-r--r--contrib/xntpd/include/ntp_request.h95
-rw-r--r--contrib/xntpd/include/ntp_stdlib.h1
-rw-r--r--contrib/xntpd/include/ntp_timex.h265
-rw-r--r--contrib/xntpd/include/ntpd.h13
-rw-r--r--contrib/xntpd/include/parse.h82
-rw-r--r--contrib/xntpd/kernel/.keep_me0
-rw-r--r--contrib/xntpd/lib/Makefile4
-rw-r--r--contrib/xntpd/lib/clocktypes.c2
-rw-r--r--contrib/xntpd/lib/netof.c25
-rw-r--r--contrib/xntpd/lib/numtohost.c5
-rw-r--r--contrib/xntpd/lib/systime.c3
-rw-r--r--contrib/xntpd/machines/.keep_me0
-rw-r--r--contrib/xntpd/ntpdate/ntpdate.h4
-rw-r--r--contrib/xntpd/ntpq/ntpq.c76
-rw-r--r--contrib/xntpd/parse/README.new_clocks212
-rw-r--r--contrib/xntpd/parse/README.parse_clocks263
-rw-r--r--contrib/xntpd/parse/clk_dcf7000.c7
-rw-r--r--contrib/xntpd/parse/clk_meinberg.c22
-rw-r--r--contrib/xntpd/parse/clk_rawdcf.c16
-rw-r--r--contrib/xntpd/parse/clk_schmid.c12
-rw-r--r--contrib/xntpd/parse/clk_trimble.c5
-rw-r--r--contrib/xntpd/parse/parse.c35
-rw-r--r--contrib/xntpd/parse/parse_conf.c7
-rw-r--r--contrib/xntpd/parse/parsesolaris.c35
-rw-r--r--contrib/xntpd/parse/parsestreams.c78
-rw-r--r--contrib/xntpd/parse/util/parsetest.c18
-rw-r--r--contrib/xntpd/parse/util/testdcf.c4
-rw-r--r--contrib/xntpd/ppsclock/ppstest/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/genassym/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/os/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sun/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sun4c/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sun4c/conf/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sun4m/conf/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sundev/.keep_me0
-rw-r--r--contrib/xntpd/ppsclock/sys/sys/.keep_me0
-rw-r--r--contrib/xntpd/refclocks/rclk.TRAK29
-rwxr-xr-xcontrib/xntpd/scripts/Guess.sh8
-rw-r--r--contrib/xntpd/scripts/README2
-rw-r--r--contrib/xntpd/scripts/stats/README35
-rw-r--r--contrib/xntpd/scripts/stats/dupe.awk3
-rw-r--r--contrib/xntpd/scripts/stats/ensemble.S5
-rw-r--r--contrib/xntpd/scripts/stats/etf.S15
-rw-r--r--contrib/xntpd/scripts/stats/itf.S5
-rw-r--r--contrib/xntpd/scripts/stats/loop.S7
-rw-r--r--contrib/xntpd/scripts/stats/loop.awk10
-rw-r--r--contrib/xntpd/scripts/stats/psummary.awk2
-rw-r--r--contrib/xntpd/scripts/stats/rms.awk41
-rwxr-xr-xcontrib/xntpd/scripts/stats/summary.sh95
-rw-r--r--contrib/xntpd/scripts/stats/tdata.S5
-rwxr-xr-xcontrib/xntpd/scripts/support/bin/monl3
-rw-r--r--contrib/xntpd/util/ntptime.c85
-rw-r--r--contrib/xntpd/util/tickadj.c71
-rw-r--r--contrib/xntpd/xntpd/Makefile4
-rw-r--r--contrib/xntpd/xntpd/minpoll (renamed from contrib/xntpd/adjtime/.keep_me)0
-rw-r--r--contrib/xntpd/xntpd/ntp_config.c201
-rw-r--r--contrib/xntpd/xntpd/ntp_control.c35
-rw-r--r--contrib/xntpd/xntpd/ntp_intres.c15
-rw-r--r--contrib/xntpd/xntpd/ntp_io.c95
-rw-r--r--contrib/xntpd/xntpd/ntp_loopfilter.c252
-rw-r--r--contrib/xntpd/xntpd/ntp_monitor.c51
-rw-r--r--contrib/xntpd/xntpd/ntp_peer.c26
-rw-r--r--contrib/xntpd/xntpd/ntp_proto.c225
-rw-r--r--contrib/xntpd/xntpd/ntp_refclock.c30
-rw-r--r--contrib/xntpd/xntpd/ntp_request.c175
-rw-r--r--contrib/xntpd/xntpd/ntp_restrict.c166
-rw-r--r--contrib/xntpd/xntpd/ntp_unixclock.c32
-rw-r--r--contrib/xntpd/xntpd/ntpd.c20
-rw-r--r--contrib/xntpd/xntpd/refclock_chu.c19
-rw-r--r--contrib/xntpd/xntpd/refclock_conf.c8
-rw-r--r--contrib/xntpd/xntpd/refclock_irig.c6
-rw-r--r--contrib/xntpd/xntpd/refclock_msfees.c2
-rw-r--r--contrib/xntpd/xntpd/refclock_parse.c103
-rw-r--r--contrib/xntpd/xntpd/refclock_trak.c1006
-rw-r--r--contrib/xntpd/xntpdc/ntpdc.c12
-rw-r--r--contrib/xntpd/xntpdc/ntpdc_ops.c297
-rw-r--r--contrib/xntpd/xntpres/xntpres.c18
97 files changed, 5555 insertions, 1645 deletions
diff --git a/contrib/xntpd/COPYRIGHT b/contrib/xntpd/COPYRIGHT
index 711a8f1efcb4..b9ce773f163a 100644
--- a/contrib/xntpd/COPYRIGHT
+++ b/contrib/xntpd/COPYRIGHT
@@ -1,6 +1,6 @@
/******************************************************************************
* *
- * Copyright (c) David L. Mills 1992, 1993, 1994 *
+ * Copyright (c) David L. Mills 1992, 1993, 1994 *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation for any purpose and without fee is hereby granted, provided *
@@ -55,4 +55,6 @@
* Torsten Duwe <duwe@immd4.informatik.uni-erlangen.de> (Linux Port)
* Paul A Vixie <vixie@vix.com> (TrueTime GPS driver)
* Jim Jagielski <jim@jagubox.gsfc.nasa.gov> (A/UX port)
-*/
+ * Ray Schnitzler <schnitz@unipress.com> (First pass at a Unixware1 port.)
+ * Ajit Thyagarajan <ajit@ee.udel.edu> (IP multicast support)
+ */
diff --git a/contrib/xntpd/Makefile.inc b/contrib/xntpd/Makefile.inc
index 0983df967f72..f38f0a91a3dc 100644
--- a/contrib/xntpd/Makefile.inc
+++ b/contrib/xntpd/Makefile.inc
@@ -1,7 +1,7 @@
DEFS_LOCAL=-DREFCLOCK -DPARSE
-NTPDEFS= -DSYS_FREEBSD -DSYS_386BSD -DHAVE_TERMIOS
+NTPDEFS= -DSYS_FREEBSD -DSYS_386BSD
AUTHDEFS= -DMD5
CLOCKDEFS= -DLOCAL_CLOCK -DPST -DWWVB -DAS2201 -DGOES -DGPSTM -DOMEGA \
- -DLEITCH
+ -DLEITCH -DTRAK
CFLAGS+= ${NTPDEFS} ${DEFS_LOCAL} ${AUTHDEFS} ${CLOCKDEFS} ${COPTS}
BINDIR?= /usr/sbin
diff --git a/contrib/xntpd/README.FreeBSD b/contrib/xntpd/README.FreeBSD
index 437d4783d1ed..8fd237e1640c 100644
--- a/contrib/xntpd/README.FreeBSD
+++ b/contrib/xntpd/README.FreeBSD
@@ -1,6 +1,8 @@
+ $Id: README.FreeBSD,v 1.7 1994/04/21 21:10:20 wollman Exp $
+
This version of NTP was converted to the BSD-style Makefile system by
Garrett Wollman (wollman@freefall.cdrom.com); it is based on version
-3.3z (late beta) from the University of Delaware.
+3.3s (late beta) from the University of Delaware.
Besides the Makefile changes, the DES code has been completely removed
in order to make this code exportable. If you have a legal copy of
@@ -8,3 +10,75 @@ in order to make this code exportable. If you have a legal copy of
to the AUTHDEFS in Makefile.inc.
You can change CLOCKDEFS in the same file to add other reference clocks.
+
+This version of xntpd knows how to talk to the kernelized NTP PLL which is
+present in versions of FreeBSD-current after 21 April 1994. When this code
+is more widely released, I'll provide the patches to Mills.
+
+----------------------------------------------------
+Support for Conrad electronic's "DCF-77 Uhr, Mobil".
+----------------------------------------------------
+Conrad electronic in Germany,, Phone (+49) 962230111 (?), sells a gadget
+called "DCF77 Uhr, mobil", which is a DCF77 timecode receiver with a
+rs-232 interface. The price is around DM130.
+ 9-pin interface is Order# 97 94 57 66
+ 25-pin interface is Order# 97 94 81 66
+
+You must define
+ -DDCF77 -DPPS -DFREEBSD_CONRAD -DDEBUG
+when you compile xntpd. You can later remove -DDEBUG, if you feel like it.
+
+You must also have
+ options COM_BIDIR
+defined in your kernel, and finally the ttyport you intend to use must
+have special interrupt vector:
+ device sio1 at isa? port "IO_COM2" tty irq 3 vector siointrts
+ ^^^^^^^^^^^^
+connect the radio-clock to the tty port and link it to /dev/refclock-0:
+
+ cd /dev
+ sh MAKEDEV cua1
+ ln -s /dev/cua01 /dev/refclock-0
+
+make a directory to gather statistics in:
+ mkdir /var/tmp/ntp
+
+Create a /etc/ntp.conf along these lines:
+
+ # DCF77 without PPS
+ server 127.127.8.20
+ # DCF77 with PPS
+ #server 127.127.8.148 prefer
+
+ driftfile /var/tmp/ntp/ntp.drift
+ statsdir /var/tmp/ntp
+ statistics loopstats
+ statistics peerstats
+ statistics clockstats
+ filegen peerstats file peerstats type day enable
+ filegen loopstats file loopstats type day enable
+ filegen clockstats file clockstats type day enable
+
+Try to start it:
+ comcontrol ttyd1 bidir
+ tickadj -A
+ xntpd -d -d -d
+
+You should see the red LED flash on the receiver every second now. You
+may have to experiment a bit with the location, and possibly adjust the
+minute variable resistor inside to get a good signal. Be aware, that just
+because you see the light flash, is not the same as the signal being
+received by the computer. The chip doing the work in the reciver uses
+less than 1 micro-ampere, so even if RTS isn't pulled low, it will happily
+receive, but be unable to buffer the signal to the rs-232 levels needed.
+
+You can see what's going on in /var/log/messages, and query the
+daemon using xntpdc and ntpq, in particular the "clockvar" command
+of ntpq will tell about the clocks healt.
+
+I live in Slagelse, Denmark, which is ~1000 Km from Mainflingen, yet
+I have +/- 2 ms precision from this cheap gadget. If you have a very
+stable signal, you can use the 'pps' address instead to improve your
+timing.
+
+Have fun... Poul-Henning Kamp <phk@login.dkuug.dk>
diff --git a/contrib/xntpd/RELNOTES b/contrib/xntpd/RELNOTES
index 1b9d9c02c3b3..411ef452195b 100644
--- a/contrib/xntpd/RELNOTES
+++ b/contrib/xntpd/RELNOTES
@@ -31,6 +31,10 @@ this distribution. To make these programs:
For custom tailored configuration copying Config.local.dist to Config.local
and editing Config.local to suit the local needs is neccessary (at most
3 lines to change), or use one of the make's above and then tweak it.
+ Config.local can also be used to override common settings from the
+ machines/* files like the AUTHDEFS= to select very specific configurations.
+ Please use this feature with care and don't be disappointed if it doesn't
+ work the way you expect.
(2) Type "make" to compile everything of general interest. Expect few or
no warnings using cc and a moderate level of warnings using gcc.
@@ -140,6 +144,7 @@ the meal. The converse is not always true.
PC BSD/386 1.0 gcc LOCAL_CLOCK possibly see "build problems"
PC Linux (pl14) gcc LOCAL_CLOCK (dw 93/10/30)
PC Dell SVR4 v2.2 gcc ? (tl 93/12/30)
+ PC Unixware1/SVR4 cc no tickadj, ? (ras 93/04/11)
NCR3445 NCR SVR4 cc LOCAL_CLOCK (tm 93/11/29)
pb: Piete Brooks
@@ -149,6 +154,7 @@ the meal. The converse is not always true.
tl: Tony Lill <ajlill@tlill.hookup.net>
tm: Tom Moore <Tom.Moore@DaytonOH.NCR.COM>
jmj: Jim Jagielski <jim@jagubox.gsfc.nasa.gov>
+ ras: Ray Schnitzler <schnitz@unipress.com>
Build Problems (and workaround):
diff --git a/contrib/xntpd/VERSION b/contrib/xntpd/VERSION
index 85051bd4db45..c145b870451f 100644
--- a/contrib/xntpd/VERSION
+++ b/contrib/xntpd/VERSION
@@ -1 +1 @@
-version=3.3c (beta)
+version=3.3s (beta multicast)
diff --git a/contrib/xntpd/authstuff/authspeed.c b/contrib/xntpd/authstuff/authspeed.c
index c83d5b24497e..ecddbcd96ba1 100644
--- a/contrib/xntpd/authstuff/authspeed.c
+++ b/contrib/xntpd/authstuff/authspeed.c
@@ -2,7 +2,7 @@
* authspeed - figure out how LONG it takes to do an NTP encryption
*/
-#if defined(SYS_HPUX) || defined(SYS_AUX3) || defined(SYS_AUX2) || defined(SOLARIS) || defined(SYS_SVR4) || defined(SYS_PTX)
+#if defined(SYS_HPUX) || defined(SYS_AUX3) || defined(SYS_AUX2) || defined(SOLARIS) || defined(SYS_SVR4) || defined(SYS_PTX) || defined(SYS_UNIXWARE1)
#define FAKE_RUSAGE
#endif
diff --git a/contrib/xntpd/compilers/.keep_me b/contrib/xntpd/compilers/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/compilers/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/conf/Config.local b/contrib/xntpd/conf/Config.local
index 12a6dfece755..22c12a36e90a 100644
--- a/contrib/xntpd/conf/Config.local
+++ b/contrib/xntpd/conf/Config.local
@@ -78,7 +78,7 @@ DEFS_OPT=-DDEBUG
# special distribution.
#
# Note: following line must always start with DEFS_LOCAL= $(DEFS_OPT)
-DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DPPSPPS -DKERNEL_PLL
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
#
# Radio clock support definitions (these only make sense if -DREFCLOCK
@@ -182,7 +182,7 @@ DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DPPSPPS -DKERNEL_PLL
# under Ultrix 4.2a/3. If the MX4200 is removed, all the rest compile on a DEC
# OSF/1 Alpha.
#
-CLOCKDEFS= -DLOCAL_CLOCK -DAS2201PPS -DCHUPPS -DGOES -DIRIG -DMX4200PPS -DOMEGA -DPSTCLK -DTPRO -DWWVBCLK -DMSFEESPPS -DLEITCH
+CLOCKDEFS= -DLOCAL_CLOCK -DAS2201PPS -DCHUPPS -DGOES -DIRIG -DMX4200PPS -DOMEGA -DPSTCLK -DTPRO -DWWVBCLK -DLEITCH
#
# Directory into which binaries should be installed (default /usr/local)
diff --git a/contrib/xntpd/conf/Config.plain b/contrib/xntpd/conf/Config.plain
new file mode 100644
index 000000000000..67dd70ad50e6
--- /dev/null
+++ b/contrib/xntpd/conf/Config.plain
@@ -0,0 +1,190 @@
+# This is the local configure file (distribution version).
+# You must modify it to fit your particular configuration
+# and name it Config.local
+# The following configuratiions can be auto-generated:
+#
+# make Config.local.green
+# make a Config.local that supports a local clock
+# (i.e. allow fallback to use of the CPU's own clock)
+# make Config.local.NO.clock
+# make a Config.local that supports no clocks
+#
+#
+# NOTE TO GREENHORNS
+#
+# For plug-'n-play and no radios or other complicated gadgetry,
+# use "make Config.local.green" as above.
+#
+# Following defines can be set in the DEFS_OPT= define:
+#
+# The flag -DDEBUG includes some debugging code. To use this, include
+# the define and start the daemon with one or more -d flags, depending
+# on your calibration of pearannoya. The daemon will not detach your
+# terminal in this case. Judicious use of grep will reduce the speaker
+# volume to bearable levels.
+#
+# To change the location of the configuration file, use a
+# -DCONFIG_FILE=\\"/local/etc/ntp.conf\\" or something similar.
+#
+# The -DSYSLOG_FILE defines allows logging messages that are normally
+# reported via syslof() in a file. The file name can be configured using
+# the configuration line "logfile <filename>" in CONFIG_FILE.
+#
+# There are three serial port system software interfaces, each of
+# which is peculiar to one or more Unix versions. Define
+# -DHAVE_SYSV_TTYS for basic System V compatibility; define -DSTREAM
+# for POSIX compatibility including System V Streams, and
+# HAVE_BSD_TTYS for 4.3bsd compatibility. Only one of these three
+# should be defined. If none are defined, HAVE_BSD_TTYS is assumed.
+# Usually these defines are already set correctly.
+#
+DEFS_OPT=-DDEBUG
+
+#
+# The DEFS_LOCAL define picks up all flags from DEFS_OPT (do not delete that)
+# and one of the following:
+#
+# The flag -DREFCLOCK causes the basic reference clock support to be
+# compiled into the daemon. If you set this you may also want to
+# configure the particular clock drivers you want in the CLOCKDEFS= line
+# below. This flag affects xntpd only. This define is included by
+# default when using the "make makeconfig" script.
+#
+# The next two sets of defines are meaningful only when radio clock
+# drivers or special 1-pps signals are to be used. For systems without
+# these features, these delicious complexities can be avoided. Ordinarily,
+# the "make makeconfig" script figures out which ones to use, but your
+# mileage may vary.
+#
+# There are three ways to utilize external 1-pps signals. Define
+# -DPPS to include just the pps routine, such as used by the DCF77(PARSE)
+# clock driver. Define -DPPSCLK to include a serial device driver
+# which avoids much of the jitter due to upper level port
+# processing. This requires a dedicated serial port and either the
+# tty_clock line discipline or tty_clk_streams module, both of
+# which are in the ./kernel directory. Define -DPPSCD to include a
+# special driver which intercepts carrier-detect transitions
+# generated by the pps signal. This requires a nondedicated serial
+# port and the ppsclock streams module in the ./kernel directory.
+# Only one of these three flags should be defined.
+#
+# The flag KERNEL_PLL causes code to be compiled for a special feature of
+# the kernel that (a) implements the phase-lock loop and (b) provides
+# a user interface to learn time, maximum error and estimated error.
+# See the file README.kern in the doc directory for further info.
+# This code is activated only if the relevant kernel features have
+# been configured; it does not affect operation of unmodified kernels.
+# To compile it, however, requires a few header files from the
+# special distribution.
+#
+# Note: following line must always start with DEFS_LOCAL= $(DEFS_OPT)
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
+
+#
+# Radio clock support definitions (these only make sense if -DREFCLOCK
+# used), which is normally the case. Note that a configuration can include
+# no clocks, more than one type of clock and even multiple clocks of the
+# same type.
+#
+# For most radio clocks operating with serial ports, accuracy can
+# be considerably improved through use of the tty_clk line
+# discipline or tty_clk_STREAMS streams module found in the
+# ./kernel directory. These gizmos capture a timestamp upon
+# occurrence of an intercept character and stuff it in the data
+# stream for the clock driver to munch. To select this mode,
+# postfix the driver name with the string CLK; that is, WWVB
+# becomes WWVBCLK. If more than one clock is in use, the CLK
+# postfix can be used with any or all of them.
+#
+# Alternatively, for the best accuracy, use the ppsclock streams
+# module in the ./ppsclock directory to steal the carrier-detect
+# transition and capture a precision timestamp. At present this
+# works only with SunOS 4.1.1 or later. To select this mode,
+# postfix the driver name with the string PPS; that is, AS2201
+# becomes AS2201PPS. If more than one clock is in use, the PPS
+# postfix should be used with only one of them. If any PPS
+# postfix is defined, the -DPPSPPS define should be used on the
+# DEFS above.
+#
+# Define -DLOCAL_CLOCK for a local pseudo-clock to masquerade as a
+# reference clock for those subnets without access to the real thing.
+# Works in all systems and requires no hardware support. This is defined
+# by default when using the "make makeconfig" script and greenhorn
+# configuraiton.
+#
+# Define -DPST for a PST/Traconex 1020 WWV/H receiver. The driver
+# supports both the CLK and PPS modes. It should work in all systems
+# with a serial port.
+#
+# Define -DWWVB for a Spectracom 8170 or Netclock/2 WWVB receiver. It
+# should work in all systems with a serial port. The driver supports
+# both the CLK and PPS modes if the requisite kernel support is installed.
+#
+# Define -DCHU for a special CHU receiver using an ordinary shortwave
+# radio. This requires the chu_clk line discipline or chu_clk_STREAMS
+# module in the ./kernel directory. At present, this driver works only
+# on SunOS4.1.x; operation in other systems has not been confirmed.
+# Construction details for a suitable modem can be found in the ./gadget
+# directory. The driver supports # neither the CLK nor PPS modes.
+#
+# Define -DPARSE for a DCF77/GPS(GENERIC) receiver. For best performance
+# this requires a special parsestreams STREAMS (SunOS 4.x) module in the
+# ./parse directory. Define -DPARSEPPS for PPS support via the
+# DCF77/GPS (GENERIC) receiver; also, define -DPPS in the DEFS above.
+# Define: -DCLOCK_MEINBERG for Meinberg clocks
+# -DCLOCK_SCHMID for Schmid receivers
+# -DCLOCK_DCF7000 for ELV DCF7000
+# -DCLOCK_RAWDCF for simple receivers (100/200ms pulses on Rx)
+# -DCLOCK_TRIMSV6 for Trimble SV6 GPS receiver
+#
+# Define -DMX4200PPS for a Magnavox 4200 GPS receiver. At present, this
+# driver works only on SunOS4.1.x with CPU serial ports only. The PPS
+# mode is required.
+#
+# Define -DAS2201 for an Austron 2200A or 2201A GPS receiver. It should
+# work in all systems with a serial port. The driver does not support the
+# CLK mode, but does support the PPS mode. If the radio is connected to
+# more than one machine, the PPS mode is required.
+#
+# Define -DGOES for a Kinemetrics/TrueTime 468-DC GOES receiver. This
+# driver is known to work with some other TrueTime products as well,
+# including the GPS-DC GPS receiver. It should work in all systems with
+# a serial port. The driver does not support the CLK mode, but does
+# support the PPS mode.
+#
+# Define -DOMEGA for a Kinemetrics/TrueTime OM-DC OMEGA receiver. It
+# should work in all systems with a serial port. The driver does not
+# support the CLK mode, but does support the PPS mode.
+#
+# Define -DTPRO for a KSI/Odetics TPRO-S IRIG-B timecode reader. This
+# requires the SunOS interface driver available from KSI. The driver
+# supports neither the CLK nor PPS modes.
+#
+# Define -DLEITCH for a Leitch CSD 5300 Master Clock System Driver for
+# the HP 5061B Cesium Clock. It should work in all systems with a serial
+# port. The driver does not support the CLK mode, but does support the
+# PPS mode.
+#
+# Define -DMSFEESPPS for an EES M201 MSF receiver. It currently only works
+# under SunOS 4.x with the PPSCD (ppsclock) STREAMS module, but the RCS
+# files on cl.cam.ac.uk still has support for CLK and CBREAK modes.
+#
+# Define -DIRIG for a IRIG-B timecode timecode using the audio codec of
+# the Sun SPARCstations. This requires a modified BSD audio driver and
+# exclusive access to the audio port. A memo describing how it works and
+# how to install the driver is in the README.irig file in the ./doc
+# directory.
+#
+# Note: The following defines result in compilation of all the above radio
+# clocks. This works on a Sun 4.1.x system which has tty_clk, chu_clk and
+# ppsclock STREAMS modules installed. If the trailing CLK and PPS suffixes
+# are removed and the IRIG, PARSE* and CLOCK* deleted, all of the rest compile
+# under Ultrix 4.2a/3. If the MX4200 is removed, all the rest compile on a DEC
+# OSF/1 Alpha.
+#
+CLOCKDEFS= -DLOCAL_CLOCK -DCHU -DGOES -DOMEGA -DPST -DWWVB -DLEITCH
+
+#
+# Directory into which binaries should be installed (default /usr/local)
+#
+BINDIR= /usr/local/bin
diff --git a/contrib/xntpd/doc/README.kern b/contrib/xntpd/doc/README.kern
index 1b791c325ccf..aac26fa2e62b 100644
--- a/contrib/xntpd/doc/README.kern
+++ b/contrib/xntpd/doc/README.kern
@@ -1,567 +1,756 @@
- Unix Kernel Modifications for Precision Timekeeping
-
- Revised 3 December 1993
-
-Note: This information file is included in the distributions for the
-SunOS, Ultrix and OSF/1 kernels and in the NTP Version 3 distribution
-(xntp3.tar.Z) as the file README.kern. Availability of the kernel
-distributions, which involve licensed code, will be announced
-separately. The NTP Version 3 distribution can be obtained via anonymous
-ftp from louie.udel.edu in the directory pub/ntp. In order to utilize
-all features of this distribution, the NTP version number should be 3.3
+ A Kernel Model for Precision Timekeeping
+
+ Revised 3 April 1994
+
+Note: This memorandum is a substantial revision of RFC-1589, "A Kernel
+Model for Precision Timekeeping," March, 1994. It includes several
+changes to the daemon and user interfaces, as well as a new feature
+which disciplines the CPU clock oscillator in both time and frequency to
+a source of precision time signals. This memorandum is included in the
+distributions for the SunOS, Ultrix and OSF/1 kernels and in the NTP
+Version 3 distribution (xntp3.v.tar.Z) as the file README.kern, where v
+is the version identifier. Availability of the kernel distributions,
+which involve licensed code, will be announced separately. The NTP
+Version 3 distribution can be obtained via anonymous ftp from
+louie.udel.edu in the directory pub/ntp. In order to utilize all
+features of this distribution, the NTP version identifier should be 3q
or later.
+Overview
+
+This memorandum describes an engineering model which implements a
+precision time-of-day function for a generic operating system. The model
+is based on the principles of disciplined oscillators and phase-lock
+loops (PLL) and frequency-lock loops (FLL) often found in the
+engineering literature. It has been implemented in the Unix kernels for
+several workstations, including those made by Sun Microsystems and
+Digital Equipment. The model changes the way the system clock is
+adjusted in time and frequency, as well as provides mechanisms to
+discipline its frequency to an external precision timing source. The
+model incorporates a generic system-call interface for use with the
+Network Time Protocol (NTP) or similar time synchronization protocol.
+The NTP Version 3 daemon xntpd operates with this model to provide
+synchronization limited in principle only by the accuracy and stability
+of the external timing source.
+
+This memorandum does not obsolete or update any RFC. It does not propose
+a standard protocol, specification or algorithm. It is intended to
+provoke comment, refinement and implementations for kernels not
+considered herein. While a working knowledge of NTP is not required for
+an understanding of the design principles or implementation of the
+model, it may be helpful in understanding how the model behaves in a
+fully functional timekeeping system. The architecture and design of NTP
+is described in [MIL91], while the current NTP Version 3 protocol
+specification is given in RFC-1305 [MIL92a] and a subset of the
+protocol, the Simple Network Time Protocol (SNTP), is given in RFC-1361
+[MIL92c].
+
+The model has been implemented in the Unix kernels for three Sun
+Microsystems and Digital Equipment workstations. In addition, for the
+Digital machines the model provides improved precision to one
+microsecond (us). Since these specific implementations involve
+modifications to licensed code, they cannot be provided directly.
+Inquiries should be directed to the manufacturer's representatives.
+However, the engineering model for these implementations, including a
+simulator with code segments almost identical to the implementations,
+but not involving licensed code, is available via anonymous FTP from
+host louie.udel.edu in the directory pub/ntp and compressed tar archive
+kernel.tar.Z. The NTP Version 3 distribution can be obtained via
+anonymous ftp from the same host and directory in the compressed tar
+archive xntp3.3q.tar.Z, where the version number shown as 3.3q may be
+adjusted for new versions as they occur.
+
1. Introduction
-This memo describes modifications to certain SunOS, Ultrix and OSF/1
-kernel software that manage the system clock and timer functions. They
-provide improved accuracy and stability through the use of a disciplined
-clock interface for use with the Network Time Protocol (NTP) or similar
-time-synchronization protocol. In addition, for the DEC 3000 AXP (Alpha)
-and DECstation 5000/240 machines, the modifications provide improved
-precision within one microsecond (us) (SunOS 4.1.x already does provide
-precision to this order). The NTP Version 3 daemon xntpd operates with
-these kernel modifications to provide synchronization in principle to
-within this order, but in practice this is limited by the short-term
-stability of the timer oscillator to within the order of 100 usec.
-
-This memo describes the principles behind the design and operation of
-the new software. There are three versions: one that operates with the
-SunOS 4.1.x kernels, a second that operates with the Ultrix 4.x kernels
-and a third that operates with the OSF/1 V1.x kernels. A detailed
-description of the variables and algorithms is given in the hope that
-similar functionality can be incorporated in Unix kernels for other
-machines. The algorithms involve only minor changes to the system clock
-and interval timer routines and include interfaces for application
-programs to learn the system clock status and certain statistics of the
-time-synchronization process. Detailed installation instructions are
-given in a companion README.install file included in the kernel
-distributions. The kernel software itself is not provided for public
-distribution, since it involves licensed code. Detailed instructions on
-how to obtain it for either SunOS, Ultrix or OSF/1 will be given
-separately.
-
-The principal feature added to the Unix kernels is to change the way the
-system clock is controlled, in order to provide precision time and
-frequency adjustments. Another feature utilizes an undocumented bus-
-cycle counter in the DEC 3000 AXP and DECstation 5000/240 to provide
-precise time to the microsecond. This feature can in principle be used
-with any DEC machine that has this counter, although this has not been
-verified. The addition of these features does not affect the operation
-of existing Unix system calls such as gettimeofday(), settimeofday() and
-adjtime(); however, if the new features are in use, the operations of
-adjtime() are controlled instead by a new system call ntp_adjtime().
-
-Most Unix programs read the system clock using the gettimeofday() system
-call, which returns only the system time and timezone data. For some
-applications it is useful to know the maximum error of the reported time
-due to all causes, including clock reading errors, oscillator frequency
-errors and accumulated latencies on the path to a primary reference
-source. However, the new software can adjust the system clock to
-compensate for its intrinsic frequency error, so that the timing errors
-expected in normal operation will usually be much less than the maximum
-error. The user application interface includes a new system call
-ntp_gettime(), which returns the system time, as well as the maximum
-error and estimated error. This interface is intended to support
-applications that need such things, including distributed file systems,
-multimedia teleconferencing and other real-time applications. The
-protocol daemon application interface includes a new system call
-ntp_adjtime(), which can be used to read and write kernel variables used
-for precision timekeeping, including time and frequency adjustments,
-controlling time constant, leap-second warning and related data.
-
-In this memo, NTP Version 3 and the Unix implementation xntpd are used
-as an example application of the new system calls for use by a protocol
-daemon. In principle, the new system calls can be used by other
-protocols and daemon implementations as well. Even in cases where the
+This memorandum describes a model and programming interface for generic
+operating system software that manages the system clock and timer
+functions. The model provides improved accuracy and stability for most
+computers using the Network Time Protocol (NTP) or similar time
+synchronization protocol. This memorandum describes the design
+principles and implementations of the model, while related technical
+reports discuss the design approach, engineering analysis and
+performance evaluation of the model as implemented in Unix kernels for
+modern workstations. The NTP Version 3 daemon xntpd operates with these
+implementations to provide improved accuracy and stability, together
+with diminished overhead in the operating system and network. In
+addition, the model supports the use of external timing sources, such as
+precision pulse-per-second (PPS) signals and the industry standard IRIG
+timing signals. The NTP daemon automatically detects the presence of the
+new features and utilizes them when available.
+
+There are three prototype implementations of the model presented in this
+memorandum, one each for the Sun Microsystems SPARCstation with the
+SunOS 4.1.x kernel, Digital Equipment DECstation 5000 with the Ultrix
+4.x kernel and Digital Equipment 3000 AXP Alpha with the OSF/1 V1.x
+kernel. In addition, for the DECstation 5000/240 and 3000 AXP Alpha
+machines, a special feature provides improved precision to 1 us (stock
+Sun kernels already do provide this precision). Other than improving the
+system clock accuracy, stability and precision, these implementations do
+not change the operation of existing Unix system calls which manage the
+system clock, such as gettimeofday(), settimeofday() and adjtime();
+however, if the new features are in use, the operations of
+gettimeofday() and adjtime() can be controlled instead by new system
+calls ntp_gettime() and ntp_adjtime() as described below.
+
+A detailed description of the variables and algorithms that operate upon
+them is given in the hope that similar functionality can be incorporated
+in Unix kernels for other machines. The algorithms involve only minor
+changes to the system clock and interval timer routines and include
+interfaces for application programs to learn the system clock status and
+certain statistics of the time synchronization process. Detailed
+installation instructions are given in a specific README files included
+in the kernel distributions.
+
+In this memorandum, NTP Version 3 and the Unix implementation xntp3 are
+used as an example application of the new system calls for use by a
+synchronization daemon. In principle, these system calls can be used by
+other protocols and implementations as well. Even in cases where the
local time is maintained by periodic exchanges of messages at relatively
-long intervals, such as using the NIST Automated Computer Time Service,
-the ability to precisely adjust the local clock frequency simplifies the
-synchronization procedures and allows the call frequency to be
-considerably reduced.
-
-2. Design Principles
-
-In order to understand how the new software works, it is useful to
-consider how most Unix systems maintain the system time. In the original
-design a hardware timer interrupts the kernel at a fixed rate: 100 Hz in
-the SunOS kernel, 256 Hz in the Ultrix kernel and 1024 Hz in the OSF/1
-kernel. Since the Ultrix kernel rate does not evenly divide one second
-in microseconds, the kernel adds 64 microseconds once each second, so
-the timescale consists of 255 advances of 3906 usec plus one of 3970
-usec. Similarly, the OSF/1 kernel adds 576 usec once each second, so its
-timescale consists of 1023 advances of 976 usec plus one of 1552 usec.
-
-In all Unix kernels considered in this memo, it is possible to slew the
-system clock to a new offset using the standard Unix adjtime() system
-call. To do this the clock frequency is changed by adding or subtracting
-a fixed amount (tickadj) at each timer interrupt (tick) for a calculated
-number of ticks. Since this calculation involves dividing the requested
-offset by tickadj, it is possible to slew to a new offset with a
-precision only of tickadj, which is usually in the neighborhood of 5 us,
-but sometimes much higher. This results in an amortization error which
-can accumulate to unacceptable levels, so that special provisions must
-be made in the clock adjustment procedures of the protocol daemon.
-
-In order to maintain the system clock within specified bounds with this
-scheme, it is necessary to call adjtime() on a regular basis. For
-instance, let the bound be set at 100 usec, which is a reasonable value
-for NTP-synchronized hosts on a local network, and let the onboard
-oscillator tolerance be 100 parts-per-million (ppm), which is a
-reasonably conservative assumption. This requires that adjtime() be
-called at intervals not exceeding 1 second (s), which is in fact what
-the unmodified NTP software daemon does.
-
-In the new software this scheme is replaced by another that extends the
-low-order bits of the system clock to provide very precise clock
-adjustments. At each timer interrupt a precisely calibrated quantity is
-added to the composite time value and overflows handled as required. The
-quantity is computed from the measured clock offset and in addition a
-frequency adjustment, which is automatically calculated from previous
-time adjustments. This implementation operates as an adaptive-parameter
-first-order, type-II, phase-lock loop (PLL), which in principle provides
-precision control of the system clock phase to within +-1 us and
-frequency to within +-5 nanoseconds (ns) per day.
-
-This PLL model is identical to the one implemented in NTP, except that
-in NTP the software daemon has to simulate the PLL using only the
-original adjtime() system call. The daemon is considerably complicated
-by the need to parcel time adjustments at frequent intervals in order to
-maintain the accuracy to specified bounds. The modified kernel routines
-do this directly, allowing vast gobs of ugly daemon code to be avoided
-at the expense of only a small amount of new code in the kernel. In
-fact, the amount of code added to the kernel for the new scheme is about
-the amount needed to implement the old scheme. A new system call
-ntp_adjtime(), which operates in a way similar to the original
-adjtime(), is called only as each new time update is determined, which
-in NTP occurs at intervals of from 16 s to 1024 s. In addition, doing
-the frequency correction in the kernel means that the system time runs
-true even if the daemon were to cease operation or the network paths to
-the primary reference source fail. The addition of the new ntp_adjtime()
-system call does not affect the original adjtime() system call, which
-continues to operate in its traditional fashion. However, the two system
-calls canot be used at the same time; only one of the two should be used
-on any given system.
-
-It is the intent in the design that settimeofday() be used for changes
-in system time greater than +-128 ms. It has been the Internet
-experience that the need to change the system time in increments greater
-than +-128 milliseconds is extremely rare and is usually associated with
-a hardware or software malfunction or system reboot. Once the system
-clock has been set in this way, the ntp_adjtime() system call is used to
-provide periodic updates including the time offset, maximum error,
-estimated error and PLL time constant. With NTP the update interval
-depends on the measured error and time constant; however, the scheme is
-quite forgiving and neither moderate loss of updates nor variations in
-the length of the polling interval are serious.
-
-In addition, the kernel adjusts the maximum error to grow by an amount
-equal to the oscillator frequency tolerance times the elapsed time since
-the last update. The default engineering parameters have been optimized
-for intervals not greater than about 16 s. For longer intervals the PLL
-time constant can be adjusted to optimize the dynamic response up to
-intervals of 1024 s. Normally, this is automatically done by NTP. In any
-case, if updates are suspended, the PLL coasts at the frequency last
+long intervals, such as using the NIST Automated Computer Time Service
+[LEV89], the ability to precisely adjust the system clock frequency
+simplifies the synchronization procedures and allows the telephone call
+frequency to be considerably reduced.
+
+2. Design Approach
+
+While not strictly necessary for an understanding or implementation of
+the model, it may be helpful to briefly describe how NTP operates to
+control the system clock in a client computer. As described in [MIL91],
+the NTP protocol exchanges timestamps with one or more peers sharing a
+synchronization subnet to calculate the time offsets between peer clocks
+and the local clock. These offsets are processed by several algorithms
+which refine and combine the offsets to produce an ensemble average,
+which is then used to adjust the local clock time and frequency. The
+manner in which the local clock is adjusted represents the main topic of
+this memorandum. The goal in the enterprise is the most accurate and
+stable system clock possible with the available computer hardware and
+kernel software.
+
+In order to understand how the new model works, it is useful to review
+how most Unix kernels maintain the system clock. In the Unix design a
+hardware counter interrupts the kernel at a fixed rate: 100 Hz in the
+SunOS kernel, 256 Hz in the Ultrix kernel and 1024 Hz in the OSF/1
+kernel. Since the Ultrix timer interval (reciprocal of the rate) does
+not evenly divide one second in microseconds, the kernel adds 64 us once
+each second, so the timescale consists of 255 advances of 3906 us plus
+one of 3970 us. Similarly, the OSF/1 kernel adds 576 us once each
+second, so its timescale consists of 1023 advances of 976 us plus one of
+1552 us.
+
+2.1. Mechanisms to Adjust Time and Frequency
+
+In most Unix kernels it is possible to slew the system clock to a new
+offset relative to the current time by using the adjtime() system call.
+To do this the clock frequency is changed by adding or subtracting a
+fixed amount (tickadj) at each timer interrupt (tick) for a calculated
+number of timer interrupts. Since this calculation involves dividing the
+requested offset by tickadj, it is possible to slew to a new offset with
+a precision only of tickadj, which is usually in the neighborhood of 5
+us, but sometimes much larger. This results in a roundoff error which
+can accumulate to an unacceptable degree, so that special provisions
+must be made in the clock adjustment procedures of the synchronization
+daemon.
+
+In order to implement a frequency discipline function, it is necessary
+to provide time offset adjustments to the kernel at regular adjustment
+intervals using the adjtime() system call. In order to reduce the system
+clock jitter to the regime consistent with the model, it is necessary
+that the adjustment interval be relatively small, in the neighborhood of
+1 s. However, the Unix adjtime() implementation requires each offset
+adjustment to complete before another one can be begun, which means that
+large adjustments must be amortized over possibly many adjustment
+intervals. The requirement to implement the adjustment interval and
+compensate for roundoff error considerably complicates the synchronizing
+daemon implementation.
+
+In the new model this scheme is replaced by another that represents the
+system clock as a multiple-word, precision-time variable in order to
+provide very precise clock adjustments. At each timer interrupt a
+precisely calibrated quantity is added to the kernel time variable and
+overflows propagated as required. The quantity is computed as in the NTP
+local clock model described in [MIL92b], which operates as an adaptive-
+parameter, first-order, type-II phase-lock loop (PLL). In principle,
+this PLL design can provide precision control of the system clock
+oscillator within 1 us and frequency to within parts in 10^11. While
+precisions of this order are surely well beyond the capabilities of the
+CPU clock oscillator used in typical workstations, they are appropriate
+using precision external oscillators, as described below.
+
+The PLL design is identical to the one originally implemented in NTP and
+described in [MIL92b]. In the original design the software daemon
+simulates the PLL using the adjtime() system call; however, the daemon
+implementation is considerably complicated by the considerations
+described above. The modified kernel routines implement the PLL in the
+kernel using precision time and frequency representations, so that these
+complications are avoided. A new system call ntp_adjtime() is called
+only as each new time update is determined, which in NTP occurs at
+intervals of from 16 s to 1024 s. In addition, doing frequency
+compensation in the kernel means that the system clock runs true even if
+the daemon were to cease operation or the network paths to the primary
+synchronization source fail.
+
+In the new model the new ntp_adjtime() operates in a way similar to the
+original adjtime() system call, but does so independently of adjtime(),
+which continues to operate in its traditional fashion. When used with
+NTP, it is the design intent that settimeofday() or adjtime() be used
+only for system clock adjustments greater than +-128 ms, although the
+dynamic range of the new model is much larger at +-512 ms. It has been
+the Internet experience that the need to change the system clock in
+increments greater than +-128 ms is extremely rare and is usually
+associated with a hardware or software malfunction or system reboot.
+
+The easiest way to set the time is with the settimeofday() system call;
+however, this can under some conditions cause the clock to jump
+backwards. If this cannot be tolerated, adjtime() can be used to slew
+the clock to the new value without running backward or affecting the
+frequency discipline process. Once the system clock has been set within
++-128 ms, the ntp_adjtime() system call is used to provide periodic
+updates including the time offset, maximum error, estimated error and
+PLL time constant. With NTP the update interval and time constant depend
+on the measured delay and dispersion; however, the scheme is quite
+forgiving and neither moderate loss of updates nor variations in the
+update interval are serious.
+
+2.2 Daemon and Application Interface
+
+Unix application programs can read the system clock using the
+gettimeofday() system call, which returns only the system time and
+timezone data. For some applications it is useful to know the maximum
+error of the reported time due to all causes, including clock reading
+errors, oscillator frequency errors and accumulated latencies on the
+path to the primary synchronization source. However, in the new model
+the PLL adjusts the system clock to compensate for its intrinsic
+frequency error, so that the time error expected in normal operation
+will usually be much less than the maximum error. The programming
+interface includes a new system call ntp_gettime(), which returns the
+system time, as well as the maximum error and estimated error. This
+interface is intended to support applications that need such things,
+including distributed file systems, multimedia teleconferencing and
+other real-time applications. The programming interface also includes a
+new system call ntp_adjtime(), which can be used to read and write
+kernel variables for time and frequency adjustment, PLL time constant,
+leap-second warning and related data.
+
+In addition, the kernel adjusts the indicated maximum error to grow by
+an amount equal to the maximum oscillator frequency tolerance times the
+elapsed time since the last update. The default engineering parameters
+have been optimized for update intervals in the order of 64 s. As shown
+in [MIL93], this is near the optimum interval for NTP used with ordinary
+room-temperature quartz oscillators. For other intervals the PLL time
+constant can be adjusted to optimize the dynamic response over intervals
+of 16-1024 s. Normally, this is automatically done by NTP. In any case,
+if updates are suspended, the PLL coasts at the frequency last
determined, which usually results in errors increasing only to a few
-tens of milliseconds over a day.
-
-The new code needs to know the initial frequency offset and time
-constant for the PLL, and the daemon needs to know the current frequency
-offset computed by the kernel for monitoring purposes. These data are
-exchanged between the kernel and protocol daemon using ntp_adjtime() as
-documented later in this memo. Provisions are made to exchange related
-timing information, such as the maximum error and estimated error,
-between the kernel and daemon and between the kernel and application
-programs.
-
-In the DEC 3000 AXP, DECstation 5000/240 and possibly other DEC
-machines there is an undocumented hardware register that counts system
-bus cycles at a rate of 25 MHz. The new kernel microtime() routine tests
-for the CPU type and, in the case of these machines, use this register
-to interpolate system time between hardware timer interrupts. This
-results in a precision of +-1 us for all time values obtained via the
-gettimeofday() and ntp_gettime() system calls. These routines call the
-microtime() routine, which returns the actual interpolated value but
-does not change the kernel time variable. Therefore, other kernel
-routines that access the kernel time variable directly and do not call
-either gettimeofday(), ntp_gettime() or microtime() will continue their
-present behavior. The microtime() feature is independent of other
-features described here and is operative even if the kernel PLL or new
-system calls have not been implemented.
-
-While any protocol daemon can in principle be modified to use the new
-system calls, the most likely will be users of the NTP Version 3 daemon
-xntpd. The xntpd code determines whether the new system calls are
+tens of milliseconds over a day using typical modern workstations.
+
+While any synchronization daemon can in principle be modified to use the
+new system calls, the most likely will be users of the NTP Version 3
+daemon xntpd. The xntpd code determines whether the new system calls are
implemented and automatically reconfigures as required. When
-implemented, the daemon reads the frequency offset from a file and
-provides it and the initial time constant via ntp_adjtime(). In
-subsequent calls to ntp_adjtime(), only the time adjustment and time
+implemented, the daemon reads the frequency offset from a system file
+and provides it and the initial time constant via ntp_adjtime(). In
+subsequent calls to ntp_adjtime(), only the time offset and time
constant are affected. The daemon reads the frequency from the kernel
-using ntp_adjtime() at intervals of about one hour and writes it to the
-system log file. This information is recovered when the daemon is
-restarted after reboot, for example, so the sometimes extensive training
-period to learn the frequency separately for each system can be avoided.
-
-3. Kernel Interfaces
-
-This section describes the kernel interfaces to the protocol daemon and
-user applications. The ideas are based on suggestions from Jeff Mogul
-and Philip Gladstone and a similar interface designed by the latter. It
-is important to point out that the functionality of the original Unix
-adjtime() system call is preserved, so that the modified kernel will
-work as the unmodified one should the kernel PLL not be in use. In this
-case the ntp_adjtime() system call can still be used to read and write
-kernel variables that might be used by a protocol daemon other than NTP,
-for example.
-
-3.1. The ntp_gettime() System Call
-
-The syntax and semantics of the ntp_gettime() call are given in the
-following fragment of the timex.h header file. This file is identical in
-the SunOS, Ultrix and OSF/1 kernel distributions. Note that the timex.h
-file calls the syscall.h system header file, which must be modified to
-define the SYS_ntp_gettime system call specific to each system type. The
-kernel distributions include directions on how to do this.
-
-/*
- * This header file defines the Network Time Protocol (NTP) interfaces
- * for user and daemon application programs. These are implemented using
- * private system calls and data structures and require specific kernel
- * support.
- *
- * NAME
- * ntp_gettime - NTP user application interface
- *
- * SYNOPSIS
- * #include <sys/timex.h>
- *
- * int system call(SYS_ntp_gettime, tptr)
- *
- * int SYS_ntp_gettime defined in syscall.h header file
- * struct ntptimeval *tptr pointer to ntptimeval structure
- *
- * NTP user interface - used to read kernel clock values
- * Note: maximum error = NTP synch distance = dispersion + delay / 2;
- * estimated error = NTP dispersion.
- */
-struct ntptimeval {
- struct timeval time; /* current time */
- long maxerror; /* maximum error (usec) */
- long esterror; /* estimated error (usec) */
-};
-
-The ntp_gettime() system call returns three values in the ntptimeval
-structure: the current time in unix timeval format plus the maximum and
-estimated errors in microseconds. While the 32-bit long data type limits
-the error quantities to something more than an hour, in practice this is
-not significant, since the protocol itself will declare an
-unsynchronized condition well below that limit. If the protocol computes
-either of these values in excess of 16 seconds, they are clamped to that
-value and the local clock declared unsynchronized.
-
-Following is a detailed description of the ntptimeval structure members.
-
-struct timeval time;
-
- This member is set to the current system time, expressed as a Unix
- timeval structure. The timeval structure consists of two 32-bit
- words, one for the number of seconds past 1 January 1970 and the
- other the number of microseconds past the most recent second's
- epoch.
-
-long maxerror;
-
- This member is set to the value of the time_maxerror kernel
- variable, which establishes the maximum error of the indicated time
- relative to the primary reference source, in microseconds. This
- variable can also be set and read by the ntp_adjtime() system call.
- For NTP, the value is determined as the synchronization distance,
- which is equal to the root dispersion plus one-half the root delay.
- It is increased by a small amount (time_tolerance) each second to
- reflect the clock frequency tolerance. This variable is computed by
- the time-synchronization daemon and the kernel and returned in a
- ntp_gettime() system call, but is otherwise not used by the kernel.
-
-long esterror;
-
- This member is set to the value of the time_esterror kernel
- variable, which establishes the expected error of the indicated
- time relative to the primary reference source, in microseconds.
- This variable can also be set and read by the ntp_adjtime() system
- call. For NTP, the value is determined as the root dispersion,
- which represents the best estimate of the actual error of the
- system clock based on its past behavior, together with observations
- of multiple clocks within the peer group. This variable is computed
- by the time-synchronization daemon and returned in a ntp_gettime()
- system call, but is otherwise not used by the kernel.
-
-3.2. The ntp_adjtime() System Call
-
-The syntax and semantics of the ntp_adjtime() call is given in the
-following fragment of the timex.h header file. Note that, as in the
-ntp_gettime() system call, the the syscall.h system header file must be
-modified to define the SYS_ntp_adjtime system call specific to each
-system type.
-
-/*
- * NAME
- * ntp_adjtime - NTP daemon application interface
- *
- * SYNOPSIS
- * #include <sys/timex.h>
- *
- * int system call(SYS_ntp_adjtime, mode, tptr)
- *
- * int SYS_ntp_adjtime defined in syscall.h header file
- * struct timex *tptr pointer to timex structure
- *
- * NTP daemon interface - used to discipline kernel clock oscillator
- */
-struct timex {
- int mode; /* mode selector */
- long offset; /* time offset (usec) */
- long frequency; /* frequency offset (scaled ppm) */
- long maxerror; /* maximum error (usec) */
- long esterror; /* estimated error (usec) */
- int status; /* clock command/status */
- long time_constant; /* pll time constant */
- long precision; /* clock precision (usec) (read only) */
- long tolerance; /* clock frequency tolerance (ppm)
- * (read only)
- */
-};
-
-The ntp_adjtime() system call is used to read and write certain time-
-related kernel variables summarized in this and subsequent sections.
-Writing these variables can only be done in superuser mode. To write a
-variable, the mode structure member is set with one or more bits, one of
-which is assigned each of the following variables in turn. The current
-values for all variables are returned in any case; therefore, a mode
-argument of zero means to return these values without changing anything.
-
-Following is a description of the timex structure members.
-
-int mode;
-
- This is a bit-coded variable selecting one or more structure
- members, with one bit assigned each member. If a bit is set, the
- value of the associated member variable is copied to the
- corresponding kernel variable; if not, the member is ignored. The
- bits are assigned as given in the following fragment of the timex.h
- header file. Note that the precision and tolerance are intrinsic
- properties of the kernel configuration and cannot be changed.
-
- /*
- * Mode codes (timex.mode)
- */
- #define ADJ_OFFSET 0x0001 /* time offset */
- #define ADJ_FREQUENCY 0x0002 /* frequency offset */
- #define ADJ_MAXERROR 0x0004 /* maximum time error */
- #define ADJ_ESTERROR 0x0008 /* estimated time error */
- #define ADJ_STATUS 0x0010 /* clock status */
- #define ADJ_TIMECONST 0x0020 /* pll time constant */
-
-long offset;
-
- If selected, this member (scaled) replaces the value of the
- time_offset kernel variable, which defines the current time offset
- of the phase-lock loop. The value must be in the range +-512 ms in
- the present implementation. If so, the clock status is
- automatically set to TIME_OK.
-
-long time_constant;
-
- If selected, this member replaces the value of the time_constant
- kernel variable, which establishes the bandwidth of "stiffness" of
- the kernel PLL. The value is used as a shift, with the effective
- PLL time constant equal to a multiple of (1 << time_constant), in
- seconds. The optimum value for the time_constant variable is
- log2(update_interval) - 4, where update_interval is the nominal
- interval between clock updates, in seconds. With an ordinary crystal
- oscillator the optimum value for time_constant is about 2, giving
- an update_interval of 4 (64 s). Values of time_constant between zero
- and 2 can be used if quick convergence is necessary; values between
- 2 and 6 can be used to reduce network load, but at a modest cost in
- accuracy. Values above 6 are appropriate only if a precision
- oscillator is available.
-
-long frequency;
-
- If selected, this member (scaled) replaces the value of the
- time_frequency kernel variable, which establishes the intrinsic
- frequency of the local clock oscillator. This variable is scaled by
- (1 << SHIFT_USEC) in parts-per-million (ppm), giving it a maximum
- value of about +-31 ms/s and a minimum value (frequency resolution)
- of about 2e-11, which is appropriate for even the best quartz
- oscillator.
-
-long maxerror;
-
- If selected, this member replaces the value of the time_maxerror
- kernel variable, which establishes the maximum error of the
- indicated time relative to the primary reference source, in
- microseconds. This variable can also be read by the ntp_gettime()
- system call. For NTP, the value is determined as the
- synchronization distance, which is equal to the root dispersion
- plus one-half the root delay. It is increased by a small amount
- (time_tolerance) each second to reflect the clock frequency
- tolerance. This variable is computed by the time-synchronization
- daemon and the kernel and returned in a ntp_gettime() system call,
- but is otherwise not used by the kernel.
-
-long esterror;
-
- If selected, this member replaces the value of the time_esterror
- kernel variable, which establishes the expected error of the
- indicated time relative to the primary reference source, in
- microseconds. This variable can also be read by the ntp_gettime()
- system call. For NTP, the value is determined as the root
- dispersion, which represents the best estimate of the actual error
- of the system clock based on its past behavior, together with
- observations of multiple clocks within the peer group. This
- variable is computed by the time-synchronization daemon and
- returned in a ntp_gettime() system call, but is otherwise not used
- by the kernel.
-
-int status;
-
- If selected, this member replaces the value of the time_status
- kernel variable, which records whether the clock is synchronized,
- waiting for a leap second, etc. In order to set this variable
- explicitly, either (a) the current clock status is TIME_OK or (b)
- the member value is TIME_BAD; that is, the ntp_adjtime() call can
- always set the clock to the unsynchronized state or, if the clock
- is running correctly, can set it to any state. In any case, the
- ntp_adjtime() call always returns the current state in this member,
- so the caller can determine whether or not the request succeeded.
-
-long precision;
-
- This member is set equal to the time_precision kernel in
- microseconds variable upon return from the system call. The
- time_precision variable cannot be written. This variable represents
- the maximum error in reading the system clock, which is ordinarily
- equal to the kernel variable tick, 10000 usec in the SunOS kernel,
- 3906 usec in Ultrix kernel and 976 usec in the OSF/1 kernel.
- However, in cases where the time can be interpolated with
- microsecond resolution, such as in the SunOS kernel and modified
- Ultrix and OSF/1 kernels, the precision is specified as 1 usec.
- This variable is computed by the kernel for use by the time-
- synchronization daemon, but is otherwise not used by the kernel.
-
-long tolerance;
-
- This member is set equal to the time_tolerance kernel variable in
- parts-per-million (ppm) upon return from the system call. The
- time_tolerance variable cannot be written. This variable represents
- the maximum frequency error or tolerance of the particular platform
- and is a property of the architecture and manufacturing process.
-
-3.3. Command/Status Codes
-
-The kernel routines use the system clock status variable time_status,
-which records whether the clock is synchronized, waiting for a leap
-second, etc. The value of this variable is returned as the result code
-by both the ntp_gettime() and ntp_adjtime() system calls. In addition,
-it can be explicitly read and written using the ntp_adjtime() system
-call, but can be written only in superuser mode. Values presently
-defined in the timex.h header file are as follows:
-
-/*
- * Clock command/status codes (timex.status)
- */
-#define TIME_OK 0 /* clock synchronized */
-#define TIME_INS 1 /* insert leap second */
-#define TIME_DEL 2 /* delete leap second */
-#define TIME_OOP 3 /* leap second in progress */
-#define TIME_BAD 4 /* clock not synchronized */
-
-A detailed description of these codes as used by the leap-second state
-machine is given later in this memo. In case of a negative result code,
-the kernel has intercepted an invalid address or (in case of the
-ntp_adjtime() system call), a superuser violation.
-
-4. Technical Summary
-
-In order to more fully understand the workings of the PLL, a stand-alone
-simulator kern.c is included in the kernel distributions. This is an
-implementation of an adaptive-parameter, first-order, type-II phase-lock
-loop. The system clock is implemented using a set of variables and
-algorithms defined in the simulator and driven by explicit offsets
-generated by the simulator. The algorithms include code fragments
-identical to those in the modified kernel routines and operate in the
-same way, but the operations can be understood separately from any
-licensed source code into which these fragments may be integrated. The
-code segments themselves are not derived from any licensed code.
-
-4.1. PLL Simulation
-
-In the simulator the hardupdate() fragment is called by ntp_adjtime() as
-each update is computed to adjust the system clock phase and frequency.
-Note that the time constant is in units of powers of two, so that
-multiplies can be done by simple shifts. The phase variable is computed
-as the offset multiplied by the time constant. Then, the time since the
-last update is computed and clamped to a maximum (for robustness) and to
-zero if initializing. The offset is multiplied (sorry about the ugly
-multiply) by the result and by the square of the time constant and then
-added to the frequency variable. Finally, the frequency variable is
-clamped not to exceed the tolerance. Note that all shifts are assumed to
-be positive and that a shift of a signed quantity to the right requires
-a little dance.
-
-With the defines given, the maximum time offset is determined by the
-size in bits of the long type (32) less the SHIFT_UPDATE scale factor or
-18 bits (signed). The scale factor is chosen so that there is no loss of
-significance in later steps, which may involve a right shift up to 14
-bits. This results in a maximum offset of about +-130 ms. Since
+using ntp_adjtime() at intervals of about one hour and writes it to a
+system file. This information is recovered when the daemon is restarted
+after reboot, for example, so the sometimes extensive training period to
+learn the frequency separately for each oscillator can be avoided.
+
+2.3. Precision Clocks for DECstation 5000/240 and 3000 AXP Alpha
+
+The stock microtime() routine in the Ultrix kernel for Digital Equipment
+MIPS-based workstations returns system time to the precision of the
+timer interrupt interval, which is in the 1-4 ms range. However, in the
+DECstation 5000/240 and possibly other machines of that family, there is
+an undocumented IOASIC hardware register that counts system bus cycles
+at a rate of 25 MHz. The new microtime() routine for the Ultrix kernel
+uses this register to interpolate system time between timer interrupts.
+This results in a precision of 1 us for all time values obtained via the
+gettimeofday() and ntp_gettime() system calls. For the Digital Equipment
+3000 AXP Alpha, the architecture provides a hardware Process Cycle
+Counter and a machine instruction (rpcc) to read it. This counter
+operates at the fundamental frequency of the CPU clock or some
+submultiple of it, 133.333 MHz for the 3000/400 for example. The new
+microtime() routine for the OSF/1 kernel uses this counter in the same
+fashion as the Ultrix routine. Support for this feature is conditionally
+compiled in the kernel only if the MICRO option is used in the kernel
+configuration file.
+
+In both the Ultrix and OSF/1 kernels the gettimeofday() and
+ntp_gettime() system call use the new microtime() routine, which returns
+the interpolated value to 1-us resolution, but does not change the
+kernel time variable. Therefore, other routines that access the kernel
+time variable directly and do not call either gettimeofday(),
+ntp_gettime() or microtime() will continue their present behavior. The
+microtime() feature is independent of other features described here and
+is operative even if the kernel PLL or new system calls have not been
+implemented.
+
+The SunOS kernel already includes a system clock with 1-us resolution;
+so, in principle, no microtime() routine is necessary. An existing
+kernel routine uniqtime() implements this function, but it is coded in
+the C language and is rather slow at 42-85 us per call on a SPARCstation
+IPC. A replacement microtime() routine coded in assembler language is
+available in the NTP Version 3 distribution and is much faster at about
+3 us per call. Note that, as explained later, this routine should be
+called at an interrupt priority level not greater than that of the timer
+interrupt routine. Otherwise, it is possible to miss a tick increment,
+with result the time returned can be late by one tick. This is always
+true in the case of gettimeofday() and ntp_gettime(), but might not be
+true in other cases, such as when using the PPS signal described later
+in this memorandum.
+
+2.4. External Time and Frequency Discipline
+
+The overall accuracy of a time synchronization subnet with respect to
+Coordinated Universal Time (UTC) depends on the accuracy and stability
+of the primary synchronization source, usually a radio or satellite
+receiver, and the CPU clock oscillator of the primary server. As
+discussed in [MIL93], the traditional interface using a ASCII serial
+timecode and RS232 port precludes the full accuracy of most radio
+clocks. In addition, the poor frequency stability of typical CPU clock
+oscillators limits the accuracy, whether or not precision time sources
+are available. There are, however, several ways in which the system
+clock accuracy and stability can be improved to the degree limited only
+by the accuracy and stability of the synchronization source and the
+jitter of the interface and operating system.
+
+Many radio clocks produce special signals that can be used by external
+equipment to precisely synchronize time and frequency. Most produce a
+pulse-per-second (PPS) signal that can be read via a modem-control lead
+of a serial port and some produce a special IRIG signal that can be read
+directly by a bus peripheral, such as the KSI/Odetics TPRO IRIG SBus
+interface, or indirectly via the audio codec of some workstations, as
+described in [MIL93]. In the NTP Version 3 daemon xntpd, the PPS signal
+can be used to augment the less precise ASCII serial timecode to improve
+accuracy to the order of a few tens of microseconds. Support is also
+included in the NTP distribution for the TPRO interface, as well as the
+audio codec; however, the latter requires a modified kernel audio driver
+contained in the compressed tar archive bsd_audio.tar.Z in the same host
+and directory as the NTP Version 3 distribution mentioned previously.
+2.4.1. PPS Signal
+
+The most convenient way to interface a PPS signal to a computer is
+usually with a serial port and RS232-compatible signal; however, the PPS
+signal produced by most radio clocks and laboratory instruments is
+usually a TTL pulse signal. Therefore, some kind of level
+converter/pulse generator is necessary to adapt the PPS signal to a
+serial port. An example design, including schematic and printed-circuit
+board artwork, is in the compressed tar archive gadget.tar.Z in the same
+host and directory as the NTP Version 3 distribution mentioned
+previously. There are several ways the PPS signal can be used in
+conjunction with the NTP Version 3 daemon xntpd, as described in [MIL93]
+and in the documentation included in the distribution.
+
+The NTP Version 3 distribution includes a special ppsclock module for
+the SunOS 4.1.x kernel that captures the PPS signal presented via a
+modem-control lead of a serial port. Normally, the ppsclock module
+produces a timestamp at each transition of the PPS signal and provides
+it to the synchronization daemon for integration with the serial ASCII
+timecode, also produced by the radio clock. With the conventional PLL
+implementation in either the daemon or the kernel as described in
+[MIL93], the accuracy of this scheme is limited by the intrinsic
+stability of the CPU clock oscillator to a millisecond or two, depending
+on environmental temperature variations.
+
+The ppsclock module has been modified to in addition call a new kernel
+routine hardpps() once each second. In addition, the Ultrix 4.3 kernel
+has been modified to provide a similar functionality. The hardpps()
+routine compares the timestamp with a sample of the CPU clock oscillator
+in order to discipline the oscillator to the time and frequency of the
+PPS signal. Using this method, the time accuracy is improved to
+typically 20 us or less and frequency stability a few parts in 10^8,
+which is about two orders of magnitude better than the undisciplined
+oscillator. The new feature is conditionally compiled in the code
+described below only if the PPS_SYNC option is used in the kernel
+configuration file.
+
+When using the PPS signal to adjust the time, there is a problem with
+some kernels which is very difficult to fix. The serial port interrupt
+routine often operates at an interrupt priority level above the timer
+interrupt routine. Thus, as explained below, it is possible that a tick
+increment can be missed and the time returned late by one tick. It may
+happen that, if the CPU clock oscillator frequency is close to the PPS
+oscillator frequency (less than a few ppm), this condition can persist
+for two or more successive PPS interrupts. A useful workaround in the
+code is to use a glitch detector and median filter to process the PPS
+sample offsets. The glitch detector suppresses offset bursts greater
+than half the tick interval and which last less than 30 successive PPS
+interrupts. The median filter ranks the offsets in a moving window of
+three samples and uses the median as the output and the difference
+between the other two as a dispersion measure.
+
+2.4.2. External Clocks
+
+It is possible to replace the system clock function with an external bus
+peripheral. The TPRO device mentioned previously can be used to provide
+IRIG-synchronized time with a precision of 1 us. A driver for this
+device tprotime.c and header file tpro.h are included in the
+kernel.tar.Z distribution mentioned previously. Using this device, the
+system clock is read directly from the interface; however, the device
+does not record the year, so special provisions have been made to obtain
+the year from the kernel time variable and initialize the driver
+accordingly. Support for this feature is conditionally compiled in the
+kernel only if the EXT_CLOCK and TPRO options are used in the kernel
+configuration file.
+
+While the system clock function is provided directly by the microtime()
+routine in the driver, the kernel time variable must be disciplined as
+well, since not all system timing functions use the microtime() routine.
+This is done by measuring the time difference between the microtime()
+clock and kernel time variable and using it to adjust the kernel PLL as
+if the adjustment were provided by an external peer and NTP.
+
+A good deal of error checking is done in the TPRO driver, since the
+system clock is vulnerable to a misbehaving radio clock, IRIG signal
+source, interface cables and TPRO device itself. Unfortunately, there is
+no practical way to utilize the extensive diversity and redundancy
+capabilities available in the NTP synchronization daemon. In order to
+avoid disruptions that might occur if the TPRO time is far different
+from the kernel time variable, the latter is used instead of the former
+if the difference between the two exceeds 1000 s; presumably in that
+case operator intervention is required.
+
+2.4.2. External Oscillators
+
+Even if a source of PPS or IRIG signals is not available, it is still
+possible to improve the stability of the system clock through the use of
+a specialized bus peripheral. In order to explore the benefits of such
+an approach, a special SBus peripheral called HIGHBALL has been
+constructed. The device includes a pair of 32-bit hardware counters in
+Unix timeval format, together with a precision, oven-controlled quartz
+oscillator with a stability of a few parts in 10^9. A driver for this
+device hightime.c and header file high.h are included in the
+kernel.tar.Z distribution mentioned previously. Support for this feature
+is conditionally compiled in the kernel only if the EXT_CLOCK and
+HIGHBALL options are used in the kernel configuration file.
+
+Unlike the external clock case, where the system clock function is
+provided directly by the microtime() routine in the driver, the HIGHBALL
+counter offsets with respect to UTC must be provided first. This is done
+using the ordinary kernel PLL, but controlling the counter offsets
+directly, rather than the kernel time variable. At first, this might
+seem to defeat the purpose of the design, since the jitter and wander of
+the synchronization source will affect the counter offsets and thus the
+accuracy of the time. However, the jitter is much reduced by the PLL and
+the wander is small, especially if using a radio clock or another
+primary server disciplined in the same way. In practice, the scheme
+works to reduce the incidental wander to a few parts in 10^8, or about
+the same as using the PPS signal.
+
+As in the previous case, the kernel time variable must be disciplined as
+well, since not all system timing functions use the microtime() routine.
+However, the kernel PLL cannot be used for this, since it is already in
+use providing offsets for the HIGHBALL counters. Therefore, a special
+correction is calculated from the difference between the microtime()
+clock and the kernel time variable and used to adjust the kernel time
+variable at the next timer interrupt. This somewhat roundabout approach
+is necessary in order that the adjustment does not cause the kernel time
+variable to jump backwards and possibly lose or duplicate a timer event.
+
+2.5 Other Features
+
+It is a design feature of the NTP architecture that the system clocks in
+a synchronization subnet are to read the same or nearly the same values
+before during and after a leap-second event, as declared by national
+standards bodies. The new model is designed to implement the leap event
+upon command by an ntp_adjtime() argument. The intricate and sometimes
+arcane details of the model and implementation are discussed in [MIL92b]
+and [MIL93]. Further details are given in the technical summary later in
+this memorandum.
+3. Technical Summary
+
+In order to more fully understand the workings of the model, a stand-
+alone simulator kern.c and header file timex.h are included in the
+kernel.tar.Z distribution mentioned previously. In addition, an example
+kernel module kern_ntptime.c which implements the ntp_gettime() and
+ntp_adjtime() system calls is included. Neither of these programs
+incorporate licensed code. Since the distribution is somewhat large, due
+to copious comments and ornamentation, it is impractical to include a
+listing of these programs in this memorandum. In any case, implementors
+may choose to snip portions of the simulator for use in new kernel
+designs; but, due to formatting conventions, this would be difficult if
+included in this memorandum.
+
+The kern.c program is an implementation of an adaptive-parameter, first-
+order, type-II phase-lock loop. The system clock is implemented using a
+set of variables and algorithms defined in the simulator and driven by
+explicit offsets generated by the main() routine in the program. The
+algorithms include code fragments almost identical to those in the
+machine-specific kernel implementations and operate in the same way, but
+the operations can be understood separately from any licensed source
+code into which these fragments may be integrated. The code fragments
+themselves are not derived from any licensed code. The following
+discussion assumes that the simulator code is available for inspection.
+
+3.1. PLL Simulation
+
+The simulator operates in conformance with the analytical model
+described in [MIL92b]. The main() program operates as a driver for the
+fragments hardupdate(), hardclock(), second_overflow(), hardpps() and
+microtime(), although not all functions implemented in these fragments
+are simulated. The program simulates the PLL at each timer interrupt and
+prints a summary of critical program variables at each time update.
+
+There are three defined options in the kernel configuration file
+specific to each implementation. The PPS_SYNC option provides support
+for a pulse-per-second (PPS) signal, which is used to discipline the
+frequency of the CPU clock oscillator. The EXT_CLOCK option provides
+support for an external kernel-readable clock, such as the KSI/Odetics
+TPRO IRIG interface or HIGHBALL precision oscillator, both for the SBus.
+The TPRO option provides support for the former, while the HIGHBALL
+option provides support for the latter. External clocks are implemented
+as the microtime() clock driver, with the specific source code selected
+by the kernel configuration file.
+
+The PPS signal is carefully monitored for error conditions which can
+affect accuracy, stability and reliability. The time_status kernel
+variable contains bits that both control the use of the PPS signal and
+reveal its operational status. The function of each bit is described in
+a later section of this memo.
+
+3.1.1. The hardupdate() Fragment
+
+The hardupdate() fragment is called by ntp_adjtime() as each update is
+computed to adjust the system clock phase and frequency. Note that the
+time constant is in units of powers of two, so that multiplies can be
+done by simple shifts. The phase variable is computed as the offset
+divided by the time constant, but clamped to a maximum (for robustness).
+Then, the time since the last update is computed and clamped to a
+maximum and to zero if initializing. The offset is multiplied (sorry
+about the ugly multiply) by the result and divided by the square of the
+time constant and then added to the frequency variable. Note that all
+shifts are assumed to be positive and that a shift of a signed quantity
+to the right requires a little dance.
+
+The STA_PLL and STA_PPSTIME status bits, which are set by the
+ntp_adjtime() system call, serve to enable or inhibit the kernel PLL and
+PPS time-discipline functions. The STA_PPSSIGNAL status bit is set by
+the hardpps() code fragment when the PPS signal is present and operating
+within nominal bounds. Time discipline from the PPS signal operates only
+if both the STA_PPSTIME and STA_PPSSIGNAL bits are set; otherwise, the
+discipline operates from the offset given in the ntp_adjtime() system
+call. In the intended mode of operation, the synchronization daemon sets
+STA_PLL to enable the PLL when first initialized, then sets STA_PPSTIME
+when reliable synchronization to within +-128 ms has been achieved with
+either a radio clock or external peer. The daemon can detect and
+indicate this condition for monitoring purposes by noting that both
+STA_PPSTIME and STA_PPSSIGNAL are set.
+
+With the defines given in the program and header files, the maximum time
+offset is determined by the size in bits of the long type (32 or 64)
+less the SHIFT_UPDATE scale factor (12) or at least 20 bits (signed).
+The scale factor is chosen so that there is no loss of significance in
+later steps, which may involve a right shift up to SHIFT_UPDATE bits.
+This results in a time adjustment range over +-512 ms. Since
time_constant must be greater than or equal to zero, the maximum
-frequency offset is determined by the SHIFT_KF (20) scale factor, or
-about +-130 ppm. In the addition step, the value of offset * mtemp is
-represented in 18 + 10 = 28 bits, which will not overflow a long add.
-There could be a loss of precision due to the right shift of up to eight
-bits, since time_constant is bounded at 6. This results in a net worst-
-case frequency error of about 2^-16 us or well down into the oscillator
-phase noise. While the time_offset value is assumed checked before
-entry, the time_phase variable is an accumulator, so is clamped to the
-tolerance on every call. This helps to damp transients before the
-oscillator frequency has been determined, as well as to satisfy the
-correctness assertions if the time-synchronization protocol comes
-unstuck.
+frequency offset is determined by the SHIFT_USEC scale factor (16) or at
+least 16 bits (signed). This results in a frequency adjustment range
+over +-31,500 ppm.
+
+In the addition step, the value of offset * mtemp is not greater than
+MAXPHASE * MAXSEC = 31 bits (signed), which will not overflow a long add
+on a 32-bit machine. There could be a loss of precision due to the right
+shift of up to 12 bits, since time_constant is bounded at 6. This
+results in a net worst-case frequency resolution of about .063 ppm,
+which is not significant for most quartz oscillators. The worst case
+could be realized only if the NTP peer misbehaves according to the
+protocol specification.
+
+The time_offset value is clamped upon entry. The time_phase variable is
+an accumulator, so is clamped to the tolerance on every call. This helps
+to damp transients before the oscillator frequency has been stabilized,
+as well as to satisfy the correctness assertions if the time
+synchronization protocol or implementation misbehaves.
+
+3.1.2. The hardclock() Fragment
The hardclock() fragment is inserted in the hardware timer interrupt
-routine at the point the system clock is to be incremented. Previous to
-this fragment the time_update variable has been initialized to the value
-computed by the adjtime() system call in the stock Unix kernel, normally
-the value of tick plus/minus the tickadj value, which is usually in the
-order of 5 microseconds. When the kernel PLL is in use, adjtime() is
-not, so the time_update value at this point is the value of tick. This
-value, the phase adjustment (time_adj) and the clock phase (time_phase)
-are summed and the total tested for overflow of the microsecond. If an
-overflow occurs, the microsecond (tick) is incremented or decremented,
-depending on the sign of the overflow.
+routine at the point the system clock is to be incremented by the value
+of tick. Previous to this fragment the time_update variable has been
+initialized to the tick increment plus the value computed by the
+adjtime() system call in the stock Unix kernel, normally plus/minus the
+tickadj value, which is usually in the order of 5 us. The time_phase
+variable, which represents the instantaneous phase of the system clock,
+is advanced by time_adj, which is calculated in the second_overflow()
+fragment described below. If the value of time_phase exceeds 1 us in
+scaled units, time_update is increased by the (signed) excess and
+time_phase retains the residue.
+
+In those cases where a PPS signal is connected by a serial port
+operating at an interrupt priority level greater than the timer
+interrupt, special consideration should be given the location of the
+hardclock() fragment in the timer interrupt routine. The system clock
+should be advanced as early in the routine as possible, preferably
+before the hardware timer interrupt flag is cleared. This reduces or
+eliminates the possibility that the microtime() routine may latch the
+time after the flag is cleared, but before the system clock is advanced,
+which results in a returned time late by one tick.
+
+Except in the case of an external oscillator such as the HIGHBALL
+interface, the hardclock() fragment advances the system clock by the
+value of tick plus time_update. However, in the case of an external
+oscillator, the system clock is obtained directly from the interface and
+time_update used to discipline that interface instead. However, the
+system clock must still be disciplined as explained previously, so the
+value of clock_cpu computed by the second_overflow() fragment is used
+instead.
+
+3.1.3. The second_overflow() Fragment
The second_overflow() fragment is inserted at the point where the
microseconds field of the system time variable is being checked for
-overflow. On rollover of the second the maximum error is increased by
-the tolerance and the time offset is divided by the phase weight
-(SHIFT_KG) and time constant. The time offset is then reduced by the
-result and the result is scaled and becomes the value of the phase
-adjustment. The phase adjustment is then corrected for the calculated
-frequency offset and a fixed offset determined from the fixtick variable
-in some kernel implementations. On rollover of the day, the leap-warning
-indicator is checked and the apparent time adjusted +-1 s accordingly.
-The microtime() routine insures that the reported time is always
-monotonically increasing.
+overflow. Upon overflow the maximum error time_maxerror is increased by
+time_tolerance to reflect the maximum time offset due to oscillator
+frequency error. Then, the increment time_adj to advance the kernel time
+variable is calculated from the (scaled) time_offset and time_freq
+variables updated at the last call to the hardclock() fragment.
+
+The phase adjustment is calculated as a (signed) fraction of the
+time_offset remaining, where the fraction is added to time_adj, then
+subtracted from time_offset. This technique provides a rapid convergence
+when offsets are high, together with good resolution when offsets are
+low. The frequency adjustment is the sum of the (scaled) time_freq
+variable, an adjustment necessary when the tick interval does not evenly
+divide one second fixtick and PPS frequency adjustment pps_freq (if
+configured).
+
+The scheme of approximating exact multiply/divide operations with shifts
+produces good results, except when an exact calculation is required,
+such as when the PPS signal is being used to discipline the CPU clock
+oscillator frequency as described below. As long as the actual
+oscillator frequency is a power of two in Hz, no correction is required.
+However, in the SunOS kernel the clock frequency is 100 Hz, which
+results in an error factor of 0.78. In this case the code increases
+time_adj by a factor of 1.25, which results in an overall error less
+than three percent.
+
+On rollover of the day, the leap-second state machine described below
+determines whether a second is to be inserted or deleted in the
+timescale. The microtime() routine insures that the reported time is
+always monotonically increasing.
+
+3.1.4. The hardpps() Fragment
+
+The hardpps() fragment is operative only if the PPS_SYNC option is
+specified in the kernel configuration file. It is called from the serial
+port driver or equivalent interface at the on-time transition of the PPS
+signal. The code operates as a first-order, type-I, frequency-lock loop
+(FLL) controlled by the difference between the frequency represented by
+the pps_freq variable and the frequency of the hardware clock
+oscillator. It also provides offsets to the hardupdate() fragment in
+order to discipline the system clock time.
+
+In order to avoid calling the microtime() routine more than once for
+each PPS transition, the interface requires the calling program to
+capture the system time and hardware counter contents at the on-time
+transition of the PPS signal and provide a pointer to the timestamp
+(Unix timeval) and counter contents as arguments to the hardpps() call.
+The hardware counter contents are determined by saving the microseconds
+field of the system time, calling the microtime() routine, and
+subtracting the saved value. If a microseconds overflow has occurred
+during the process, the resulting microseconds value will be negative,
+in which case the caller adds 1000000 to normalize the microseconds
+field.
+
+In order to avoid large jitter when the PPS interrupt occurs during the
+timer interrupt routine before the system clock is advanced, a glitch
+detector is used. The detector latches when an offset exceeds a
+threshold tick/2 and stays latched until either a subsequent offset is
+less than the threshold or a specified interval MAXGLITCH (30 s) has
+elapsed. As long as the detector remains latched, it outputs the offset
+immediately preceding the latch, rather than the one received.
+
+A three-stage median filter is used to suppress jitter less than the
+glitch threshold. The median sample drives the PLL, while the difference
+between the other two samples represents the time dispersion. Time
+dispersion samples are averaged and used as a jitter estimate. If this
+estimate exceeds a threshold MAXTIME/2 (100 us), an error bit
+STA_PPSJITTER is raised in the status word.
+
+The frequency of the hardware oscillator is determined from the
+difference in hardware counter readings at the beginning and end of the
+calibration interval divided by the duration of the interval. However,
+the oscillator frequency tolerance, as much as 100 ppm, may cause the
+difference to exceed the tick value, creating an ambiguity. In order to
+avoid this ambiguity, the hardware counter value at the beginning of the
+interval is increased by the current pps_freq value once each second,
+but computed modulo the tick value. At the end of the interval, the
+difference between this value and the value computed from the hardware
+counter is the control signal for the FLL.
+
+Control signal samples which exceed the frequency tolerance MAXFREQ (100
+ppm) are discarded, as well as samples resulting from excessive interval
+duration jitter. In these cases an error bit STA_PPSERROR is raised in
+the status word. Surviving samples are then processed by a three-stage
+median filter. The median sample drives the FLL, while the difference
+between the other two samples represents the frequency dispersion.
+Frequency dispersion samples are averaged and used as a stabiity
+estimate. If this estimate is below a threshold MAXFREQ/4 (25 ppm), the
+median sample is used to correct the oscillator frequency pps_freq with
+a weight expressed as a shift PPS_AVG (2).
+
+Initially, an approximate value for the oscillator frequency is not
+known, so the duration of the calibration interval must be kept small to
+avoid overflowing the tick. The time difference at the end of the
+calibration interval is measured. If greater than tick/4, the interval
+is reduced by half. If less than this fraction for four successive
+calibration intervals, the interval is doubled. This design
+automatically adapts to nominal jitter in the PPS signal, as well as the
+value of tick. The duration of the calibration interval is set by the
+pps_shift variable as a shift in powers of two. The minimum value
+PPS_SHIFT (2) is chosen so that with the highest CPU oscillator
+frequency 1024 Hz and frequency tolerance 100 ppm the tick will not
+overflow. The maximum value PPS_SHIFTMAX (8) is chosen such that the
+maximum averaging time is about 1000 s as determined by measurements of
+Allan variance [MIL93].
+
+Should the PPS signal fail, the current frequency estimate pps_freq
+continues to be used, so the nominal frequency remains correct subject
+only to the instability of the undisciplined oscillator. The procedure
+to save and restore the frequency estimate works as follows. When
+setting the frequency from a file, the time_freq value is set as the
+file value minus the pps_freq value; when retrieving the frequency, the
+two values are added before saving in the file. This scheme provides a
+seamless interface should the PPS signal fail or the kernel
+configuration change. Note that the frequency discipline is active
+whether or not the synchronization daemon is active. Since all Unix
+systems take some time after reboot to build a running system, usually
+by that time the discipline process has already settled down and the
+initial transients due to frequency discipline have damped out.
+3.1.4. External Clock Interface
+
+The external clock driver interface is implemented with two routines,
+microtime(), which returns the current clock time, and clock_set(),
+which furnishes the apparent system time derived from the kernel time
+variable. The latter routine is called only when the clock is set using
+the settimeofday() system call, but can be called from within the
+driver, such as when the year rolls over, for example.
+
+In the stock SunOS kernel and modified Ultrix and OSF/1 kernels, the
+microtime() routine returns the kernel time variable plus an
+interpolation between timer interrupts based on the contents of a
+hardware counter. In the case of an external clock, such as described
+above, the system clock is read directly from the hardware clock
+registers. Examples of external clock drivers are in the tprotime.c and
+hightime.c routines included in the kernel.tar.Z distribution.
+
+The external clock routines return a status code which indicates whether
+the clock is operating correctly and the nature of the problem, if not.
+The return code is interpreted by the ntp_gettime() system call, which
+transitions the status state machine to the TIME_ERR state if an error
+code is returned. This is the only error checking implemented for the
+external clock in the present version of the code.
The simulator has been used to check the PLL operation over the design
-envelope of +-128 ms in time error and +-100 ppm in frequency error.
+envelope of +-512 ms in time error and +-100 ppm in frequency error.
This confirms that no overflows occur and that the loop initially
converges in about 15 minutes for timer interrupt rates from 50 Hz to
-1024 Hz. The loop has a normal overshoot of about seven percent and a
-final convergence time of several hours, depending on the initial time
-and frequency error.
+1024 Hz. The loop has a normal overshoot of a few percent and a final
+convergence time of several hours, depending on the initial time and
+frequency error.
-4.2. Leap Seconds
+3.2. Leap Seconds
It does not seem generally useful in the user application interface to
provide additional details private to the kernel and synchronization
@@ -571,205 +760,615 @@ independently evaluate the quality of time and project into the future
how long this time might be "valid." However, to do that properly would
duplicate the functionality of the synchronization protocol and require
knowledge of many mundane details of the platform architecture, such as
-the subnet configuration, reachability status and related variables.
-However, for the curious, the ntp_adjtime() system call can be used to
-reveal some of these mysteries.
+the subnet configuration, reachability status and related variables. For
+the curious, the ntp_adjtime() system call can be used to reveal some of
+these mysteries.
However, the user application may need to know whether a leap second is
scheduled, since this might affect interval calculations spanning the
event. A leap-warning condition is determined by the synchronization
protocol (if remotely synchronized), by the timecode receiver (if
available), or by the operator (if awake). This condition is set by the
-protocol daemon on the day the leap second is to occur (30 June or 31
-December, as announced) by specifying in a ntp_adjtime() system call a
-clock status of either TIME_DEL, if a second is to be deleted, or
-TIME_INS, if a second is to be inserted. Note that, on all occasions
+synchronization daemon on the day the leap second is to occur (30 June
+or 31 December, as announced) by specifying in a ntp_adjtime() system
+call a status bit of either STA_DEL, if a second is to be deleted, or
+STA_INS, if a second is to be inserted. Note that, on all occasions
since the inception of the leap-second scheme, there has never been a
-deletion occasion. If the value is TIME_DEL, the kernel adds one second
-to the system time immediately following second 23:59:58 and resets the
-clock status to TIME_OK. If the value is TIME_INS, the kernel subtracts
-one second from the system time immediately following second 23:59:59
-and resets the clock status to TIME_OOP, in effect causing system time
-to repeat second 59. Immediately following the repeated second, the
-kernel resets the clock status to TIME_OK.
+deletion, nor is there likely to be one in future. If the bit is
+STA_DEL, the kernel adds one second to the system time immediately
+following second 23:59:58 and resets the clock state to TIME_WAIT. If
+the bit is STA_INS, the kernel subtracts one second from the system time
+immediately following second 23:59:59 and resets the clock stateto
+TIME_OOP, in effect causing system time to repeat second 59. Immediately
+following the repeated second, the kernel resets the clock status to
+TIME_WAIT.
+
+Following the leap operations, the clock remains in the TIME_WAIT state
+until both the STA_DEL and STA_INS status bits are reset. This provides
+both an unambiguous indication that a leap recently occured, as well as
+time for the daemon or operator to clear the warning condition.
Depending upon the system call implementation, the reported time during
a leap second may repeat (with the TIME_OOP return code set to advertise
that fact) or be monotonically adjusted until system time "catches up"
to reported time. With the latter scheme the reported time will be
correct before and shortly after the leap second (depending on the
-number of microtime() calls during the leap second itself), but freeze
-or slowly advance during the leap second itself. However, Most programs
+number of microtime() calls during the leap second), but freeze or
+slowly advance during the leap second itself. However, Most programs
will probably use the ctime() library routine to convert from timeval
(seconds, microseconds) format to tm format (seconds, minutes,...). If
this routine is modified to use the ntp_gettime() system call and
inspect the return code, it could simply report the leap second as
second 60.
-To determine local midnight without fuss, the kernel simply finds the
-residue of the time.tv_sec value mod 86,400, but this requires a messy
-divide. Probably a better way to do this is to initialize an auxiliary
-counter in the settimeofday() routine using an ugly divide and increment
-the counter at the same time the time.tv_sec is incremented in the timer
-interrupt routine. For future embellishment.
+3.3. Clock Status State Machine
+
+The various options possible with the system clock model described in
+this memorandum require a careful examination of the state transitions,
+status indications and recovery procedures should a crucial signal or
+interface fail. In this section is presented a prototype state machine
+designed to support leap second insertion and deletion, as well as
+reveal various kinds of errors in the synchronization process. The
+states of this machine are decoded as follows:
+
+ TIME_OK If a PPS signal or external clock is present, it is
+ working properly and the system clock is derived
+ from it. If not, the synchronization daemon is
+ working properly and the system clock is
+ synchronized to a radio clock or one or more peers.
+
+ TIME_INS An insertion of one second in the system clock has
+ been declared following the last second of the
+ current day, but has not yet been executed.
+
+ TIME_DEL A deletion of the last second of the current day has
+ been declared, but not yet executed.
+
+ TIME_OOP An insertion of one second in the system clock has
+ been declared following the last second of the
+ current day. The second is in progress, but not yet
+ completed. Library conversion routines should
+ interpret this second as 23:59:60.
+
+ TIME_WAIT The scheduled leap event has occurred, but the
+ STA_DEL and STA_INS status bits have not yet been
+ cleared.
+
+ TIME_ERROR Either (a) the synchronization daemon has declared
+ the protocol is not working properly, (b) all
+ sources of outside synchronization have been lost or
+ (c) a PPS signal or external clock is present, but
+ not working properly.
+
+In all states the system clock is derived from either a PPS signal or
+external clock, if present, or the kernel time variable, if not. If a
+PPS error condition is recognized, the PPS signal is disabled and
+ntp_adjtime() updates are used instead. If an external clock error
+condition is recognized, the external clock is disabled and the kernel
+time variable is used instead.
+
+The state machine makes a transition once each second at an instant
+where the microseconds field of the kernel time variable overflows and
+one second is added to the seconds field. However, this condition is
+checked when the timer overflows, which may not coincide with the actual
+seconds increment. This may lead to some interesting anomalies, such as
+a status indication of a leap second in progress (TIME_OOP) when the
+leap second has already expired. This ambiguity is unavoidable, unless
+the timer interrupt is made synchronous with the system clock.
+
+The following state transitions are executed automatically by the kernel
+at rollover of the microseconds field:
+
+ any state -> TIME_ERROR This transition occurs when an error
+ condition is recognized and continues as long
+ as the condition persists. The error indication
+ overrides the normal state indication, but does
+ not affect the actual clock state. Therefore,
+ when the condition is cleared, the normal state
+ indication resumes.
+
+ TIME_OK->TIME_DEL This transition occurs if the STA_DEL bit is
+ set in the status word.
+
+ TIME_OK->TIME_INS This transition occurs if the STA_INS bit is
+ set in the status word.
+
+ TIME_INS->TIME_OOP This transition occurs immediately following
+ second 86,400 of the current day when an
+ insert-second event has been declared.
+
+ TIME_OOP->TIME_WAIT This transition occurs immediately following
+ second 86,401 of the current day; that is, one
+ second after entry to the TIME_OOP state.
+
+ TIME_DEL->TIME_WAIT This transition occurs immediately following
+ second 86,399 of the current day when a delete-
+ second event has been declared.
+
+ TIME_WAIT->TIME_OK This transition occurs when the STA_DEL and
+ STA_INS bits are cleared by an ntp_adjtime()
+ call.
+
+The following table summarizes the actions just before, during and just
+after a leap-second event. Each line in the table shows the UTC and NTP
+times at the beginning of the second. The left column shows the behavior
+when no leap event is to occur. In the middle column the state machine
+is in TIME_INS at the end of UTC second 23:59:59 and the NTP time has
+just reached 400. The NTP time is set back one second to 399 and the
+machine enters TIME_OOP. At the end of the repeated second the machine
+enters TIME_OK and the UTC and NTP times are again in correspondence. In
+the right column the state machine is in TIME_DEL at the end of UTC
+second 23:59:58 and the NTP time has just reached 399. The NTP time is
+incremented, the machine enters TIME_OK and both UTC and NTP times are
+again in correspondence.
+
+ No Leap Leap Insert Leap Delete
+ UTC NTP UTC NTP UTC NTP
+ ---------------------------------------------
+ 23:59:58|398 23:59:58|398 23:59:58|398
+ | | |
+ 23:59:59|399 23:59:59|399 00:00:00|400
+ | | |
+ 00:00:00|400 23:59:60|399 00:00:01|401
+ | | |
+ 00:00:01|401 00:00:00|400 00:00:02|402
+ | | |
+ 00:00:02|402 00:00:01|401 00:00:03|403
+ | | |
+To determine local midnight without fuss, the kernel code simply finds
+the residue of the time.tv_sec (or time.tv_sec + 1) value mod 86,400,
+but this requires a messy divide. Probably a better way to do this is to
+initialize an auxiliary counter in the settimeofday() routine using an
+ugly divide and increment the counter at the same time the time.tv_sec
+is incremented in the timer interrupt routine. For future embellishment.
+
+4. Programming Model and Interfaces
+
+This section describes the programming model for the synchronization
+daemon and user application programs. The ideas are based on suggestions
+from Jeff Mogul and Philip Gladstone and a similar interface designed by
+the latter. It is important to point out that the functionality of the
+original Unix adjtime() system call is preserved, so that the modified
+kernel will work as the unmodified one, should the new features not be
+in use. In this case the ntp_adjtime() system call can still be used to
+read and write kernel variables that might be used by a synchronization
+daemon other than NTP, for example.
+
+The kernel routines use the clock state variable time_state, which
+records whether the clock is synchronized, waiting for a leap second,
+etc. The value of this variable is returned as the result code by both
+the ntp_gettime() and ntp_adjtime() system calls. It is set implicitly
+by the STA_DEL and STA_INS status bits, as described previously. Values
+presently defined in the timex.h header file are as follows:
+
+ TIME_OK 0 no leap second warning
+ TIME_INS 1 insert leap second warning
+ TIME_DEL 2 delete leap second warning
+ TIME_OOP 3 leap second in progress
+ TIME_WAIT 4 leap second has occured
+ TIME_ERROR 5 clock not synchronized
+
+In case of a negative result code, the kernel has intercepted an invalid
+address or (in case of the ntp_adjtime() system call), a superuser
+violation.
+
+4.1. The ntp_gettime() System Call
+
+The syntax and semantics of the ntp_gettime() call are given in the
+following fragment of the timex.h header file. This file is identical,
+except for the SHIFT_HZ define, in the SunOS, Ultrix and OSF/1 kernel
+distributions. (The SHIFT_HZ define represents the logarithm to the base
+2 of the clock oscillator frequency specific to each system type.) Note
+that the timex.h file calls the syscall.h system header file, which must
+be modified to define the SYS_ntp_gettime system call specific to each
+system type. The kernel distributions include directions on how to do
+this.
+
+ /*
+ * This header file defines the Network Time Protocol (NTP)
+ * interfaces for user and daemon application programs. These are
+ * implemented using private system calls and data structures and
+ * require specific kernel support.
+ *
+ * NAME
+ * ntp_gettime - NTP user application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int system call(SYS_ntp_gettime, tptr)
+ *
+ * int SYS_ntp_gettime defined in syscall.h header file
+ * struct ntptimeval *tptr pointer to ntptimeval structure
+ *
+ * NTP user interface - used to read kernel clock values
+ * Note: maximum error = NTP synch distance = dispersion + delay /
+ * 2
+ * estimated error = NTP dispersion.
+ */
+ struct ntptimeval {
+ struct timeval time; /* current time (ro) */
+ long maxerror; /* maximum error (us) (ro) */
+ long esterror; /* estimated error (us) (ro) */
+ };
+
+The ntp_gettime() system call returns three read-only (ro) values in the
+ntptimeval structure: the current time in unix timeval format plus the
+maximum and estimated errors in microseconds. While the 32-bit long data
+type limits the error quantities to something more than an hour, in
+practice this is not significant, since the protocol itself will declare
+an unsynchronized condition well below that limit. In the NTP Version 3
+specification, if the protocol computes either of these values in excess
+of 16 seconds, they are clamped to that value and the system clock
+declared unsynchronized.
+
+Following is a detailed description of the ntptimeval structure members.
+
+struct timeval time (ro)
-4.2. Kernel Variables
+ This member is the current system time expressed as a Unix timeval
+ structure. The timeval structure consists of two 32-bit words; the
+ first is the number of seconds past 1 January 1970 assuming no
+ intervening leap-second insertions or deletions, while the second
+ is the number of microseconds within the second.
-The following kernel variables are defined by the new code:
+long maxerror (ro)
-long time_offset = 0; /* time adjustment (us) */
+ This member is the value of the time_maxerror kernel variable,
+ which represents the maximum error of the indicated time relative
+ to the primary synchronization source, in microseconds. For NTP,
+ the value is initialized by a ntp_adjtime() call to the
+ synchronization distance, which is equal to the root dispersion
+ plus one-half the root delay. It is increased by a small amount
+ (time_tolerance) each second to reflect the maximum clock frequency
+ error. This variable is provided bu a ntp-adjtime() system call and
+ modified by the kernel, but is otherwise not used by the kernel.
- This variable is used by the PLL to adjust the system time in small
- increments. It is scaled by (1 << SHIFT_UPDATE) in binary
- microseconds. The maximum value that can be represented is about +-
- 512 ms and the minimum value or precision is one microsecond.
+long esterror (ro)
-long time_constant = 0; /* pll time constant */
+ This member is the value of the time_esterror kernel variable,
+ which represents the expected error of the indicated time relative
+ to the primary synchronization source, in microseconds. For NTP,
+ the value is determined as the root dispersion, which represents
+ the best estimate of the actual error of the system clock based on
+ its past behavior, together with observations of multiple clocks
+ within the peer group. This variable is provided bu a ntp-adjtime()
+ system call, but is otherwise not used by the kernel.
+
+4.2. The ntp_adjtime() System Call
+
+The syntax and semantics of the ntp_adjtime() call are given in the
+following fragment of the timex.h header file. Note that, as in the
+ntp_gettime() system call, the syscall.h system header file must be
+modified to define the SYS_ntp_adjtime system call specific to each
+system type. In the fragment, rw = read/write, ro = read-only, wo =
+write-only.
+
+ /*
+ * NAME
+ * ntp_adjtime - NTP daemon application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int system call(SYS_ntp_adjtime, mode, tptr)
+ *
+ * int SYS_ntp_adjtime defined in syscall.h header file
+ * struct timex *tptr pointer to timex structure
+ *
+ * NTP daemon interface - used to discipline kernel clock
+ * oscillator
+ */
+ struct timex {
+ unsigned int mode; /* mode selector (wo) */
+ long offset; /* time offset (us) (rw) */
+ long frequency; /* frequency offset (scaled ppm) (rw)
+ */
+ long maxerror; /* maximum error (us) (rw) */
+ long esterror; /* estimated error (us) (rw) */
+ int status; /* clock status bits (rw) */
+ long constant; /* pll time constant (rw) */
+ long precision; /* clock precision (us) (ro) */
+ long tolerance; /* clock frequency tolerance (scaled
+ * ppm) (ro) */
+ /*
+ * The following read-only structure members are implemented
+ * only if the PPS signal discipline is configured in the
+ * kernel.
+ */
+ long ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ long jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro)
+ */
+ long stabil; /* pps stability (scaled ppm) (ro) */
+ long jitcnt; /* jitter limit exceeded (ro) */
+ long calcnt; /* calibration intervals (ro) */
+ long errcnt; /* calibration errors (ro) */
+ long stbcnt; /* stability limit exceeded (ro) */
+ };
- This variable determines the bandwidth or "stiffness" of the PLL.
- It is used as a shift, with the effective value in positive powers
- of two. The default value (0) corresponds to a PLL time constant of
- about 4 minutes.
+The ntp_adjtime() system call is used to read and write certain time-
+related kernel variables summarized below. Writing these variables can
+only be done in superuser mode. To write a variable, the mode structure
+member is set with one or more bits, one of which is assigned each of
+the following variables in turn. The current values for all variables
+are returned in any case; therefore, a mode argument of zero means to
+return these values without changing anything.
-long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
+Following is a description of the timex structure members.
- This variable represents the maximum frequency error or tolerance
- of the particular platform and is a property of the architecture.
- It is expressed as a positive number greater than zero in parts-
- per-million (ppm). The default MAXFREQ (100) is appropriate for
- conventional workstations.
+mode (wo)
-long time_precision = 1000000 / HZ; /* clock precision (us) */
+ This is a bit-coded variable selecting one or more structure
+ members, with one bit assigned each member. If a bit is set, the
+ value of the associated member variable is copied to the
+ corresponding kernel variable; if not, the member is ignored. The
+ bits are assigned as given in the following, with the variable name
+ indicated in parens. Note that the precision, tolerance and PPS
+ variables are determined by the kernel and cannot be changed by
+ ntp_adjtime().
+
+ MOD_OFFSET 0x0001 time offset (offset)
+ MOD_FREQUENCY 0x0002 frequency offset (frequency)
+ MOD_MAXERROR 0x0004 maximum time error (maxerror)
+ MOD_ESTERROR 0x0008 estimated time error (esterror)
+ MOD_STATUS 0x0010 clock status (status)
+ MOD_TIMECONST 0x0020 pll time constant (constant)
+ MOD_CLKB 0x4000 set clock B
+ MOD_CLKA 0x8000 set clock A
+
+ Note that the MOD_CLK0 and MOD_CLK1 bits are intended for those
+ systems where more than one hardware clock is available for backup,
+ such as in Tandem Non-Stop computers. Presumably, in such cases
+ each clock would have its own oscillator and require a separate PLL
+ for each. Refinements to this model are for further study. The
+ interpretation of these bits is as follows:
+
+offset (rw)
+
+ If selected, this member specifies the time adjustment, in
+ microseconds. The absolute value must be less than MAXPHASE
+ (128000) microseconds defined in the timex.h header file. On
+ return, this member contains the residual offset remaining between
+ a previously specified offset and the current system time, in
+ microseconds.
+
+frequency (rw)
+
+ If selected, this member replaces the value of the time_frequency
+ kernel variable. The value is in ppm, with the integer part in the
+ high order 16 bits and fraction in the low order 16 bits. The
+ absolute value must be in the range less than MAXFREQ (100) ppm
+ defined in the timex.h header file.
+
+ The time_freq variable represents the frequency offset of the CPU
+ clock oscillator. It is recalculated as each update to the system
+ clock is determined by the offset member of the timex structure. It
+ is usually set from a value stored in a file when the
+ synchronization daemon is first started. The current value is
+ usually retrieved via this member and written to the file about
+ once per hour.
+
+maxerror (rw)
- This variable represents the maximum error in reading the system
- clock. It is expressed as a positive number greater than zero in
- microseconds and is usually based on the number of microseconds
- between timer interrupts, 3906 usec for the Ultrix kernel, 976 usec
- for the OSF/1 kernel. However, in cases where the time can be
- interpolated between timer interrupts with microsecond resolution,
- such as in the unmodified SunOS kernel and modified Ultrix and
- OSF/1 kernels, the precision is specified as 1 usec. This variable
- is computed by the kernel for use by the time-synchronization
- daemon, but is otherwise not used by the kernel.
+ If selected, this member replaces the value of the time_maxerror
+ kernel variable, in microseconds. This is the same variable as in
+ the ntp_getime() system call.
-long time_maxerror; /* maximum error */
+esterror (rw)
- This variable establishes the maximum error of the indicated time
- relative to the primary reference source, in microseconds. For NTP,
- the value is determined as the synchronization distance, which is
- equal to the root dispersion plus one-half the root delay. It is
- increased by a small amount (time_tolerance) each second to reflect
- the clock frequency tolerance. This variable is computed by the
- time-synchronization daemon and the kernel, but is otherwise not
- used by the kernel.
+ If selected, this member replaces the value of the time_esterror
+ kernel variable, in microseconds. This is the same variable as in
+ the ntp_getime() system call.
-long time_esterror; /* estimated error */
+int status (rw)
- This variable establishes the expected error of the indicated time
- relative to the primary reference source, in microseconds. For NTP,
- the value is determined as the root dispersion, which represents
- the best estimate of the actual error of the system clock based on
- its past behavior, together with observations of multiple clocks
- within the peer group. This variable is computed by the time-
- synchronization daemon and returned in system calls, but is
- otherwise not used by the kernel.
-
-long time_phase = 0; /* phase offset (scaled us) */
-long time_freq = 0; /* frequency offset (scaled ppm) */
-time_adj = 0; /* tick adjust (scaled 1 / HZ) */
-
- These variables control the phase increment and the frequency
- increment of the system clock at each tick. The time_phase variable
- is scaled by (1 << SHIFT_SCALE) (24) in microseconds, giving a
- maximum adjustment of about +-128 us/tick and a resolution of about
- 60 femtoseconds/tick. The time_freq variable is scaled by (1 <<
- SHIFT_KF) in parts-per-million (ppm), giving it a maximum value of
- over +-2000 ppm and a minimum value (frequency resolution) of about
- 1e-5 ppm. The time_adj variable is the actual phase increment in
- scaled microseconds to add to time_phase once each tick. It is
- computed from time_phase and time_freq once per second.
-
-long time_reftime = 0; /* time at last adjustment (s) */
-
- This variable is the second's portion of the system time on the
- last call to adjtime(). It is used to adjust the time_freq variable
- as the time since the last update increases.
-
-int fixtick = 1000000 % HZ; /* amortization factor */
-
- In some systems such as the Ultrix and OSF/1 kernels, the local
- clock runs at some frequency that does not divide the number of
- microseconds in the second. In order that the clock runs at a
- precise rate, it is necessary to introduce an amortization factor
- into the local timescale, in effect a leap-multimicrosecond. This
- is not a new kernel variable, but a new use of an existing kernel
- variable.
-
-4.3. Architecture Constants
-
-Following is a list of the important architecture constants that
-establish the response and stability of the PLL and provide maximum
-bounds on behavior in order to satisfy correctness assertions made in
-the protocol specification.
-
-#define HZ 256 /* timer interrupt frequency (Hz) */
-#define SHIFT_HZ 8 /* log2(HZ) */
-
- The HZ define (a variable in some kernels) establishes the timer
- interrupt frequency, 100 Hz for the SunOS kernel, 256 Hz for the
- Ultrix kernel and 1024 Hz for the OSF/1 kernel. The SHIFT_HZ define
- expresses the same value as the nearest power of two in order to
- avoid hardware multiply operations. These are the only parameters
- that need to be changed for different kernel timer interrupt
- frequencies.
-
-#define SHIFT_KG 6 /* shift for phase increment */
-#define SHIFT_KF 16 /* shift for frequency increment */
-#define MAXTC 6 /* maximum time constant (shift) */
-
- These defines establish the response and stability characteristics
- of the PLL model. The SHIFT_KG and SHIFT_KF defines establish the
- damping of the PLL and are chosen by analysis for a slightly
- underdamped convergence characteristic. The MAXTC define
- establishes the maximum time constant of the PLL.
-
-#define SHIFT_SCALE (SHIFT_KF + SHIFT_HZ) /* shift for scale factor */
-#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* shift for offset scale
- * factor */
-#define SHIFT_USEC 16 /* shift for 1 us in external units */
-#define FINEUSEC (1 << SHIFT_SCALE) /* 1 us in scaled units */
-
- The SHIFT_SCALE define establishes the decimal point on the
- time_phase variable which serves as a an extension to the low-order
- bits of the system clock variable. The SHIFT_UPDATE define
- establishes the decimal point of the phase portion of the
- ntp_adjtime() update. The SHIFT_USEC define represents 1 us in
- external units (shift), while the FINEUSEC define represents 1 us
- in internal units.
-
-#define MAXPHASE 128000 /* max phase error (usec) */
-#define MAXFREQ 100 /* max frequency error (ppm) */
-#define MINSEC 16 /* min interval between updates (s) */
-#define MAXSEC 1200 /* max interval between updates (s) */
-
- These defines establish the performance envelope of the PLL, one to
- bound the maximum phase error, another to bound the maximum
- frequency error and two others to bound the minimum and maximum
- time between updates. The intent of these bounds is to force the
- PLL to operate within predefined limits in order to conform to the
- correctness models assumed by time-synchronization protocols like
- NTP and DTSS. An excursion which exceeds these bounds is clamped to
- the bound and operation proceeds accordingly. In practice, this can
- occur only if something has failed or is operating out of
- tolerance, but otherwise the PLL continues to operate in a stable
- mode. Note that the MAXPHASE define conforms to the maximum offset
- allowed in NTP before the system time is reset (by settimeofday(),
- rather than incrementally adjusted (by ntp_adjtime().
+ If selected, this member replaces the value of the time_status
+ kernel variable. This variable controls the state machine used to
+ insert or delete leap seconds and shows the status of the
+ timekeeping system, PPS signal and external oscillator, if
+ configured.
+
+ STA_PLL 0x0001 enable PLL updates (r/w)
+ STA_PPSFREQ 0x0002 enable PPS freq discipline (r/w)
+ STA_PPSTIME 0x0004 enable PPS time discipline (r/w)
+ STA_INS 0x0010 insert leap (r/w)
+ STA_DEL 0x0020 delete leap (r/w)
+ STA_UNSYNC 0x0040 clock unsynchronized (r/w)
+ STA_PPSSIGNAL 0x0100 PPS signal present (r)
+ STA_PPSJITTER 0x0200 PPS signal jitter exceeded (r)
+ STA_PPSWANDER 0x0400 PPS signal wander exceeded (r)
+ STA_PPSERROR 0x0800 PPS signal calibration error (r)
+ STA_CLOCKERR 0x1000 clock hardware fault (r)
+
+ The interpretation of these bits is as follows:
+
+ STA_PLL set/cleared by the caller to enable PLL updates
+
+ STA_PPSFREQ set/cleared by the caller to enable PPS frequency
+ discipline
+
+ STA_PPSTIME set/cleared by the caller to enable PPS time
+ discipline
+
+ STA_INS set by the caller to insert a leap second at the end
+ of the current day; cleared by the caller after the
+ event
+
+ STA_DEL set by the caller to delete a leap second at the end
+ of the current day; cleared by the caller after the
+ event
+
+ STA_UNSYNC set/cleared by the caller to indicate clock
+ unsynchronized (e.g., when no peers are reachable)
+
+ STA_PPSSIGNAL set/cleared by the hardpps() fragment to indicate
+ PPS signal present
+
+ STA_PPSJITTER set/cleared by the hardpps() fragment to indicates
+ PPS signal jitter exceeded
+
+ STA_PPSWANDER set/cleared by the hardpps() fragment to indicates
+ PPS signal wander exceeded
+
+ STA_PPSERROR set/cleared by the hardpps() fragment to indicates
+ PPS signal calibration error
+
+ STA_CLOCKERR set/cleared by the external hardware clock driver to
+ indicate hardware fault
+
+ An error condition is raised when (a) either STA_UNSYNC or
+ STA_CLOCKERR is set (loss of synchronization), (b) STA_PPSFREQ or
+ STA_PPSTIME is set and STA_PPSSIGNAL is clear (loss of PPS signal),
+ (c) STA_PPSTIME and STA_PPSJITTER are both set (jitter exceeded),
+ (d) STA_PPSFREQ is set and either STA_PPSWANDER or STA_PPSERROR is
+ set (wander exceeded). An error condition results in a system call
+ return code of TIME_ERROR.
+
+constant (rw)
+
+ If selected, this member replaces the value of the time_constant
+ kernel variable. The value must be between zero and MAXTC (6)
+ defined in the timex.h header file.
+
+ The time_constant variable determines the bandwidth or "stiffness"
+ of the PLL. The value is used as a shift between zero and MAXTC
+ (6), with the effective PLL time constant equal to a multiple of (1
+ << time_constant), in seconds. For room-temperature quartz
+ oscillators, the recommended default value is 2, which corresponds
+ to a PLL time constant of about 900 s and a maximum update interval
+ of about 64 s. The maximum update interval scales directly with the
+ time constant, so that at the maximum time constant of 6, the
+ update interval can be as large as 1024 s.
+
+ Values of time_constant between zero and 2 can be used if quick
+ convergence is necessary; values between 2 and 6 can be used to
+ reduce network load, but at a modest cost in accuracy. Values above
+ 6 are appropriate only if an precision external oscillator is
+ present.
+
+precision (ro)
+
+ This is the current value of the time_precision kernel variable in
+ microseconds.
+
+ The time_precision variable represents the maximum error in reading
+ the system clock, in microseconds. It is usually based on the
+ number of microseconds between timer interrupts (tick), 10000 us
+ for the SunOS kernel, 3906 us for the Ultrix kernel, 976 us for the
+ OSF/1 kernel. However, in cases where the time can be interpolated
+ between timer interrupts with microsecond resolution, such as in
+ the stock SunOS kernel and modified Ultrix and OSF/1 kernels, the
+ precision is specified as 1 us. In cases where a PPS signal or
+ external oscillator is available, the precision can depend on the
+ operating condition of the signal or oscillator. This variable is
+ determined by the kernel for use by the synchronization daemon, but
+ is otherwise not used by the kernel.
+
+tolerance (ro)
+
+ This is the current value of the time_tolerance kernel variable.
+ The value is in ppm, with the integer part in the high order 16
+ bits and fraction in the low order 16 bits.
+
+ The time_tolerance variable represents the maximum frequency error
+ in ppm of the particular CPU clock oscillator and is a property of
+ the hardware; however, in principle it could change as result of
+ the presence of external discipline signals, for instance.
+
+ The recommended value for time_tolerance MAXFREQ (200) ppm is
+ appropriate for room-temperature quartz oscillators used in typical
+ workstations. However, it can change due to the operating condition
+ of the PPS signal and/or external oscillator. With either the PPS
+ signal or external oscillator, the recommended value for MAXFREQ is
+ 100 ppm.
+
+The following members are defined only if the PPS_SYNC option is
+specified in the kernel configuration file. These members are useful
+primarily as a monitoring and evalutation tool. These variables can be
+written only by the kernel.
+
+ppsfreq (ro)
+
+ This is the current value of the pps_freq kernel variable, which is
+ the CPU clock oscillator frequency offset relative to the PPS
+ discipline signal. The value is in ppm, with the integer part in
+ the high order 16 bits and fraction in the low order 16 bits.
+
+jitter (ro)
+
+ This is the current value of the pps_jitter kernel variable, which
+ is the average PPS time dispersion measured by the time-offset
+ median filter, in microseconds.
+
+shift (ro)
+
+ This is the current value of the pps_shift kernel variable, which
+ determines the duration of the calibration interval as the value of
+ 1 << pps_shift, in seconds.
+stabil (ro)
+
+ This is the current value of the pps_stabil kernel variable, which
+ is the average PPS frequency dispersion measured by the frequency-
+ offset median filter. The value is in ppm, with the integer part in
+ the high order 16 bits and fraction in the low order 16 bits.
+
+jitcnt (ro)
+
+ This is the current value of the pps_jitcnt kernel variable, counts
+ the number of PPS signals where the average jitter exceeds the
+ threshold MAXTIME (200 us).
+
+calcnt (ro)
+
+ This is the current value of the pps_calcnt kernel variable, which
+ counts the number of frequency calibration intervals. The duration
+ of these intervals can range from 4 to 256 seconds, as determined
+ by the pps_shift kernel variable.
+
+errcnt (ro)
+
+ This is the current value of the pps_errcnt kernel variable, which
+ counts the number of frequency calibration cycles where (a) the
+ apparent frequency offset is greater than MAXFREQ (100 ppm) or (b)
+ the interval jitter exceeds tick * 2.
+
+stbcnt (ro)
+
+ This is the current value of the pps_discnt kernel variable, which
+ counts the number of calibration intervals where the average
+ stability exceeds the threshold MAXFREQ / 4 (25 ppm).
+
+7. References
+
+[MIL91] Mills, D.L. Internet time synchronization: the Network Time
+Protocol, IEEE Trans. Communications COM-39, 10 (October 1991),
+1482-1493. Also in: Yang, Z., and T.A. Marsland (Eds.). Global
+States and Time in Distributed Systems, IEEE Press, Los Alamitos,
+CA, 91-102.
+
+[MIL92a] Mills, D.L. Network Time Protocol (Version 3) specification,
+implementation and analysis, RFC 1305, University of Delaware, March
+1992, 113 pp.
+
+[MIL92b] Mills, D.L. Modelling and analysis of computer network clocks,
+Electrical Engineering Department Report 92-5-2, University of Delaware,
+May 1992, 29 pp.
+
+[MIL92c] Mills, D.L. Simple Network Time Protocol (SNTP), RFC 1361,
+University of Delaware, August 1992, 10 pp.
+
+[MIL93] Mills, D.L. Precision synchronizatin of computer network clocks,
+Electrical Engineering Department Report 93-11-1, University of
+Delaware, November 1993, 66 pp.
+
+[LEV89] Levine, J., M. Weiss, D. Davis, D. Allan, and D. Sullivan. The
+NIST automated computer time service. J. Research National Institute of
+Standards and Technology 94, 5 (September-October 1989), 311-321.
David L. Mills <mills@udel.edu>
Electrical Engineering Department
University of Delaware
Newark, DE 19716
302 831 8247 fax 302 831 4316
-
-1 April 1992
+3 April 1994
diff --git a/contrib/xntpd/doc/notes.txt b/contrib/xntpd/doc/notes.txt
index 5ea2b3318bb3..1dd59f25b3ac 100644
--- a/contrib/xntpd/doc/notes.txt
+++ b/contrib/xntpd/doc/notes.txt
@@ -785,7 +785,7 @@ configuration functionality (though the only thing you can currently do
with mode-6 messages is set the leap-second warning bits) and the ntpq
program provides generic support for the latter. The leap bits that can be
set in the leap_warning variable (up to one month ahead) and in the
-leap_indication variable have a slighly different encoding than the
+leap_indication variable have a slightly different encoding than the
usual interpretation:
Value Action
diff --git a/contrib/xntpd/gadget/.keep_me b/contrib/xntpd/gadget/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/gadget/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/hints/.keep_me b/contrib/xntpd/hints/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/hints/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/include/l_stdlib.h b/contrib/xntpd/include/l_stdlib.h
index 89a8092853b5..e0b7c474095c 100644
--- a/contrib/xntpd/include/l_stdlib.h
+++ b/contrib/xntpd/include/l_stdlib.h
@@ -70,11 +70,11 @@ extern int getppid P((void));
extern int close P((int));
extern int ioctl P((int, int, char *));
-extern int read P((int, char *, unsigned));
+extern int read P((int, void *, unsigned));
extern int rename P((char *, char *));
-extern int write P((int, char *, int));
-extern int unlink P((char *));
-extern int link P((char *, char *));
+extern int write P((int, const void *, unsigned));
+extern int unlink P((const char *));
+extern int link P((const char *, const char *));
#ifdef FILE
extern int fclose P((FILE *));
diff --git a/contrib/xntpd/include/ntp.h b/contrib/xntpd/include/ntp.h
index 310353f1cda2..01bfa16a7ad8 100644
--- a/contrib/xntpd/include/ntp.h
+++ b/contrib/xntpd/include/ntp.h
@@ -173,6 +173,7 @@ struct interface {
#define INT_BROADCAST 1 /* can broadcast out this interface */
#define INT_BCASTOPEN 2 /* broadcast socket is open */
#define INT_LOOPBACK 4 /* the loopback interface */
+#define INT_MULTICAST 8 /* multicasting enabled */
/*
* Define flasher bits (tests 1 through 8 in packet procedure)
@@ -222,7 +223,7 @@ struct peer {
U_LONG keyid; /* encription key ID */
U_LONG pkeyid; /* keyid used to encrypt last message */
u_short associd; /* association ID, a unique integer */
- u_char unused;
+ u_char ttl; /* time to live (multicast) */
/* **Start of clear-to-zero area.*** */
/* Everything that is cleared to zero goes below here */
u_char valid; /* valid counter */
@@ -248,12 +249,6 @@ struct peer {
s_fp soffset; /* fp version of above */
s_fp synch; /* synch distance from above */
u_fp selectdisp; /* select dispersion */
-
- /*
- * Stuff related to the experimental broadcast delay
- * determination code. The registers will probably go away
- * later.
- */
U_LONG estbdelay; /* broadcast delay, as a ts fraction */
/*
@@ -346,7 +341,7 @@ struct peer {
*/
#define REFCLK_NONE 0 /* unknown or missing */
#define REFCLK_LOCALCLOCK 1 /* external (e.g., ACTS) */
-#define REFCLK_WWV_HEATH 2 /* Heath GC-1000 WWV/H */
+#define REFCLK_GPS_TRAK 2 /* TRAK 8810 GPS Receiver */
#define REFCLK_WWV_PST 3 /* PST/Traconex 1020 WWV/H */
#define REFCLK_WWVB_SPECTRACOM 4 /* Spectracom 8170/Netclock WWVB */
#define REFCLK_GOES_TRUETIME 5 /* TrueTime 468-DC GOES */
@@ -579,8 +574,8 @@ struct recvbuf {
#define PROTO_AUTHENTICATE 3
#define PROTO_BROADDELAY 4
#define PROTO_AUTHDELAY 5
-#define PROTO_MAXSKEW 6
-#define PROTO_SELECT 7
+#define PROTO_MULTICAST_ADD 6
+#define PROTO_MULTICAST_DEL 7
/*
* Configuration items for the loop filter
@@ -603,7 +598,7 @@ struct recvbuf {
*/
#define DEFPRECISION (-5) /* conservatively low */
#define DEFBROADDELAY (0x020c49ba) /* 8 ms. This is round trip delay */
-
+#define INADDR_NTP 0xe0000101 /* NTP multicast address 224.0.1.1 */
/*
* Structure used optionally for monitoring when this is turned on.
*/
@@ -612,6 +607,9 @@ struct mon_data {
struct mon_data *hash_prev; /* previous structure in hash list */
struct mon_data *mru_next; /* next structure in MRU list */
struct mon_data *mru_prev; /* previous structure in MRU list */
+ struct mon_data *fifo_next; /* next structure in FIFO list */
+ struct mon_data *fifo_prev; /* previous structure in FIFO list */
+ U_LONG lastdrop; /* last time dropped due to RES_LIMIT*/
U_LONG lasttime; /* last time data updated */
U_LONG firsttime; /* time structure initialized */
U_LONG count; /* count we have seen */
@@ -621,7 +619,12 @@ struct mon_data {
u_char version; /* version of incoming packet */
};
-
+/*
+ * Values used with mon_enabled to indicate reason for enabling monitoring
+ */
+#define MON_OFF 0x00 /* no monitoring */
+#define MON_ON 0x01 /* monitoring explicitly enabled */
+#define MON_RES 0x02 /* implicit monitoring for RES_LIMITED */
/*
* Structure used for restrictlist entries
*/
@@ -645,10 +648,11 @@ struct restrictlist {
#define RES_NOPEER 0x20 /* don't allocate memory resources */
#define RES_NOTRAP 0x40 /* don't allow him to set traps */
#define RES_LPTRAP 0x80 /* traps set by him are low priority */
+#define RES_LIMITED 0x100 /* limit per net number of clients */
#define RES_ALLFLAGS \
(RES_IGNORE|RES_DONTSERVE|RES_DONTTRUST|RES_NOQUERY\
- |RES_NOMODIFY|RES_NOPEER|RES_NOTRAP|RES_LPTRAP)
+ |RES_NOMODIFY|RES_NOPEER|RES_NOTRAP|RES_LPTRAP|RES_LIMITED)
/*
* Match flags
diff --git a/contrib/xntpd/include/ntp_control.h b/contrib/xntpd/include/ntp_control.h
index 74f75f17f51a..1e193835660d 100644
--- a/contrib/xntpd/include/ntp_control.h
+++ b/contrib/xntpd/include/ntp_control.h
@@ -68,6 +68,7 @@ struct ntp_control {
#define CTL_SST_TS_UDPTIME 7 /* time source UDP/TIME */
#define CTL_SST_TS_WRSTWTCH 8 /* time source is wristwatch */
#define CTL_SST_TS_TELEPHONE 9 /* time source is telephone modem */
+#define CTL_SST_TS_PPS 0x20 /* time source is PPS signal */
#define CTL_SYS_MAXEVENTS 15
diff --git a/contrib/xntpd/include/ntp_if.h b/contrib/xntpd/include/ntp_if.h
index 1a76ca02da4b..45a70c51bcd5 100644
--- a/contrib/xntpd/include/ntp_if.h
+++ b/contrib/xntpd/include/ntp_if.h
@@ -16,6 +16,10 @@
#include <sys/sockio.h>
#endif
+#if defined(SYS_UNIXWARE1)
+#include <sys/sockio.h>
+#endif
+
#if defined(SYS_PTX) || defined(SYS_SINIXM)
#include <sys/stream.h>
#include <sys/stropts.h>
diff --git a/contrib/xntpd/include/ntp_in.h b/contrib/xntpd/include/ntp_in.h
new file mode 100755
index 000000000000..80aa45151fc6
--- /dev/null
+++ b/contrib/xntpd/include/ntp_in.h
@@ -0,0 +1,259 @@
+/* @(#)in.h 1.19 90/07/27 SMI; from UCB 7.5 2/22/88 */
+
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+/*
+ * Constants and structures defined by the internet system,
+ * Per RFC 790, September 1981.
+ */
+
+#ifndef _netinet_in_h
+#define _netinet_in_h
+#define _NETINET_IN_H_
+#define _SYS_IN_INCLUDED
+#define __IN_HEADER
+
+/*
+ * Protocols
+ */
+#define IPPROTO_IP 0 /* dummy for IP */
+#define IPPROTO_ICMP 1 /* control message protocol */
+#define IPPROTO_IGMP 2 /* group control protocol */
+#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
+#define IPPROTO_ST 5 /* st */
+#define IPPROTO_TCP 6 /* tcp */
+#define IPPROTO_EGP 8 /* exterior gateway protocol */
+#define IPPROTO_PUP 12 /* pup */
+#define IPPROTO_UDP 17 /* user datagram protocol */
+#define IPPROTO_IDP 22 /* xns idp */
+#define IPPROTO_HELLO 63 /* "hello" routing protocol */
+#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
+#define IPPROTO_OSPF 89 /* Open SPF IGP */
+
+#define IPPROTO_RAW 255 /* raw IP packet */
+#define IPPROTO_MAX 256
+
+/*
+ * Port/socket numbers: network standard functions
+ */
+#define IPPORT_ECHO 7
+#define IPPORT_DISCARD 9
+#define IPPORT_SYSTAT 11
+#define IPPORT_DAYTIME 13
+#define IPPORT_NETSTAT 15
+#define IPPORT_FTP 21
+#define IPPORT_TELNET 23
+#define IPPORT_SMTP 25
+#define IPPORT_TIMESERVER 37
+#define IPPORT_NAMESERVER 42
+#define IPPORT_WHOIS 43
+#define IPPORT_MTP 57
+
+/*
+ * Port/socket numbers: host specific functions
+ */
+#define IPPORT_TFTP 69
+#define IPPORT_RJE 77
+#define IPPORT_FINGER 79
+#define IPPORT_TTYLINK 87
+#define IPPORT_SUPDUP 95
+
+/*
+ * UNIX TCP sockets
+ */
+#define IPPORT_EXECSERVER 512
+#define IPPORT_LOGINSERVER 513
+#define IPPORT_CMDSERVER 514
+#define IPPORT_EFSSERVER 520
+
+/*
+ * UNIX UDP sockets
+ */
+#define IPPORT_BIFFUDP 512
+#define IPPORT_WHOSERVER 513
+#define IPPORT_ROUTESERVER 520 /* 520+1 also used */
+
+/*
+ * Ports < IPPORT_RESERVED are reserved for
+ * privileged processes (e.g. root).
+ * Ports > IPPORT_USERRESERVED are reserved
+ * for servers, not necessarily privileged.
+ */
+#define IPPORT_RESERVED 1024
+#define IPPORT_USERRESERVED 5000
+
+/*
+ * Link numbers
+ */
+#define IMPLINK_IP 155
+#define IMPLINK_LOWEXPER 156
+#define IMPLINK_HIGHEXPER 158
+
+/*
+ * Internet address
+ * This definition contains obsolete fields for compatibility
+ * with SunOS 3.x and 4.2bsd. The presence of subnets renders
+ * divisions into fixed fields misleading at best. New code
+ * should use only the s_addr field.
+ */
+struct in_addr {
+ union {
+ struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
+ struct { u_short s_w1,s_w2; } S_un_w;
+ u_long S_addr;
+ } S_un;
+#define s_addr S_un.S_addr /* should be used for all code */
+#define s_host S_un.S_un_b.s_b2 /* OBSOLETE: host on imp */
+#define s_net S_un.S_un_b.s_b1 /* OBSOLETE: network */
+#define s_imp S_un.S_un_w.s_w2 /* OBSOLETE: imp */
+#define s_impno S_un.S_un_b.s_b4 /* OBSOLETE: imp # */
+#define s_lh S_un.S_un_b.s_b3 /* OBSOLETE: logical host */
+};
+
+/*
+ * Definitions of bits in internet address integers.
+ * On subnets, the decomposition of addresses to host and net parts
+ * is done according to subnet mask, not the masks here.
+ */
+#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST 0x00ffffff
+#define IN_CLASSA_MAX 128
+
+#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST 0x0000ffff
+#define IN_CLASSB_MAX 65536
+
+#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST 0x000000ff
+
+#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
+#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
+#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
+#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
+#define IN_MULTICAST(i) IN_CLASSD(i)
+
+#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000)
+#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
+
+#define INADDR_ANY (u_long)0x00000000
+#define INADDR_LOOPBACK (u_long)0x7F000001
+#define INADDR_BROADCAST (u_long)0xffffffff /* must be masked */
+
+#define INADDR_UNSPEC_GROUP (u_long)0xe0000000 /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP (u_long)0xe0000001 /* 224.0.0.1 */
+#define INADDR_MAX_LOCAL_GROUP (u_long)0xe00000ff /* 224.0.0.255 */
+
+#define IN_LOOPBACKNET 127 /* official! */
+
+/*
+ * Define a macro to stuff the loopback address into an Internet address
+ */
+#define IN_SET_LOOPBACK_ADDR(a) {(a)->sin_addr.s_addr = htonl(INADDR_LOOPBACK); \
+ (a)->sin_family = AF_INET;}
+
+/*
+ * Socket address, internet style.
+ */
+struct sockaddr_in {
+ short sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+/*
+ * Options for use with [gs]etsockopt at the IP level.
+ */
+#define IP_OPTIONS 1 /* set/get IP per-packet options */
+#define IP_MULTICAST_IF 2 /* set/get IP multicast interface */
+#define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */
+#define IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */
+#define IP_ADD_MEMBERSHIP 5 /* add an IP group membership */
+#define IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */
+
+#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
+#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
+#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
+
+/*
+ * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
+ */
+struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+#if !defined(vax) && !defined(ntohl) && !defined(i386)
+/*
+ * Macros for number representation conversion.
+ */
+#define ntohl(x) (x)
+#define ntohs(x) (x)
+#define htonl(x) (x)
+#define htons(x) (x)
+#endif
+
+#if !defined(ntohl) && (defined(vax) || defined(i386))
+u_short ntohs(), htons();
+u_long ntohl(), htonl();
+#endif
+
+#ifdef KERNEL
+extern struct domain inetdomain;
+extern struct protosw inetsw[];
+struct in_addr in_makeaddr();
+u_long in_netof(), in_lnaof();
+#endif
+
+#ifndef BYTE_ORDER
+/*
+ * Definitions for byte order,
+ * according to byte significance from low address to high.
+ */
+#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */
+#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
+#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */
+
+#if defined(vax) || defined(i386)
+#define BYTE_ORDER LITTLE_ENDIAN
+#else
+#define BYTE_ORDER BIG_ENDIAN /* mc68000, tahoe, most others */
+#endif
+#endif BYTE_ORDER
+
+/*
+ * Macros for number representation conversion.
+ */
+#if BYTE_ORDER==LITTLE_ENDIAN
+#define NTOHL(d) ((d) = ntohl((d)))
+#define NTOHS(d) ((d) = ntohs((d)))
+#define HTONL(d) ((d) = htonl((d)))
+#define HTONS(d) ((d) = htons((d)))
+#else
+#define ntohl(x) (x)
+#define ntohs(x) (x)
+#define htonl(x) (x)
+#define htons(x) (x)
+#define NTOHL(d)
+#define NTOHS(d)
+#define HTONL(d)
+#define HTONS(d)
+#endif
+
+#endif /*!_netinet_in_h*/
diff --git a/contrib/xntpd/include/ntp_io.h b/contrib/xntpd/include/ntp_io.h
index c3b79be0616c..d60f08359b84 100644
--- a/contrib/xntpd/include/ntp_io.h
+++ b/contrib/xntpd/include/ntp_io.h
@@ -3,6 +3,7 @@
* SEEK_SET symbol form <untisd.h>.
*/
#if defined(NTP_POSIX_SOURCE)
+
/*
* POSIX way
*/
diff --git a/contrib/xntpd/include/ntp_machine.h b/contrib/xntpd/include/ntp_machine.h
index 1c3983e4a9ef..16c3fbf6da83 100644
--- a/contrib/xntpd/include/ntp_machine.h
+++ b/contrib/xntpd/include/ntp_machine.h
@@ -44,11 +44,16 @@ Signaled IO - Signled IO defines.
WHICH TERMINAL MODEL TO USE - I would assume HAVE_TERMIOS if
NTP_POSIX_SOURCE was set but can't. The
posix tty driver is too restrictive on most systems.
- It defined if you define STREAMS.
+ It is defined if you define STREAMS.
+ We do not put these defines in the ntp_machine.h as some systems
+ offer multiple interfaces and refclock configuration likes to
+ peek into the configuration defines for tty model restrictions.
+ Thus all tty definitions should be in the files in the machines directory.
+
+ HAVE_TERMIOS - Use POSIX termios.h
HAVE_SYSV_TTYS - Use SYSV termio.h
HAVE_BSD_TTYS - Use BSD stty.h
- HAVE_TERMIOS - Use POSIX termios.h
THIS MAKES PORTS TO NEW SYSTEMS EASY - You only have to wory about
kernel mucking.
@@ -79,6 +84,7 @@ INFO ON NEW KERNEL PLL SYS CALLS
NTP_SYSCALLS_STD - use the "normal" ones
NTP_SYSCALL_GET - SYS_ntp_gettime id
NTP_SYSCALL_ADJ - SYS_ntp_adjtime id
+ NTP_SYSCALLS_LIBC - ntp_adjtime() and ntp_gettime() are in libc.
HOW TO GET IP INTERFACE INFORMATION
@@ -274,7 +280,6 @@ in this file.
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/Ultrix"
#endif
-#define HAVE_TERMIOS
#endif
/*
@@ -297,9 +302,9 @@ in this file.
#define FORCE_NTPDATE_STEP
#define RETSIGTYPE void
#define HAVE_ATT_SETPGRP
-#define HAVE_BSD_TTYS
#define LOG_NTP LOG_LOCAL1
#define HAVE_SIGNALED_IO
+#define NTP_NEED_BOPS
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/AUX"
#endif
@@ -309,6 +314,7 @@ in this file.
* Next
*/
#if defined(SYS_NEXT)
+#define RETSIGTYPE void
#define DOSYNCTODR
#define HAVE_READKMEM
#define HAVE_BSD_NICE
@@ -329,8 +335,12 @@ in this file.
#define setlinebuf(f) setvbuf(f, NULL, _IOLBF, 0)
#define NO_SIGNED_CHAR_DECL
#define LOCK_PROCESS
-#define HAVE_NO_NICE /* HPUX uses rtprio instead */
#define RETSIGTYPE void
+#if (SYS_HPUX < 9)
+#define HAVE_NO_NICE /* HPUX uses rtprio instead */
+#else
+#define HAVE_BSD_NICE /* new at 9.X */
+#endif
#if (SYS_HPUX < 10)
#define NOKMEM
#else
@@ -352,8 +362,6 @@ in this file.
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/BSDI"
#endif
-#define HAVE_BSD_TTYS
-#define HAVE_TERMIOS
#endif
/*
@@ -387,6 +395,13 @@ in this file.
#define STR_SYSTEM "UNIX/*BSD"
#endif
#endif
+#ifdef SYS_FREEBSD
+#define HAVE_TERMIOS
+#define HAVE_UNAME
+#define HAVE_SYS_TIMEX_H
+#define NTP_SYSCALLS_LIBC
+#define KERNEL_PLL
+#endif
/*
* DEC AXP OSF/1
@@ -441,9 +456,6 @@ in this file.
*/
#if defined(SYS_PTX)
#define NO_SIGNED_CHAR_DECL
-#ifndef HAVE_SYSV_TTYS
-#define HAVE_SYSV_TTYS
-#endif
#define STREAMS_TLI
#define HAVE_ATT_SETPGRP
#define HAVE_SIGNALED_IO
@@ -458,6 +470,7 @@ in this file.
#define HAVE_READKMEM
#define UDP_WILDCARD_DELIVERY
#define NTP_POSIX_SOURCE
+#define memmove(x, y, z) memcpy(x, y, z)
struct timezone { int __0; }; /* unused placebo */
/*
* no comment !@!
@@ -521,13 +534,46 @@ typedef unsigned long u_long;
#endif
/*
+ * (Univel/Novell) Unixware1 SVR4 on intel x86 processor
+ */
+#if defined(SYS_UNIXWARE1)
+/* #define _POSIX_SOURCE */
+#undef HAVE_ATT_SETPGRP
+#define USE_PROTOTYPES
+#define NTP_POSIX_SOURCE
+#define HAVE_ATT_NICE
+#define HAVE_READKMEM
+#define USE_TTY_SIGPOLL
+#define USE_UDP_SIGPOLL
+#define UDP_WILDCARD_DELIVERY
+#undef HAVE_SIGNALED_IO
+#define STREAM
+#define STREAMS
+#ifndef STREAMS_TLI
+/*#define STREAMS_TLI*/
+#endif
+/* #define USE_STREAMS_DEVICE_FOR_IF_CONFIG */
+#undef STEP_SLEW /* TWO step */
+#define LOCK_PROCESS
+#define NO_SIGNED_CHAR_DECL
+#undef SYSV_TIMEOFDAY
+#define SIZE_RETURNED_IN_BUFFER
+#define RETSIGTYPE void
+#include <sys/sockio.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#ifndef STR_SYSTEM
+#define STR_SYSTEM "UNIX/Unixware1"
+#endif
+#endif
+
+/*
* DomainOS
*/
#if defined(SYS_DOMAINOS)
#define HAVE_BSD_NICE
#define NOKMEM
#define HAVE_SIGNALED_IO
-#define HAVE_BSD_TTYS
#define NTP_SYSCALLS_STD
#define USE_PROTOTYPES
#define UDP_WILDCARD_DELIVERY
@@ -565,6 +611,20 @@ typedef unsigned long u_long;
ERROR You_must_define_one_of_the_HAVE_xx_NICE_defines
#endif
+/*
+ * use only one tty model - no use in initialising
+ * a tty in three ways
+ * HAVE_TERMIOS is preferred over HAVE_SYSV_TTYS over HAVE_BSD_TTYS
+ */
+#ifdef HAVE_TERMIOS
+#undef HAVE_BSD_TTYS
+#undef HAVE_SYSV_TTYS
+#endif
+
+#ifdef HAVE_SYSV_TTYS
+#undef HAVE_BSD_TTYS
+#endif
+
#if !defined(HAVE_SYSV_TTYS) \
&& !defined(HAVE_BSD_TTYS) \
&& !defined(HAVE_TERMIOS)
diff --git a/contrib/xntpd/include/ntp_request.h b/contrib/xntpd/include/ntp_request.h
index e94cb452aac7..b1a947291316 100644
--- a/contrib/xntpd/include/ntp_request.h
+++ b/contrib/xntpd/include/ntp_request.h
@@ -254,9 +254,8 @@ struct resp_pkt {
#define REQ_GET_LEAPINFO 35 /* get leap information */
#define REQ_GET_CLOCKINFO 36 /* get clock information */
#define REQ_SET_CLKFUDGE 37 /* set clock fudge factors */
-#define REQ_SET_MAXSKEW 38 /* set the maximum skew factor */
+#define REQ_GET_KERNEL 38 /* get kernel pll/pps information */
#define REQ_GET_CLKBUGINFO 39 /* get clock debugging info */
-#define REQ_SET_SELECT_CODE 40 /* set selection algorithm */
#define REQ_SET_PRECISION 41 /* set clock precision */
@@ -267,8 +266,9 @@ struct resp_pkt {
#define INFO_FLAG_SYSPEER 0x2
#define INFO_FLAG_MINPOLL 0x4
#define INFO_FLAG_REFCLOCK 0x8
+#define INFO_FLAG_MCLIENT 0x8 /* danger */
#define INFO_FLAG_BCLIENT 0x10
-#define INFO_FLAG_PREFER 0x10 /* SHARES BCLIENT bit - ok since mutually exclusive - Oh why ist flags a u_char ? */
+#define INFO_FLAG_PREFER 0x10 /* danger */
#define INFO_FLAG_AUTHENABLE 0x20
#define INFO_FLAG_SEL_CANDIDATE 0x40
#define INFO_FLAG_SHORTLIST 0x80
@@ -323,10 +323,10 @@ struct info_peer {
u_char valid; /* peer.valid */
u_char reach; /* peer.reach */
u_char unreach; /* peer.unreach */
- u_char trust; /* peer.trust */
- u_char unused1;
- u_char unused2;
- u_char unused3;
+ u_char flash; /* peer.flash */
+ u_char ttl; /* peer.ttl */
+ u_char unused8; /* (obsolete) */
+ u_char unused9;
u_short associd; /* association ID */
U_LONG keyid; /* auth key in use */
U_LONG pkeyid; /* peer.pkeyid */
@@ -344,7 +344,14 @@ struct info_peer {
s_fp delay; /* peer.estdelay */
u_fp dispersion; /* peer.estdisp */
l_fp offset; /* peer.estoffset */
- U_LONG bdelay[NTP_SHIFT]; /* broadcast delay filters */
+ u_fp selectdisp; /* peer select dispersion */
+ LONG unused1; /* (obsolete) */
+ LONG unused2;
+ LONG unused3;
+ LONG unused4;
+ LONG unused5;
+ LONG unused6;
+ LONG unused7;
U_LONG estbdelay; /* broadcast delay */
};
@@ -406,12 +413,13 @@ struct info_sys {
U_LONG refid; /* reference ID of sync source */
l_fp reftime; /* system reference time */
U_LONG poll; /* system poll interval */
- u_short flags; /* system flags */
- u_char selection; /* selection algorithm code */
- u_char unused;
- l_fp bdelay; /* default broadcast delay, a ts fraction */
+ u_char flags; /* system flags */
+ u_char unused1; /* unused */
+ u_char unused2; /* unused */
+ u_char unused3; /* unused */
+ l_fp bdelay; /* default broadcast delay */
l_fp authdelay; /* default authentication delay */
- u_fp maxskew; /* maximum skew parameter (obsolete) */
+ u_fp maxskew; /* (obsolete) */
};
@@ -428,6 +436,24 @@ struct info_sys_stats {
U_LONG badlength; /* packets with bad length */
U_LONG processed; /* packets processed */
U_LONG badauth; /* packets dropped because of authorization */
+ U_LONG wanderhold; /* (obsolete) */
+ U_LONG limitrejected; /* rejected because of client limitation */
+};
+
+
+/*
+ * System stats - old version
+ */
+struct old_info_sys_stats {
+ U_LONG timeup; /* time we have been up and running */
+ U_LONG timereset; /* time since these were last cleared */
+ U_LONG badstratum; /* packets claiming an invalid stratum */
+ U_LONG oldversionpkt; /* old version packets received */
+ U_LONG newversionpkt; /* new version packets received */
+ U_LONG unknownversion; /* don't know version packets */
+ U_LONG badlength; /* packets with bad length */
+ U_LONG processed; /* packets processed */
+ U_LONG badauth; /* packets dropped because of authorization */
U_LONG wanderhold;
};
@@ -486,7 +512,8 @@ struct conf_peer {
u_char minpoll; /* min host poll interval */
u_char maxpoll; /* max host poll interval */
u_char flags; /* flags for this request */
- u_char unused;
+ u_char ttl; /* time to live (multicast) */
+ u_short unused; /* unused */
U_LONG keyid; /* key to use for this association */
};
@@ -516,6 +543,7 @@ struct conf_sys_flags {
*/
#define SYS_FLAG_BCLIENT 0x1
#define SYS_FLAG_AUTHENTICATE 0x2
+#define SYS_FLAG_MCLIENT 0x4
/*
* Structure used for returning restrict entries
@@ -546,6 +574,7 @@ struct conf_restrict {
struct info_monitor {
U_LONG lasttime; /* last packet from this host */
U_LONG firsttime; /* first time we received a packet */
+ U_LONG lastdrop; /* last time we rejected a packet due to client limitation policy */
U_LONG count; /* count of packets received */
U_LONG addr; /* host address */
u_short port; /* port number of last reception */
@@ -553,6 +582,18 @@ struct info_monitor {
u_char version; /* version number of last packet */
};
+/*
+ * Structure used for returning monitor data (old format
+ */
+struct old_info_monitor {
+ U_LONG lasttime; /* last packet from this host */
+ U_LONG firsttime; /* first time we received a packet */
+ U_LONG count; /* count of packets received */
+ U_LONG addr; /* host address */
+ u_short port; /* port number of last reception */
+ u_char mode; /* mode of last packet */
+ u_char version; /* version number of last packet */
+};
/*
* Structure used for passing indication of flags to clear
@@ -711,3 +752,29 @@ struct info_clkbug {
U_LONG values[NUMCBUGVALUES];
l_fp times[NUMCBUGTIMES];
};
+
+/*
+ * Structure used for returning kernel pll/PPS information
+ */
+struct info_kernel {
+ LONG offset;
+ LONG freq;
+ LONG maxerror;
+ LONG esterror;
+ u_short status;
+ u_short shift;
+ LONG constant;
+ LONG precision;
+ LONG tolerance;
+
+/*
+ * Variables used only if PPS signal discipline is implemented
+ */
+ LONG ppsfreq;
+ LONG jitter;
+ LONG stabil;
+ LONG jitcnt;
+ LONG calcnt;
+ LONG errcnt;
+ LONG stbcnt;
+};
diff --git a/contrib/xntpd/include/ntp_stdlib.h b/contrib/xntpd/include/ntp_stdlib.h
index 0ec062581616..f68c768d82d3 100644
--- a/contrib/xntpd/include/ntp_stdlib.h
+++ b/contrib/xntpd/include/ntp_stdlib.h
@@ -79,6 +79,7 @@ extern char * inttoa P((LONG));
extern char * mfptoa P((U_LONG, U_LONG, int));
extern char * mfptoms P((U_LONG, U_LONG, int));
extern char * modetoa P((int));
+extern U_LONG netof P((U_LONG));
extern char * numtoa P((U_LONG));
extern char * numtohost P((U_LONG));
extern int octtoint P((const char *, U_LONG *));
diff --git a/contrib/xntpd/include/ntp_timex.h b/contrib/xntpd/include/ntp_timex.h
index 1756e2e07f21..cb8396ac23fe 100644
--- a/contrib/xntpd/include/ntp_timex.h
+++ b/contrib/xntpd/include/ntp_timex.h
@@ -1,6 +1,6 @@
/******************************************************************************
* *
- * Copyright (c) David L. Mills 1993 *
+ * Copyright (c) David L. Mills 1993, 1994 *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation for any purpose and without fee is hereby granted, provided *
@@ -17,12 +17,18 @@
/*
* Modification history timex.h
*
+ * 19 Mar 94 David L. Mills
+ * Moved defines from kernel routines to header file and added new
+ * defines for PPS phase-lock loop.
+ *
+ * 20 Feb 94 David L. Mills
+ * Revised status codes and structures for external clock and PPS
+ * signal discipline.
+ *
* 28 Nov 93 David L. Mills
- * Adjusted parameters to improve stability and increase poll interval
+ * Adjusted parameters to improve stability and increase poll
+ * interval.
*
- * 10 Oct 93 Torsten Duwe
- * Changed to ntp_timex.h (#ifdef'd HAVE_SYS_TIMEX_H)
- *
* 17 Sep 93 David L. Mills
* Created file
*/
@@ -41,7 +47,7 @@
* int syscall(SYS_ntp_gettime, tptr)
*
* int SYS_ntp_gettime defined in syscall.h header file
- * struct ntptimeval *tptr pointer to ntptimeval structure
+ * struct ntptimeval *tptr pointer to ntptimeval structure
*
* NAME
* ntp_adjtime - NTP daemon application interface
@@ -55,104 +61,213 @@
* struct timex *tptr pointer to timex structure
*
*/
-#ifndef _NTP_TIMEX_H
-#define _NTP_TIMEX_H
+#ifndef MSDOS /* Microsoft specific */
+#include <sys/syscall.h>
+#endif /* MSDOS */
/*
- * Include system timex.h (if appropriate)
+ * The following defines establish the engineering parameters of the
+ * phase-lock loop (PLL) model used in the kernel implementation. These
+ * parameters have been carefully chosen by analysis for good stability
+ * and wide dynamic range.
+ *
+ * The hz variable is defined in the kernel build environment. It
+ * establishes the timer interrupt frequency, 100 Hz for the SunOS
+ * kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the OSF/1
+ * kernel. SHIFT_HZ expresses the same value as the nearest power of two
+ * in order to avoid hardware multiply operations.
+ *
+ * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen
+ * for a slightly underdamped convergence characteristic.
+ *
+ * MAXTC establishes the maximum time constant of the PLL. With the
+ * SHIFT_KG and SHIFT_KF values given and a time constant range from
+ * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
+ * respectively.
*/
-#ifdef HAVE_SYS_TIMEX_H
-#include <sys/timex.h>
-#else /* provide definitions */
-#include <sys/syscall.h>
-
-extern int syscall P((int, void *, ...));
+#define SHIFT_HZ 7 /* log2(hz) */
+#define SHIFT_KG 6 /* phase factor (shift) */
+#define SHIFT_KF 16 /* frequency factor (shift) */
+#define MAXTC 6 /* maximum time constant (shift) */
-#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
-#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
+/*
+ * The following defines establish the scaling of the various variables
+ * used by the PLL. They are chosen to allow the greatest precision
+ * possible without overflow of a 32-bit word.
+ *
+ * SHIFT_SCALE defines the scaling (shift) of the time_phase variable,
+ * which serves as a an extension to the low-order bits of the system
+ * clock variable time.tv_usec.
+ *
+ * SHIFT_UPDATE defines the scaling (shift) of the time_offset variable,
+ * which represents the current time offset with respect to standard
+ * time.
+ *
+ * SHIFT_USEC defines the scaling (shift) of the time_freq and
+ * time_tolerance variables, which represent the current frequency
+ * offset and maximum frequency tolerance.
+ *
+ * FINEUSEC is 1 us in SHIFT_UPDATE units of the time_phase variable.
+ */
+#define SHIFT_SCALE 23 /* phase scale (shift) */
+#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
+#define SHIFT_USEC 16 /* frequency offset scale (shift) */
+#define FINEUSEC (1L << SHIFT_SCALE) /* 1 us in phase units */
/*
- * The following defines establish the engineering parameters of the PLL
- * model. The HZ variable establishes the timer interrupt frequency, 100 Hz
- * for the SunOS kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the
- * OSF/1 kernel. The SHIFT_HZ define expresses the same value as the
- * nearest power of two in order to avoid hardware multiply operations.
+ * The following defines establish the performance envelope of the PLL.
+ * They insure it operates within predefined limits, in order to satisfy
+ * correctness assertions. An excursion which exceeds these bounds is
+ * clamped to the bound and operation proceeds accordingly. In practice,
+ * this can occur only if something has failed or is operating out of
+ * tolerance, but otherwise the PLL continues to operate in a stable
+ * mode.
+ *
+ * MAXPHASE must be set greater than or equal to CLOCK.MAX (128 ms), as
+ * defined in the NTP specification. CLOCK.MAX establishes the maximum
+ * time offset allowed before the system time is reset, rather than
+ * incrementally adjusted. Here, the maximum offset is clamped to
+ * MAXPHASE only in order to prevent overflow errors due to defective
+ * protocol implementations.
+ *
+ * MAXFREQ is the maximum frequency tolerance of the CPU clock
+ * oscillator plus the maximum slew rate allowed by the protocol. It
+ * should be set to at least the frequency tolerance of the oscillator
+ * plus 100 ppm for vernier frequency adjustments. If the kernel
+ * PPS discipline code is configured (PPS_SYNC), the oscillator time and
+ * frequency are disciplined to an external source, presumably with
+ * negligible time and frequency error relative to UTC, and MAXFREQ can
+ * be reduced.
+ *
+ * MAXTIME is the maximum jitter tolerance of the PPS signal if the
+ * kernel PPS discipline code is configured (PPS_SYNC).
+ *
+ * MINSEC and MAXSEC define the lower and upper bounds on the interval
+ * between protocol updates.
*/
-#define SHIFT_HZ 7 /* log2(HZ) */
+#define MAXPHASE 128000L /* max phase error (us) */
+#ifdef PPS_SYNC
+#define MAXFREQ (100L << SHIFT_USEC) /* max freq error (100 ppm) */
+#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */
+#else
+#define MAXFREQ (200L << SHIFT_USEC) /* max freq error (200 ppm) */
+#endif /* PPS_SYNC */
+#define MINSEC 16L /* min interval between updates (s) */
+#define MAXSEC 1200L /* max interval between updates (s) */
+#ifdef PPS_SYNC
/*
- * The SHIFT_KG and SHIFT_KF defines establish the damping of the PLL
- * and are chosen by analysis for a slightly underdamped convergence
- * characteristic. The MAXTC define establishes the maximum time constant
- * of the PLL. With the parameters given and the default time constant of
- * zero, the PLL will converge in about 15 minutes.
+ * The following defines are used only if a pulse-per-second (PPS)
+ * signal is available and connected via a modem control lead, such as
+ * produced by the optional ppsclock feature incorporated in the Sun
+ * asynch driver. They establish the design parameters of the frequency-
+ * lock loop used to discipline the CPU clock oscillator to the PPS
+ * signal.
+ *
+ * PPS_AVG is the averaging factor for the frequency loop, as well as
+ * the time and frequency dispersion.
+ *
+ * PPS_SHIFT and PPS_SHIFTMAX specify the minimum and maximum
+ * calibration intervals, respectively, in seconds as a power of two.
+ *
+ * PPS_VALID is the maximum interval before the PPS signal is considered
+ * invalid and protocol updates used directly instead.
+ *
+ * MAXGLITCH is the maximum interval before a time offset of more than
+ * MAXTIME is believed.
*/
-#define SHIFT_KG 6 /* shift for phase increment */
-#define SHIFT_KF 16 /* shift for frequency increment */
-#define MAXTC 6 /* maximum time constant (shift) */
+#define PPS_AVG 2 /* pps averaging constant (shift) */
+#define PPS_SHIFT 2 /* min interval duration (s) (shift) */
+#define PPS_SHIFTMAX 8 /* max interval duration (s) (shift) */
+#define PPS_VALID 120 /* pps signal watchdog max (s) */
+#define MAXGLITCH 30 /* pps signal glitch max (s) */
+#endif /* PPS_SYNC */
/*
- * The SHIFT_SCALE define establishes the decimal point of the time_phase
- * variable which serves as a an extension to the low-order bits of the
- * system clock variable. The SHIFT_UPDATE define establishes the decimal
- * point of the time_offset variable which represents the current offset
- * with respect to standard time. The SHIFT_USEC define represents 1 us in
- * external units (shift), while the FINEUSEC define represents 1 us in
- * internal units.
+ * The following defines and structures define the user interface for
+ * the ntp_gettime() and ntp_adjtime() system calls.
+ *
+ * Control mode codes (timex.modes)
*/
-#define SHIFT_SCALE 23 /* shift for phase scale factor */
-#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* shift for offset scale factor */
-#define SHIFT_USEC 16 /* shift for 1 us in external units */
-#define FINEUSEC (1 << SHIFT_SCALE) /* 1 us in internal units */
+#define MOD_OFFSET 0x0001 /* set time offset */
+#define MOD_FREQUENCY 0x0002 /* set frequency offset */
+#define MOD_MAXERROR 0x0004 /* set maximum time error */
+#define MOD_ESTERROR 0x0008 /* set estimated time error */
+#define MOD_STATUS 0x0010 /* set clock status bits */
+#define MOD_TIMECONST 0x0020 /* set pll time constant */
+#define MOD_CLKB 0x4000 /* set clock B */
+#define MOD_CLKA 0x8000 /* set clock A */
/*
- * Mode codes (timex.mode)
+ * Status codes (timex.status)
*/
-#define ADJ_OFFSET 0x0001 /* time offset */
-#define ADJ_FREQUENCY 0x0002 /* frequency offset */
-#define ADJ_MAXERROR 0x0004 /* maximum time error */
-#define ADJ_ESTERROR 0x0008 /* estimated time error */
-#define ADJ_STATUS 0x0010 /* clock status */
-#define ADJ_TIMECONST 0x0020 /* pll time constant */
+#define STA_PLL 0x0001 /* enable PLL updates (rw) */
+#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */
+#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */
+
+#define STA_INS 0x0010 /* insert leap (rw) */
+#define STA_DEL 0x0020 /* delete leap (rw) */
+#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */
+
+#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */
+#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */
+#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */
+#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
+
+#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
+
+#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \
+ STA_PPSERROR | STA_CLOCKERR) /* read-only bits */
/*
- * Clock command/status codes (timex.status)
+ * Clock states (time_state)
*/
-#define TIME_OK 0 /* clock synchronized */
-#define TIME_INS 1 /* insert leap second */
-#define TIME_DEL 2 /* delete leap second */
+#define TIME_OK 0 /* no leap second warning */
+#define TIME_INS 1 /* insert leap second warning */
+#define TIME_DEL 2 /* delete leap second warning */
#define TIME_OOP 3 /* leap second in progress */
-#define TIME_BAD 4 /* clock not synchronized */
+#define TIME_WAIT 4 /* leap second has occured */
+#define TIME_ERROR 5 /* clock not synchronized */
/*
- * NTP user interface - used to read kernel clock values
+ * NTP user interface (ntp_gettime()) - used to read kernel clock values
+ *
* Note: maximum error = NTP synch distance = dispersion + delay / 2;
* estimated error = NTP dispersion.
*/
struct ntptimeval {
- struct timeval time; /* current time */
- long maxerror; /* maximum error (usec) */
- long esterror; /* estimated error (usec) */
+ struct timeval time; /* current time (ro) */
+ LONG maxerror; /* maximum error (us) (ro) */
+ LONG esterror; /* estimated error (us) (ro) */
};
/*
- * NTP daemon interface - used to discipline kernel clock oscillator
+ * NTP daemon interface - (ntp_adjtime()) used to discipline CPU clock
+ * oscillator
*/
struct timex {
- int mode; /* mode selector */
- long offset; /* time offset (usec) */
- long frequency; /* frequency offset (scaled ppm) */
- long maxerror; /* maximum error (usec) */
- long esterror; /* estimated error (usec) */
- int status; /* clock command/status */
- long time_constant; /* pll time constant */
- long precision; /* clock precision (usec) (read only) */
- long tolerance; /* clock frequency tolerance (ppm)
- * (read only)
- */
-};
-
-#endif /* HAVE_SYS_TIMEX_H */
-
-#endif /* _NTP_TIMEX_H */
+ unsigned int modes; /* clock mode bits (wo) */
+ LONG offset; /* time offset (us) (rw) */
+ LONG freq; /* frequency offset (scaled ppm) (rw) */
+ LONG maxerror; /* maximum error (us) (rw) */
+ LONG esterror; /* estimated error (us) (rw) */
+ int status; /* clock status bits (rw) */
+ LONG constant; /* pll time constant (rw) */
+ LONG precision; /* clock precision (us) (ro) */
+ LONG tolerance; /* clock frequency tolerance (scaled
+ * ppm) (ro) */
+ /*
+ * The following read-only structure members are implemented
+ * only if the PPS signal discipline is configured in the
+ * kernel.
+ */
+ LONG ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ LONG jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ LONG stabil; /* pps stability (scaled ppm) (ro) */
+ LONG jitcnt; /* jitter limit exceeded (ro) */
+ LONG calcnt; /* calibration intervals (ro) */
+ LONG errcnt; /* calibration errors (ro) */
+ LONG stbcnt; /* stability limit exceeded (ro) */
+};
diff --git a/contrib/xntpd/include/ntpd.h b/contrib/xntpd/include/ntpd.h
index f2c56af20b90..037e8cb366f4 100644
--- a/contrib/xntpd/include/ntpd.h
+++ b/contrib/xntpd/include/ntpd.h
@@ -63,6 +63,9 @@ extern void input_handler P((l_fp *));
extern void io_clr_stats P((void));
extern void io_setbclient P((void));
extern void io_unsetbclient P((void));
+extern void io_multicast_add P((U_LONG));
+extern void io_multicast_del P((U_LONG));
+
extern void sendpkt P((struct sockaddr_in *, struct interface *, struct pkt *, int));
#ifdef HAVE_SIGNALED_IO
extern void wait_for_signal P((void));
@@ -93,8 +96,8 @@ extern int pps_sample P((l_fp *));
/* ntp_monitor.c */
extern void init_mon P((void));
-extern void mon_start P((void));
-extern void mon_stop P((void));
+extern void mon_start P((int));
+extern void mon_stop P((int));
extern void monitor P((struct recvbuf *));
/* ntp_peer.c */
@@ -102,10 +105,10 @@ extern void init_peer P((void));
extern struct peer *findexistingpeer P((struct sockaddr_in *, struct peer *));
extern struct peer *findpeer P((struct sockaddr_in *, struct interface *));
extern struct peer *findpeerbyassoc P((int));
-extern struct peer *newpeer P((struct sockaddr_in *, struct interface *, int, int, int, int, U_LONG));
+extern struct peer *newpeer P((struct sockaddr_in *, struct interface *, int, int, int, int, int, U_LONG));
extern void peer_all_reset P((void));
extern void peer_clr_stats P((void));
-extern struct peer *peer_config P((struct sockaddr_in *, struct interface *, int, int, int, int, U_LONG, int));
+extern struct peer *peer_config P((struct sockaddr_in *, struct interface *, int, int, int, int, int, int, U_LONG));
extern void peer_reset P((struct peer *));
extern int peer_unconfig P((struct sockaddr_in *, struct interface *));
extern void unpeer P((struct peer *));
@@ -131,7 +134,7 @@ extern void clock_select P((void));
extern void clock_combine P((struct peer **, int));
extern void fast_xmit P((struct recvbuf *, int, int));
extern void init_proto P((void));
-extern void proto_config P((int, LONG));
+extern void proto_config P((int, U_LONG));
extern void proto_clr_stats P((void));
#ifdef REFCLOCK
diff --git a/contrib/xntpd/include/parse.h b/contrib/xntpd/include/parse.h
index 31041afe292f..6ce3f192754a 100644
--- a/contrib/xntpd/include/parse.h
+++ b/contrib/xntpd/include/parse.h
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/include/parse.h,v 3.13 1994/01/25 19:04:21 kardel Exp
+ * /src/NTP/REPOSITORY/v3/include/parse.h,v 3.17 1994/03/03 09:27:20 kardel Exp
*
- * parse.h,v 3.13 1994/01/25 19:04:21 kardel Exp
+ * parse.h,v 3.17 1994/03/03 09:27:20 kardel Exp
*
* Copyright (c) 1989,1990,1991,1992,1993,1994
* Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
@@ -15,7 +15,7 @@
#ifndef __PARSE_H__
#define __PARSE_H__
#if !(defined(lint) || defined(__GNUC__))
- static char parsehrcsid[]="parse.h,v 3.13 1994/01/25 19:04:21 kardel Exp FAU";
+ static char parsehrcsid[]="parse.h,v 3.17 1994/03/03 09:27:20 kardel Exp";
#endif
#include "ntp_types.h"
@@ -81,35 +81,55 @@ extern int debug;
/*
* state flags
*/
-#define PARSEB_ANNOUNCE 0x0001 /* switch time zone warning (DST switch) */
-#define PARSEB_POWERUP 0x0002 /* no synchronisation */
-#define PARSEB_NOSYNC 0x0004 /* timecode currently not confirmed */
-#define PARSEB_DST 0x0008 /* DST in effect */
-#define PARSEB_UTC 0x0010 /* UTC time */
-#define PARSEB_LEAP 0x0020 /* LEAP warning (1 hour prior to occurence) */
-#define PARSEB_ALTERNATE 0x0040 /* alternate antenna used */
-#define PARSEB_POSITION 0x0080 /* position available */
-#define PARSEB_LEAPSECOND 0x0100 /* actual leap second */
-
-#define PARSEB_S_LEAP 0x0200 /* supports LEAP */
-#define PARSEB_S_ANTENNA 0x0400 /* supports antenna information */
-#define PARSEB_S_PPS 0x0800 /* supports PPS time stamping */
-#define PARSEB_S_POSITION 0x1000 /* supports position information (GPS) */
-
-#define PARSEB_TIMECODE 0x2000 /* valid time code sample */
-#define PARSEB_PPS 0x4000 /* valid PPS sample */
+#define PARSEB_POWERUP 0x00000001 /* no synchronisation */
+#define PARSEB_NOSYNC 0x00000002 /* timecode currently not confirmed */
+
+/*
+ * time zone information
+ */
+#define PARSEB_ANNOUNCE 0x00000010 /* switch time zone warning (DST switch) */
+#define PARSEB_DST 0x00000020 /* DST in effect */
+#define PARSEB_UTC 0x00000040 /* UTC time */
+
+/*
+ * leap information
+ */
+#define PARSEB_LEAPDEL 0x00000100 /* LEAP deletion warning */
+#define PARSEB_LEAPADD 0x00000200 /* LEAP addition warning */
+#define PARSEB_LEAPS 0x00000300 /* LEAP warnings */
+#define PARSEB_LEAPSECOND 0x00000400 /* actual leap second */
+/*
+ * optional status information
+ */
+#define PARSEB_ALTERNATE 0x00001000 /* alternate antenna used */
+#define PARSEB_POSITION 0x00002000 /* position available */
+
+/*
+ * feature information
+ */
+#define PARSEB_S_LEAP 0x00010000 /* supports LEAP */
+#define PARSEB_S_ANTENNA 0x00020000 /* supports antenna information */
+#define PARSEB_S_PPS 0x00040000 /* supports PPS time stamping */
+#define PARSEB_S_POSITION 0x00080000 /* supports position information (GPS) */
+
+/*
+ * time stamp availality
+ */
+#define PARSEB_TIMECODE 0x10000000 /* valid time code sample */
+#define PARSEB_PPS 0x20000000 /* valid PPS sample */
#define PARSE_TCINFO (PARSEB_ANNOUNCE|PARSEB_POWERUP|PARSEB_NOSYNC|PARSEB_DST|\
- PARSEB_UTC|PARSEB_LEAP|PARSEB_ALTERNATE|PARSEB_S_LEAP|\
+ PARSEB_UTC|PARSEB_LEAPS|PARSEB_ALTERNATE|PARSEB_S_LEAP|\
PARSEB_S_LOCATION|PARSEB_TIMECODE)
-#define PARSE_POWERUP(x) ((x) & PARSEB_POWERUP)
-#define PARSE_NOSYNC(x) (((x) & (PARSEB_POWERUP|PARSEB_NOSYNC)) == PARSEB_NOSYNC)
-#define PARSE_SYNC(x) (((x) & (PARSEB_POWERUP|PARSEB_NOSYNC)) == 0)
-#define PARSE_ANNOUNCE(x) ((x) & PARSEB_ANNOUNCE)
-#define PARSE_DST(x) ((x) & PARSEB_DST)
+#define PARSE_POWERUP(x) ((x) & PARSEB_POWERUP)
+#define PARSE_NOSYNC(x) (((x) & (PARSEB_POWERUP|PARSEB_NOSYNC)) == PARSEB_NOSYNC)
+#define PARSE_SYNC(x) (((x) & (PARSEB_POWERUP|PARSEB_NOSYNC)) == 0)
+#define PARSE_ANNOUNCE(x) ((x) & PARSEB_ANNOUNCE)
+#define PARSE_DST(x) ((x) & PARSEB_DST)
#define PARSE_UTC(x) ((x) & PARSEB_UTC)
-#define PARSE_LEAP(x) (PARSE_SYNC(x) && ((x) & PARSEB_LEAP))
+#define PARSE_LEAPADD(x) (PARSE_SYNC(x) && (((x) & PARSEB_LEAPS) == PARSEB_LEAPADD))
+#define PARSE_LEAPDEL(x) (PARSE_SYNC(x) && (((x) & PARSEB_LEAPS) == PARSEB_LEAPDEL))
#define PARSE_ALTERNATE(x) ((x) & PARSEB_ALTERNATE)
#define PARSE_LEAPSECOND(x) (PARSE_SYNC(x) && ((x) & PARSEB_LEAP_SECOND))
@@ -118,9 +138,9 @@ extern int debug;
#define PARSE_S_PPS(x) ((x) & PARSEB_S_PPS)
#define PARSE_S_POSITION(x) ((x) & PARSEB_S_POSITION)
-#define PARSE_TIMECODE(x) ((x) & PARSEB_TIMECODE)
+#define PARSE_TIMECODE(x) ((x) & PARSEB_TIMECODE)
#define PARSE_PPS(x) ((x) & PARSEB_PPS)
-#define PARSE_POSITION(x) ((x) & PARSEB_POSITION)
+#define PARSE_POSITION(x) ((x) & PARSEB_POSITION)
/*
* operation flags - some are also fudge flags
@@ -281,6 +301,7 @@ struct clocktime /* clock time broken up from time code */
LONG second;
LONG usecond;
LONG utcoffset; /* in seconds */
+ time_t utctime; /* the actual time - alternative to date/time */
LONG flags; /* current clock status */
};
@@ -365,6 +386,9 @@ extern unsigned LONG pps_simple P((parse_t *, int status, timestamp_t *));
* History:
*
* parse.h,v
+ * Revision 3.17 1994/03/03 09:27:20 kardel
+ * rcs ids fixed
+ *
* Revision 3.13 1994/01/25 19:04:21 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/kernel/.keep_me b/contrib/xntpd/kernel/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/kernel/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/lib/Makefile b/contrib/xntpd/lib/Makefile
index dcb4f091f82c..b6c00416c159 100644
--- a/contrib/xntpd/lib/Makefile
+++ b/contrib/xntpd/lib/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.4 1993/12/22 11:32:23 rgrimes Exp $
+# $Id: Makefile,v 1.5 1994/04/03 20:37:05 wollman Exp $
#
CFLAGS+= -I${.CURDIR}/../include
@@ -10,7 +10,7 @@ SRCS= atoint.c atolfp.c atouint.c auth12crypt.c authdecrypt.c authdes.c \
clocktime.c dofptoa.c dolfptoa.c emalloc.c fptoa.c fptoms.c \
gettstamp.c hextoint.c hextolfp.c humandate.c inttoa.c \
lib_strbuf.c mfptoa.c mfptoms.c modetoa.c mstolfp.c \
- msutotsf.c numtoa.c refnumtoa.c numtohost.c octtoint.c \
+ msutotsf.c netof.c numtoa.c refnumtoa.c numtohost.c octtoint.c \
prettydate.c ranny.c tsftomsu.c tstotv.c tvtoa.c tvtots.c \
uglydate.c uinttoa.c utvtoa.c clocktypes.c \
md5.c a_md5encrypt.c a_md5decrypt.c \
diff --git a/contrib/xntpd/lib/clocktypes.c b/contrib/xntpd/lib/clocktypes.c
index 2701e3f1d0ef..816ef0708b3e 100644
--- a/contrib/xntpd/lib/clocktypes.c
+++ b/contrib/xntpd/lib/clocktypes.c
@@ -11,7 +11,7 @@
struct clktype clktypes[] = {
{ REFCLK_NONE, "unspecified type (0)", "UNKNOWN" },
{ REFCLK_LOCALCLOCK, "local clock synchronization (1)", "LOCAL" },
- { REFCLK_WWV_HEATH, "Heathkit WWV clock (2)", "WWV_HEATH" },
+ { REFCLK_GPS_TRAK, "TRAK 8810 GPS Receiver (2)", "GPS_TRAK" },
{ REFCLK_WWV_PST, "Precision Standard Time WWV clock (3)", "WWV_PST" },
{ REFCLK_WWVB_SPECTRACOM, "Spectracom WWVB clock (4)", "WWVB_SPEC" },
{ REFCLK_GOES_TRUETIME, "True Time GPS/GOES clock (5)", "GPS_GOES_TRUE" },
diff --git a/contrib/xntpd/lib/netof.c b/contrib/xntpd/lib/netof.c
new file mode 100644
index 000000000000..286a5846eb40
--- /dev/null
+++ b/contrib/xntpd/lib/netof.c
@@ -0,0 +1,25 @@
+/*
+ * netof - return the net address part of an ip address
+ * (zero out host part)
+ */
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "ntp_stdlib.h"
+
+U_LONG
+netof(num)
+ U_LONG num;
+{
+ register U_LONG netnum;
+
+ netnum = num;
+
+ if(IN_CLASSC(netnum))
+ netnum &= IN_CLASSC_NET;
+ else if (IN_CLASSB(netnum))
+ netnum &= IN_CLASSB_NET;
+ else /* treat als other like class A */
+ netnum &= IN_CLASSA_NET;
+ return netnum;
+}
diff --git a/contrib/xntpd/lib/numtohost.c b/contrib/xntpd/lib/numtohost.c
index e22b6231790a..2f07c2c4dac5 100644
--- a/contrib/xntpd/lib/numtohost.c
+++ b/contrib/xntpd/lib/numtohost.c
@@ -1,12 +1,11 @@
-/* numtohost.c,v 3.1 1993/07/06 01:08:40 jbj Exp
+/*
* numtohost - convert network number to host name.
*/
-#include "ntp_types.h"
#include <netdb.h>
#include "ntp_fp.h"
-#include "lib_strbuf.h"
#include "ntp_stdlib.h"
+#include "lib_strbuf.h"
#define LOOPBACKNET 0x7f000000
#define LOOPBACKHOST 0x7f000001
diff --git a/contrib/xntpd/lib/systime.c b/contrib/xntpd/lib/systime.c
index ea15734f1abb..1d6c59a5d969 100644
--- a/contrib/xntpd/lib/systime.c
+++ b/contrib/xntpd/lib/systime.c
@@ -47,12 +47,13 @@ extern int debug;
* We also remember the clock precision we computed from the kernel in
* case someone asks us.
*/
+ LONG sys_clock;
+
LONG adj_precision; /* adj precision in usec (tickadj) */
LONG tvu_maxslew; /* maximum adjust doable in 1<<CLOCK_ADJ sec (usec) */
U_LONG tsf_maxslew; /* same as above, as LONG format */
- LONG sys_clock;
l_fp sys_clock_offset; /* correction for current system time */
/*
diff --git a/contrib/xntpd/machines/.keep_me b/contrib/xntpd/machines/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/machines/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ntpdate/ntpdate.h b/contrib/xntpd/ntpdate/ntpdate.h
index 4a8ff746e772..f6d3ebf877f3 100644
--- a/contrib/xntpd/ntpdate/ntpdate.h
+++ b/contrib/xntpd/ntpdate/ntpdate.h
@@ -54,7 +54,11 @@ struct server {
* are close, or step the time if the times are farther apart. The
* following defines what is "close".
*/
+#ifdef linux
+#define NTPDATE_THRESHOLD (FP_SECOND / 8) /* 1/8 second */
+#else
#define NTPDATE_THRESHOLD (FP_SECOND >> 1) /* 1/2 second */
+#endif
/*
* When doing adjustments, ntpdate actually overadjusts (currently
diff --git a/contrib/xntpd/ntpq/ntpq.c b/contrib/xntpd/ntpq/ntpq.c
index 5cfc3daff820..73c2a351aa70 100644
--- a/contrib/xntpd/ntpq/ntpq.c
+++ b/contrib/xntpd/ntpq/ntpq.c
@@ -75,6 +75,7 @@ int jump = 0;
#define OC 12 /* integer, print in octal */
#define MD 13 /* mode */
#define AR 14 /* array of times */
+#define TST 15 /* test flags */
#define EOV 255 /* end of table */
@@ -145,7 +146,7 @@ struct ctl_var peer_var[] = {
{ CP_RECEIVED, UI, "received" }, /* 31 */
{ CP_SENT, UI, "sent" }, /* 32 */
{ CP_FILTERROR, AR, "filterror" }, /* 33 */
- { CP_FLASH, ST, "flash"}, /* 34 */
+ { CP_FLASH, TST, "flash"}, /* 34 */
{ CP_DISP, AR, "disp" }, /* 35 */
/*
* These are duplicate entires so that we can
@@ -189,6 +190,20 @@ struct codestring {
};
/*
+ * flasher bits
+ */
+static char *tstflagnames[] = {
+ "DUPLICATE PKT",
+ "BOGUS PKT",
+ "PROTO UNSYNC",
+ "PEER BOUNDS",
+ "BAD AUTH",
+ "PEER CLOCK UNSYNC",
+ "BAD STRATUM",
+ "ROOT BOUNDS"
+};
+
+/*
* Leap values
*/
struct codestring leap_codes[] = {
@@ -301,7 +316,7 @@ static int decodereach P((char *, U_LONG *));
static int decodearr P((char *, int *, l_fp *));
static char * getcode P((int, struct codestring *));
static void help P((struct parse *, FILE *));
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
static int helpsort P((const void *, const void *));
#else
static int helpsort P((char **, char **));
@@ -335,7 +350,7 @@ static void output P((FILE *, char *, char *));
static void endoutput P((FILE *));
static void outputarr P((FILE *, char *, int, l_fp *));
static void cookedprint P((int, int, char *, int, FILE *));
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
static int assoccmp P((const void *, const void *));
#else
static int assoccmp P((struct association *, struct association *));
@@ -1888,7 +1903,7 @@ help(pcmd, fp)
for (xcp = opcmds; xcp->keyword != 0; xcp++)
cmdsort[n++] = xcp->keyword;
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
qsort((void *)cmdsort, n, sizeof(char *), helpsort);
#else
qsort((char *)cmdsort, n, sizeof(char *), helpsort);
@@ -1934,7 +1949,7 @@ help(pcmd, fp)
* helpsort - do hostname qsort comparisons
*/
static int
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
helpsort(t1, t2)
const void *t1;
const void *t2;
@@ -2836,7 +2851,45 @@ outputarr(fp, name, narr, lfp)
output(fp, name, buf);
}
-
+static char *
+tstflags(val)
+ U_LONG val;
+{
+ register char *cb, *s;
+ register int i;
+ register char *sep;
+
+ sep = "";
+ i = 0;
+ s = cb = &circ_buf[nextcb][0];
+ if (++nextcb >= NUMCB)
+ nextcb = 0;
+
+ sprintf(cb, "0x%x", val);
+ cb += strlen(cb);
+ if (val <= ((1<<8)-1)) {
+ if (!val) {
+ strcat(cb, "<OK>");
+ cb += strlen(cb);
+ } else {
+ *cb++ = '<';
+ while (val) {
+ if (val & 0x1) {
+ sprintf(cb, "%s%s", sep, tstflagnames[i]);
+ sep = ";";
+ cb += strlen(cb);
+ }
+ i++;
+ val >>= 1;
+ }
+ *cb++ = '>';
+ }
+ } else {
+ *cb++ = '?';
+ }
+ *cb = '\0';
+ return s;
+}
/*
* cookedprint - output variables in cooked mode
@@ -2994,6 +3047,13 @@ cookedprint(datatype, length, data, status, fp)
outputarr(fp, name, narr, lfparr);
break;
+ case TST:
+ if (!decodeuint(value, &uval))
+ output_raw = '?';
+ else
+ output(fp, name, tstflags(uval));
+ break;
+
default:
(void) fprintf(stderr,
"Internal error in cookedprint, %s=%s, fmt %d\n",
@@ -3028,7 +3088,7 @@ void
sortassoc()
{
if (numassoc > 1)
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
qsort((void *)assoc_cache, numassoc,
sizeof(struct association), assoccmp);
#else
@@ -3042,7 +3102,7 @@ sortassoc()
* assoccmp - compare two associations
*/
static int
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
assoccmp(t1, t2)
const void *t1;
const void *t2;
diff --git a/contrib/xntpd/parse/README.new_clocks b/contrib/xntpd/parse/README.new_clocks
new file mode 100644
index 000000000000..8fdd7cbd4250
--- /dev/null
+++ b/contrib/xntpd/parse/README.new_clocks
@@ -0,0 +1,212 @@
+Here is an attempt to sketch out what you need to do in order to
+add another clock to the parse driver:
+
+Prerequisites:
+- Does the system you want the clock connect to have
+ termio.h or termios.h ? (You need that for the parse driver)
+
+What to do:
+
+Make a conversion module (parse/clk_*.c)
+
+- What ist the time code format ?
+ - find year, month, day, hour, minute, second, status (synchronised or
+ not), possibly time zone information (you need to give the offset to UTC)
+ You will have to convert the data from a string into a struct clocktime:
+ struct clocktime /* clock time broken up from time code */
+ {
+ LONG day;
+ LONG month;
+ LONG year;
+ LONG hour;
+ LONG minute;
+ LONG second;
+ LONG usecond;
+ LONG utcoffset; /* in seconds */
+ time_t utcoffset; /* true utc time instead of date/time */
+ LONG flags; /* current clock status */
+ };
+
+ Conversion is usually simple and straight forward. For the flags following
+ values can be OR'ed together:
+
+ PARSEB_ANNOUNCE switch time zone warning (informational only)
+ PARSEB_POWERUP no synchronisation - clock confused (must set then)
+ PARSEB_NOSYNC timecode currently not confirmed (must set then)
+ usually on reception error when there is still a
+ chance the the generated time is still ok.
+
+ PARSEB_DST DST in effect (informational only)
+ PARSEB_UTC timecode contains UTC time (informational only)
+ PARSEB_LEAPADD LEAP addition warning (prior to leap happening - must set when imminent)
+ also used for time code that do not encode the
+ direction (as this is currently the default).
+ PARSEB_LEAPDEL LEAP deletion warning (prior to leap happening - must set when imminent)
+ PARSEB_ALTERNATE backup transmitter (informational only)
+ PARSEB_POSITION geographic position available (informational only)
+ PARSEB_LEAPSECOND actual leap second (this time code is the leap
+ second - informational only)
+
+ These are feature flags denoting items that are supported by the clock:
+ PARSEB_S_LEAP supports LEAP - might set PARSEB_LEAP
+ PARSEB_S_ANTENNA supports ANTENNA - might set PARSEB_ALTERNATE
+ PARSEB_S_PPS supports PPS time stamping
+ PARSEB_S_POSITION supports position information (GPS)
+
+ If the utctime field is non zero this value will be take as
+ time code value. This allows for conversion routines that
+ already have the utc time value. The utctime field gives the seconds
+ since Jan 1st 1970, 0:00:00. The useconds field gives the respective
+ usec value. The fields for date and time (down to second resolution)
+ will be ignored.
+
+ Conversion is done in the cvt_* routine in parse/clk_*.c files. look in
+ them for examples. The basic structure is:
+
+ struct clockformat <yourclock>_format = {
+ lots of fields for you to fill out (see below)
+ };
+
+ static cvt_<yourclock>()
+ ...
+ {
+ if (<I do not recognize my time code>) {
+ return CVT_NONE;
+ } else {
+ if (<conversion into clockformat is ok>) {
+ <set all necessary flags>;
+ return CVT_OK;
+ } else {
+ return CVT_FAIL|CVT_BADFMT;
+ }
+ }
+
+ The struct clockformat is the interface to the rest of the parse
+ driver - it holds all information necessary for finding the
+ clock message and doing the appropriate time stamping.
+
+struct clockformat
+{
+ unsigned LONG (*convert)();
+ /* conversion routine - your routine - cvt_<yourclock> */
+ void (*syncevt)();
+ /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
+ unsigned LONG (*syncpps)();
+ /* PPS input routine - usually pps_simple */
+ unsigned LONG (*synth)();
+ /* time code synthesizer - usually not used - (LONG (*)())0 */
+ void *data;
+ /* local parameters - any parameters/data/configuration info your conversion
+ routine might need */
+ char *name;
+ /* clock format name - Name of the time code */
+ unsigned short length;
+ /* maximum length of data packet for your clock format */
+ unsigned LONG flags;
+ /* information for the parser what to look for */
+ struct timeval timeout;
+ /* buffer restart after timeout (us) - some clocks preceede new data by
+ a longer period of silence - unsually not used */
+ unsigned char startsym;
+ /* start symbol - character at the beginning of the clock data */
+ unsigned char endsym;
+ /* end symbol - character at the end of the clock data */
+ unsigned char syncsym;
+ /* sync symbol - character that is "on time" - where the time stamp should be taken */
+};
+
+ The flags:
+ F_START use startsym to find the beginning of the clock data
+ F_END use endsym to find the end of the clock data
+ SYNC_TIMEOUT packet restart after timeout in timeout field
+ SYNC_START packet start is sync event (time stamp at paket start)
+ SYNC_END packet end is sync event (time stamp at paket end)
+ SYNC_CHAR special character (syncsym) is sync event
+ SYNC_ONE PPS synchronize on 'ONE' transition
+ SYNC_ZERO PPS synchronize on 'ZERO' transition
+ SYNC_SYNTHESIZE generate intermediate time stamps (very special case!)
+ CVT_FIXEDONLY convert only in fixed configuration - (data format not
+ suitable for auto-configuration)
+
+
+ The above should have given you some hints on how to build a clk_*.c
+ file with the time code conversion. See the examples and pick a clock
+ closest to yours and tweak the code to match your clock.
+
+ In order to make your clk_*.c file usable a reference to the clockformat
+ structure must be put into parse_conf.c.
+
+TTY setup and initialisation/configuration will be done in
+xntpd/refclock_parse.c
+
+- Find out the exact tty settings for your clock (baud rate, parity,
+ stop bits, character size, ...) and note them in terms of
+ termio*.h c_cflag macros.
+
+- in xntpd/refclock_parse.c fill out a new the struct clockinfo element
+ (that allocates a new "IP" address - see comments)
+ (see all the other clocks for example)
+ struct clockinfo
+ {
+ U_LONG cl_flags; /* operation flags (io modes) */
+ PARSE_F_NOPOLLONLY always do async io - read whenever input comes
+ PARSE_F_POLLONLY never do async io - only read when expecting data
+ PARSE_F_PPSPPS use loopfilter PPS code (CIOGETEV)
+ PARSE_F_PPSONSECOND PPS pulses are on second
+ usually flags stay 0 as they are used only for special setups
+
+ void (*cl_poll)(); /* active poll routine */
+ The routine to call when the clock needs data sent to it in order to
+ get a time code from the clock (e.g. Trimble clock)
+ int (*cl_init)(); /* active poll init routine */
+ The routine to call for very special initializations.
+ void (*cl_end)(); /* active poll end routine */
+ The routine to call to undo any special initialisation (free memory/timers)
+ void *cl_data; /* local data area for "poll" mechanism */
+ local data for polling routines
+ u_fp cl_rootdelay; /* rootdelay */
+ NTP rottdelay estimate (usually 0)
+ U_LONG cl_basedelay; /* current offset - unsigned l_fp fractional par
+ time (fraction) by which the RS232 time code is delayed from the actual time.
+ t */
+ U_LONG cl_ppsdelay; /* current PPS offset - unsigned l_fp fractional
+ time (fraction) by which the PPS time stamp is delayed (usually 0)
+ part */
+ char *cl_id; /* ID code (usually "DCF") */
+ Refclock id - (max 4 chars)
+ char *cl_description; /* device name */
+ Name of this device.
+ char *cl_format; /* fixed format */
+ If the data format cann not ne detected automatically this is the name
+ as in clk_*.c clockformat.
+ u_char cl_type; /* clock type (ntp control) */
+ Type if clock as in clock status word (ntp control messages) - usually 0
+ U_LONG cl_maxunsync; /* time to trust oscillator after loosing synch
+ */
+ seconds a clock can be trusted after loosing synchronisation.
+
+ U_LONG cl_cflag; /* terminal io flags */
+ U_LONG cl_iflag; /* terminal io flags */
+ U_LONG cl_oflag; /* terminal io flags */
+ U_LONG cl_lflag; /* terminal io flags */
+ termio*.h tty modes.
+ } clockinfo[] = {
+ ...,<other clocks>,...
+ { < your parameters> },
+ };
+
+
+Well, this is very sketchy, i know. But I hope it helps a little bit.
+The best way is to look which clock comes closest to your and tweak that
+code.
+Two sorts of clocks are used with parse. Clocks that automatically send
+their time code (once a second) do not need entries in the poll routines because
+they send the data all the time. The second sort are the clocks that need a
+command sent to them in order to reply with a time code (like the Trimble
+clock).
+
+For questions: kardel@informatik.uni-erlangen.de. Please include
+an exact description on how your clock works. (initialisation,
+TTY modes, strings to be sent to it, responses received from the clock).
+
+Frank Kardel
diff --git a/contrib/xntpd/parse/README.parse_clocks b/contrib/xntpd/parse/README.parse_clocks
new file mode 100644
index 000000000000..cf8d77eb76bb
--- /dev/null
+++ b/contrib/xntpd/parse/README.parse_clocks
@@ -0,0 +1,263 @@
+The parse driver currently supports several clocks with different
+query mechanisms. In order for you to find a sample that might be
+similar to a clock you might want to integrate into parse i'll sum
+up the major features of the clocks (this information is distributed
+in the parse/clk_*.c and xntpd/refclock_parse.c files).
+
+---
+ Meinberg: 127.127.8. 0- 3 (PZF535TCXO)
+ 127.127.8. 4- 7 (PZF535OCXO)
+ 127.127.8. 8-11 (DCFUA31)
+ 127.127.8.28-31 (GPS166)
+ Meinberg: start=<STX>, end=<ETX>, sync on start
+ pattern="\2D: . . ;T: ;U: . . ; \3"
+ pattern="\2 . . ; ; : : ; \3"
+ pattern="\2 . . ; ; : : ; : ; ; . . "
+
+ Meinberg is a german manufacturer of time code receivers. Those clocks
+ have a pretty common output format in the stock version. In order to
+ support NTP Meinberg was so kind to produce some special versions of
+ the firmware for the use with NTP. So, if you are going to use a
+ Meinberg clock please ask whether there is a special Uni Erlangen
+ version.
+
+ General characteristics:
+ Meinberg clocks primarily output pulse per second and a describing
+ ASCII string. This string can be produced in two modes. either upon
+ the reception of a question mark or every second. NTP uses the latter
+ mechanism. The DCF77 variants have a pretty good relationship between
+ RS232 time code and the PPS signal while the GPS receiver has no fixed
+ timeing between the datagram and the pulse (you need to use PPS with
+ GPS!) on DCF77 you might get away without the PPS signal.
+
+ The preferred tty setting for Meinberg is:
+ CFLAG (B9600|CS7|PARENB|CREAD|HUPCL)
+ IFLAG (IGNBRK|IGNPAR|ISTRIP)
+ OFLAG 0
+ LFLAG 0
+
+ The clock is run at datagram once per second.
+ Stock dataformat is:
+
+ <STX>D:<dd>.<mm>.<yy>;T:<w>;U:<hh>:<mm>:<ss>;<S><F><D><A><ETX>
+ pos: 0 00 00 0 00 0 11 111 1 111 12 2 22 2 22 2 2 2 3 3 3
+ 1 23 45 6 78 9 01 234 5 678 90 1 23 4 56 7 8 9 0 1 2
+
+ <STX> = '\002' ASCII start of text
+ <ETX> = '\003' ASCII end of text
+ <dd>,<mm>,<yy> = day, month, year(2 digits!!)
+ <w> = day of week (sunday= 0)
+ <hh>,<mm>,<ss> = hour, minute, second
+ <S> = '#' if never synced since powerup else ' ' for DCF U/A 31
+ '#' if not PZF sychronisation available else ' ' for PZF 535
+ <F> = '*' if time comes from internal quartz else ' '
+ <D> = 'S' if daylight saving time is active else ' '
+ <A> = '!' during the hour preceeding an daylight saving time
+ start/end change
+
+ For the university of Erlangen a special format was implemented to support
+ LEAP announcement and anouncement of alternate antenna.
+
+ Version for UNI-ERLANGEN Software is: PZFUERL V4.6 (Meinberg)
+
+ The use of this software release (or higher) is *ABSOLUTELY*
+ recommended (ask for PZFUERL version as some minor HW fixes have
+ been introduced) due to the LEAP second support and UTC indication.
+ The standard timecode does not indicate when the timecode is in
+ UTC (by front panel configuration) thus we have no chance to find
+ the correct utc offset. For the standard format do not ever use
+ UTC display as this is not detectable in the time code !!!
+
+ <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <U><S><F><D><A><L><R><ETX>
+ pos: 0 00 0 00 0 00 11 1 11 11 1 11 2 22 22 2 2 2 2 2 3 3 3
+ 1 23 4 56 7 89 01 2 34 56 7 89 0 12 34 5 6 7 8 9 0 1 2
+ <STX> = '\002' ASCII start of text
+ <ETX> = '\003' ASCII end of text
+ <dd>,<mm>,<yy> = day, month, year(2 digits!!)
+ <w> = day of week (sunday= 0)
+ <hh>,<mm>,<ss> = hour, minute, second
+ <U> = 'U' UTC time display
+ <S> = '#' if never synced since powerup else ' ' for DCF U/A 31
+ '#' if not PZF sychronisation available else ' ' for PZF 535
+ <F> = '*' if time comes from internal quartz else ' '
+ <D> = 'S' if daylight saving time is active else ' '
+ <A> = '!' during the hour preceeding an daylight saving time
+ start/end change
+ <L> = 'A' LEAP second announcement
+ <R> = 'R' alternate antenna
+
+ Meinberg GPS166 receiver
+
+ You must get the Uni-Erlangen firmware for the GPS receiver support
+ to work to full satisfaction !
+
+ <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <+/-><00:00>; <U><S><F><D><A><L><R><L>; <position...><ETX>
+ *
+ 000000000111111111122222222223333333333444444444455555555556666666
+ 123456789012345678901234567890123456789012345678901234567890123456
+ \x0209.07.93; 5; 08:48:26; +00:00; ; 49.5736N 11.0280E 373m\x03
+ *
+
+ <STX> = '\002' ASCII start of text
+ <ETX> = '\003' ASCII end of text
+ <dd>,<mm>,<yy> = day, month, year(2 digits!!)
+ <w> = day of week (sunday= 0)
+ <hh>,<mm>,<ss> = hour, minute, second
+ <+/->,<00:00> = offset to UTC
+ <S> = '#' if never synced since powerup else ' ' for DCF U/A 31
+ '#' if not PZF sychronisation available else ' ' for PZF 535
+ <U> = 'U' UTC time display
+ <F> = '*' if time comes from internal quartz else ' '
+ <D> = 'S' if daylight saving time is active else ' '
+ <A> = '!' during the hour preceeding an daylight saving time
+ start/end change
+ <L> = 'A' LEAP second announcement
+ <R> = 'R' alternate antenna (reminiscent of PZF535) usually ' '
+ <L> = 'L' on 23:59:60
+
+
+ For the Meinberg parse look into clock_meinberg.c
+
+---
+ RAWDCF: 127.127.8.20-23 (Conrad receiver module - delay 210ms)
+ 127.127.8.24-27 (FAU receiver - delay 258ms)
+ RAWDCF: end=TIMEOUT>1.5s, sync each char (any char),generate psuedo time
+ codes, fixed format
+
+ direct DCF77 code input
+ In Europe it is relatively easy/cheap the receive the german time code
+ transmitter DCF77. The simplest version to process its signal is to
+ feed the 100/200ms pulse of the demodulated AM signal via a level
+ converter to an RS232 port at 50Baud. parse/clk_rawdcf.c holds all
+ necessary decoding logic for the time code which is transmitted each
+ minute for one minute. A bit of the time code is sent once a second.
+
+ The preferred tty setting is:
+ CFLAG (B50|CS8|CREAD|CLOCAL)
+ IFLAG 0
+ OFLAG 0
+ LFLAG 0
+
+ DCF77 raw time code
+
+ From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig
+ und Berlin, Maerz 1989
+
+ Timecode transmission:
+ AM:
+ time marks are send every second except for the second before the
+ next minute mark
+ time marks consist of a reduction of transmitter power to 25%
+ of the nominal level
+ the falling edge is the time indication (on time)
+ time marks of a 100ms duration constitute a logical 0
+ time marks of a 200ms duration constitute a logical 1
+ FM:
+ see the spec. (basically a (non-)inverted psuedo random phase shift)
+
+ Encoding:
+ Second Contents
+ 0 - 10 AM: free, FM: 0
+ 11 - 14 free
+ 15 R - alternate antenna
+ 16 A1 - expect zone change (1 hour before)
+ 17 - 18 Z1,Z2 - time zone
+ 0 0 illegal
+ 0 1 MEZ (MET)
+ 1 0 MESZ (MED, MET DST)
+ 1 1 illegal
+ 19 A2 - expect leap insertion/deletion (1 hour before)
+ 20 S - start of time code (1)
+ 21 - 24 M1 - BCD (lsb first) Minutes
+ 25 - 27 M10 - BCD (lsb first) 10 Minutes
+ 28 P1 - Minute Parity (even)
+ 29 - 32 H1 - BCD (lsb first) Hours
+ 33 - 34 H10 - BCD (lsb first) 10 Hours
+ 35 P2 - Hour Parity (even)
+ 36 - 39 D1 - BCD (lsb first) Days
+ 40 - 41 D10 - BCD (lsb first) 10 Days
+ 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday)
+ 45 - 49 MO - BCD (lsb first) Month
+ 50 MO0 - 10 Months
+ 51 - 53 Y1 - BCD (lsb first) Years
+ 54 - 57 Y10 - BCD (lsb first) 10 Years
+ 58 P3 - Date Parity (even)
+ 59 - usually missing (minute indication), except for leap insertion
+
+---
+ Schmid clock: 127.127.8.16-19
+ Schmid clock: needs poll, binary input, end='\xFC', sync start
+
+ The Schmid clock is a DCF77 receiver that sends a binary
+ time code at the reception of a flag byte. The contents
+ if the flag byte determined the time code format. The
+ binary time code is delimited by the byte 0xFC.
+
+ TTY setup is:
+ CFLAG (B1200|CS8|CREAD|CLOCAL)
+ IFLAG 0
+ OFLAG 0
+ LFLAG 0
+
+ The command to Schmid's DCF77 clock is a single byte; each bit
+ allows the user to select some part of the time string, as follows (the
+ output for the lsb is sent first).
+
+ Bit 0: time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths
+ Bit 1: date 3 bytes *binary, not BCD: dd.mm.yy
+ Bit 2: week day, 1 byte (unused here)
+ Bit 3: time zone, 1 byte, 0=MET, 1=MEST. (unused here)
+ Bit 4: clock status, 1 byte, 0=time invalid,
+ 1=time from crystal backup,
+ 3=time from DCF77
+ Bit 5: transmitter status, 1 byte,
+ bit 0: backup antenna
+ bit 1: time zone change within 1h
+ bit 3,2: TZ 01=MEST, 10=MET
+ bit 4: leap second will be
+ added within one hour
+ bits 5-7: Zero
+ Bit 6: time in backup mode, units of 5 minutes (unused here)
+
+
+---
+ Trimble SV6: 127.127.8.32-35
+ Trimble SV6: needs poll, ascii timecode, start='>', end='<',
+ query='>QTM<', eol='<'
+
+ Trimble SV6 is a GPS receiver with PPS output. It needs to be polled.
+ It also need a special tty mode setup (EOL='<').
+
+ TTY setup is:
+ CFLAG (B4800|CS8|CREAD)
+ IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
+ OFLAG (OPOST|ONLCR)
+ LFLAG (ICANON|ECHOK)
+
+ Special flags are:
+ PARSE_F_PPSPPS - use CIOGETEV for PPS time stamping
+ PARSE_F_PPSONSECOND - the time code is not related to
+ the PPS pulse (so use the time code
+ only for the second epoch)
+
+ Timecode
+ 0000000000111111111122222222223333333 / char
+ 0123456789012345678901234567890123456 \ posn
+ >RTMhhmmssdddDDMMYYYYoodnnvrrrrr;*xx< Actual
+ ----33445566600112222BB7__-_____--99- Parse
+ >RTM 1 ;* <", Check
+
+---
+ ELV DCF7000: 127.127.8.12-15
+ ELV DCF7000: end='\r', pattern=" - - - - - - - \r"
+
+ The ELV DCF7000 is a cheap DCF77 receiver sending each second
+ a time code (though not very precise!) delimited by '`r'
+
+ Timecode
+ YY-MM-DD-HH-MM-SS-FF\r
+
+ FF&0x1 - DST
+ FF&0x2 - DST switch warning
+ FF&0x4 - unsynchronised
+
diff --git a/contrib/xntpd/parse/clk_dcf7000.c b/contrib/xntpd/parse/clk_dcf7000.c
index 5655d0a017f0..8b55e2f23280 100644
--- a/contrib/xntpd/parse/clk_dcf7000.c
+++ b/contrib/xntpd/parse/clk_dcf7000.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_DCF7000)
/*
- * /src/NTP/REPOSITORY/v3/parse/clk_dcf7000.c,v 3.10 1994/01/25 19:05:07 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_dcf7000.c,v 3.11 1994/02/02 17:45:14 kardel Exp
*
- * clk_dcf7000.c,v 3.10 1994/01/25 19:05:07 kardel Exp
+ * clk_dcf7000.c,v 3.11 1994/02/02 17:45:14 kardel Exp
*
* ELV DCF7000 module
*
@@ -121,6 +121,9 @@ cvt_dcf7000(buffer, size, format, clock)
* History:
*
* clk_dcf7000.c,v
+ * Revision 3.11 1994/02/02 17:45:14 kardel
+ * rcs ids fixed
+ *
* Revision 3.6 1993/10/09 15:01:27 kardel
* file structure unified
*
diff --git a/contrib/xntpd/parse/clk_meinberg.c b/contrib/xntpd/parse/clk_meinberg.c
index b08dfec91152..69f88b90d30e 100644
--- a/contrib/xntpd/parse/clk_meinberg.c
+++ b/contrib/xntpd/parse/clk_meinberg.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_MEINBERG)
/*
- * /src/NTP/REPOSITORY/v3/parse/clk_meinberg.c,v 3.11 1994/01/25 19:05:10 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_meinberg.c,v 3.14 1994/02/20 13:04:37 kardel Exp
*
- * clk_meinberg.c,v 3.11 1994/01/25 19:05:10 kardel Exp
+ * clk_meinberg.c,v 3.14 1994/02/20 13:04:37 kardel Exp
*
* Meinberg clock support
*
@@ -284,8 +284,13 @@ cvt_meinberg(buffer, size, format, clock)
clock->flags |= PARSEB_S_LEAP;
clock->flags |= PARSEB_S_ANTENNA;
+ /*
+ * DCF77 does not encode the direction -
+ * so we take the current default -
+ * earth slowing down
+ */
if (f[4] == 'A')
- clock->flags |= PARSEB_LEAP;
+ clock->flags |= PARSEB_LEAPADD;
if (f[5] == 'R')
clock->flags |= PARSEB_ALTERNATE;
@@ -394,9 +399,12 @@ cvt_mgps(buffer, size, format, clock)
/*
* oncoming leap second
+ * data format does not (yet) specify whether
+ * to add or to delete a second - thus we
+ * pick the current default
*/
if (f[5] == 'A')
- clock->flags |= PARSEB_LEAP;
+ clock->flags |= PARSEB_LEAPADD;
/*
* this is the leap second
@@ -414,6 +422,12 @@ cvt_mgps(buffer, size, format, clock)
* History:
*
* clk_meinberg.c,v
+ * Revision 3.14 1994/02/20 13:04:37 kardel
+ * parse add/delete second support
+ *
+ * Revision 3.13 1994/02/02 17:45:21 kardel
+ * rcs ids fixed
+ *
* Revision 3.11 1994/01/25 19:05:10 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/clk_rawdcf.c b/contrib/xntpd/parse/clk_rawdcf.c
index 2fd3cae20b89..6b02031b6394 100644
--- a/contrib/xntpd/parse/clk_rawdcf.c
+++ b/contrib/xntpd/parse/clk_rawdcf.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_RAWDCF)
/*
- * /src/NTP/REPOSITORY/v3/parse/clk_rawdcf.c,v 3.9 1994/01/25 19:05:12 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_rawdcf.c,v 3.13 1994/03/10 19:00:43 kardel Exp
*
- * clk_rawdcf.c,v 3.9 1994/01/25 19:05:12 kardel Exp
+ * clk_rawdcf.c,v 3.13 1994/03/10 19:00:43 kardel Exp
*
* Raw DCF77 pulse clock support
*
@@ -245,6 +245,7 @@ static unsigned LONG convert_rawdcf(buffer, size, dcfparam, clock)
parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n"));
clock->flags = PARSEB_S_ANTENNA|PARSEB_S_LEAP;
+ clock->utctime= 0;
clock->usecond= 0;
clock->second = 0;
clock->minute = ext_bf(buffer, DCF_M10, dcfparam->zerobits);
@@ -278,7 +279,7 @@ static unsigned LONG convert_rawdcf(buffer, size, dcfparam, clock)
clock->flags |= PARSEB_ANNOUNCE;
if (ext_bf(buffer, DCF_A2, dcfparam->zerobits))
- clock->flags |= PARSEB_LEAP;
+ clock->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */
if (ext_bf(buffer, DCF_R, dcfparam->zerobits))
clock->flags |= PARSEB_ALTERNATE;
@@ -529,6 +530,15 @@ static unsigned LONG snt_rawdcf(parseio, ptime)
* History:
*
* clk_rawdcf.c,v
+ * Revision 3.13 1994/03/10 19:00:43 kardel
+ * clear utctime field to avoid confusion on synthesize time stamps
+ *
+ * Revision 3.12 1994/02/20 13:04:39 kardel
+ * parse add/delete second support
+ *
+ * Revision 3.11 1994/02/02 17:45:23 kardel
+ * rcs ids fixed
+ *
* Revision 3.9 1994/01/25 19:05:12 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/clk_schmid.c b/contrib/xntpd/parse/clk_schmid.c
index a8ec8a64b546..8129474782bb 100644
--- a/contrib/xntpd/parse/clk_schmid.c
+++ b/contrib/xntpd/parse/clk_schmid.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_SCHMID)
/*
- * /src/NTP/REPOSITORY/v3/parse/clk_schmid.c,v 3.10 1994/01/25 19:05:15 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_schmid.c,v 3.13 1994/02/20 13:04:41 kardel Exp
*
- * clk_schmid.c,v 3.10 1994/01/25 19:05:15 kardel Exp
+ * clk_schmid.c,v 3.13 1994/02/20 13:04:41 kardel Exp
*
* Schmid clock support
*
@@ -152,7 +152,7 @@ cvt_schmid(buffer, size, format, clock)
if (buffer[8] & WS_LEAP)
{
- clock->flags |= PARSEB_LEAP;
+ clock->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */
}
}
@@ -168,6 +168,12 @@ cvt_schmid(buffer, size, format, clock)
* History:
*
* clk_schmid.c,v
+ * Revision 3.13 1994/02/20 13:04:41 kardel
+ * parse add/delete second support
+ *
+ * Revision 3.12 1994/02/02 17:45:25 kardel
+ * rcs ids fixed
+ *
* Revision 3.10 1994/01/25 19:05:15 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/clk_trimble.c b/contrib/xntpd/parse/clk_trimble.c
index bfbf1e6bc796..187aed52a4d7 100644
--- a/contrib/xntpd/parse/clk_trimble.c
+++ b/contrib/xntpd/parse/clk_trimble.c
@@ -1,6 +1,6 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_TRIMSV6)
/*
- * /src/NTP/REPOSITORY/v3/parse/clk_trimble.c,v 3.7 1994/01/25 19:05:17 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_trimble.c,v 3.9 1994/02/02 17:45:27 kardel Exp
*
* Trimble SV6 clock support
*/
@@ -106,6 +106,9 @@ cvt_trimsv6(buffer, size, format, clock)
* History:
*
* clk_trimble.c,v
+ * Revision 3.9 1994/02/02 17:45:27 kardel
+ * rcs ids fixed
+ *
* Revision 3.7 1994/01/25 19:05:17 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/parse.c b/contrib/xntpd/parse/parse.c
index ed5fd9a8fad7..84bfa39d1293 100644
--- a/contrib/xntpd/parse/parse.c
+++ b/contrib/xntpd/parse/parse.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
/*
- * /src/NTP/REPOSITORY/v3/parse/parse.c,v 3.19 1994/01/25 19:05:20 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parse.c,v 3.23 1994/03/25 13:09:02 kardel Exp
*
- * parse.c,v 3.19 1994/01/25 19:05:20 kardel Exp
+ * parse.c,v 3.23 1994/03/25 13:09:02 kardel Exp
*
* Parser module for reference clock
*
@@ -29,6 +29,10 @@ static char rcsid[] = "parse.c,v 3.19 1994/01/25 19:05:20 kardel Exp";
#include "sys/time.h"
#include "sys/errno.h"
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+
#include "ntp_machine.h"
#if defined(PARSESTREAM) && (defined(SYS_SUNOS4) || defined(SYS_SOLARIS)) && defined(STREAM)
@@ -49,10 +53,6 @@ static char rcsid[] = "parse.c,v 3.19 1994/01/25 19:05:20 kardel Exp";
#endif
#endif
-#include "ntp_fp.h"
-#include "ntp_unixtime.h"
-#include "ntp_calendar.h"
-
#include "parse.h"
#include "ntp_stdlib.h"
@@ -178,6 +178,10 @@ setup_bitmaps(parseio, low, high)
{
fmt = clockformats[i];
+ if (!(parseio->parse_flags & PARSE_FIXED_FMT) &&
+ (fmt->flags & CVT_FIXEDONLY))
+ continue;
+
if (fmt->flags & F_START)
{
index = fmt->startsym / 8;
@@ -556,6 +560,9 @@ parse_to_unixtime(clock, cvtrtc)
register int i;
time_t t;
+ if (clock->utctime)
+ return clock->utctime; /* if the conversion routine gets it right away - why not */
+
if (clock->year < 100)
clock->year += 1900;
@@ -628,6 +635,9 @@ parse_to_unixtime(clock, cvtrtc)
t += clock->utcoffset; /* warp to UTC */
/* done */
+
+ clock->utctime = t; /* documentray only */
+
return t;
}
@@ -890,6 +900,8 @@ timepacket(parseio)
if (parseio->parse_flags & PARSE_FIXED_FMT)
{
+ clock.utctime = 0;
+
switch ((cvtrtc = clockformats[format]->convert ? clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock) : CVT_NONE) & CVT_MASK)
{
case CVT_FAIL:
@@ -941,6 +953,8 @@ timepacket(parseio)
{
do
{
+ clock.utctime = 0;
+
switch ((cvtrtc = (clockformats[format]->convert && !(clockformats[format]->flags & CVT_FIXEDONLY)) ?
clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock) :
CVT_NONE) & CVT_MASK)
@@ -1148,6 +1162,15 @@ parse_setcs(dct, parse)
* History:
*
* parse.c,v
+ * Revision 3.23 1994/03/25 13:09:02 kardel
+ * considering FIXEDONLY entries only in FIXEDONLY mode
+ *
+ * Revision 3.22 1994/02/25 12:34:49 kardel
+ * allow for converter generated utc times
+ *
+ * Revision 3.21 1994/02/02 17:45:30 kardel
+ * rcs ids fixed
+ *
* Revision 3.19 1994/01/25 19:05:20 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/parse_conf.c b/contrib/xntpd/parse/parse_conf.c
index 0281c9dd1071..238dd1234e66 100644
--- a/contrib/xntpd/parse/parse_conf.c
+++ b/contrib/xntpd/parse/parse_conf.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
/*
- * /src/NTP/REPOSITORY/v3/parse/parse_conf.c,v 3.13 1994/01/25 19:05:23 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parse_conf.c,v 3.15 1994/02/02 17:45:32 kardel Exp
*
- * parse_conf.c,v 3.13 1994/01/25 19:05:23 kardel Exp
+ * parse_conf.c,v 3.15 1994/02/02 17:45:32 kardel Exp
*
* Parser configuration module for reference clocks
*
@@ -81,6 +81,9 @@ unsigned short nformats = sizeof(clockformats) / sizeof(clockformats[0]) - 1;
* History:
*
* parse_conf.c,v
+ * Revision 3.15 1994/02/02 17:45:32 kardel
+ * rcs ids fixed
+ *
* Revision 3.13 1994/01/25 19:05:23 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/parsesolaris.c b/contrib/xntpd/parse/parsesolaris.c
index 09fac2861f0c..23bc252e8fce 100644
--- a/contrib/xntpd/parse/parsesolaris.c
+++ b/contrib/xntpd/parse/parsesolaris.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/parsesolaris.c,v 3.9 1994/01/25 19:05:26 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parsesolaris.c,v 3.15 1994/02/15 22:20:51 kardel Exp
*
- * parsesolaris.c,v 3.9 1994/01/25 19:05:26 kardel Exp
+ * parsesolaris.c,v 3.15 1994/02/15 22:20:51 kardel Exp
*
* STREAMS module for reference clocks
* (SunOS5.x - not fully tested - buyer beware ! - OS KILLERS may still be
@@ -19,7 +19,7 @@
*/
#ifndef lint
-static char rcsid[] = "parsesolaris.c,v 3.9 1994/01/25 19:05:26 kardel Exp";
+static char rcsid[] = "parsesolaris.c,v 3.15 1994/02/15 22:20:51 kardel Exp";
#endif
/*
@@ -65,7 +65,7 @@ static struct fmodsw fmod_templ =
{
"parse", /* module name */
&parseinfo, /* module information */
- 0, /* not clean yet */
+ D_NEW|D_MP|D_MTQPAIR, /* exclusive for q pair */
/* lock ptr */
};
@@ -139,7 +139,7 @@ int Strcmp(s, t)
/*ARGSUSED*/
int _init(void)
{
- static char revision[] = "3.9";
+ static char revision[] = "3.15";
char *s, *S, *t;
/*
@@ -413,6 +413,8 @@ static int parseopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
parse->parse_ppsclockev.tv.tv_usec = 0;
parse->parse_ppsclockev.serial = 0;
+ qprocson(q);
+
parseprintf(DD_OPEN,("parse: OPEN - initializing io subsystem q=%x\n", q));
if (!parse_ioinit(&parse->parse_io))
@@ -420,6 +422,8 @@ static int parseopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
/*
* ok guys - beat it
*/
+ qprocsoff(q);
+
kmem_free((caddr_t)parse, sizeof(parsestream_t));
parsebusy--;
@@ -441,7 +445,7 @@ static int parseopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
*/
if (!notice)
{
- printf("%s: Copyright (c) 1991-1993, Frank Kardel\n", modlstrmod.strmod_linkinfo);
+ printf("%s: Copyright (c) 1991-1994, Frank Kardel\n", modlstrmod.strmod_linkinfo);
notice = 1;
}
@@ -449,7 +453,12 @@ static int parseopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
}
else
{
+ qprocsoff(q);
+
+ kmem_free((caddr_t)parse, sizeof(parsestream_t));
+
parsebusy--;
+
return EIO;
}
}
@@ -462,6 +471,8 @@ static int parseclose(queue_t *q, int flags)
parseprintf(DD_CLOSE,("parse: CLOSE\n"));
+ qprocsoff(q);
+
s = splhigh();
if (parse->parse_dqueue)
@@ -1179,6 +1190,18 @@ static void zs_xsisr(struct zscom *zs)
* History:
*
* parsesolaris.c,v
+ * Revision 3.15 1994/02/15 22:20:51 kardel
+ * rcsid fixed
+ *
+ * Revision 3.14 1994/02/15 22:06:04 kardel
+ * added qprocsx & flags for MT capability
+ *
+ * Revision 3.13 1994/02/13 19:16:47 kardel
+ * updated verbose Copyright message
+ *
+ * Revision 3.12 1994/02/02 17:45:35 kardel
+ * rcs ids fixed
+ *
* Revision 3.9 1994/01/25 19:05:26 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/parsestreams.c b/contrib/xntpd/parse/parsestreams.c
index b371aedafcee..45d296337a69 100644
--- a/contrib/xntpd/parse/parsestreams.c
+++ b/contrib/xntpd/parse/parsestreams.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/parsestreams.c,v 3.12 1994/01/25 19:05:30 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp
*
- * parsestreams.c,v 3.12 1994/01/25 19:05:30 kardel Exp
+ * parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp
*
* STREAMS module for reference clocks
* (SunOS4.x)
@@ -16,7 +16,7 @@
*/
#ifndef lint
-static char rcsid[] = "parsestreams.c,v 3.12 1994/01/25 19:05:30 kardel Exp";
+static char rcsid[] = "parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp";
#endif
#include "sys/types.h"
@@ -195,7 +195,7 @@ int xxxinit(fc, vdp, vdi, vds)
}
else
{
- static char revision[] = "3.12";
+ static char revision[] = "3.19";
char *s, *S, *t;
strncpy(ifm->f_name, mname, FMNAMESZ);
@@ -527,7 +527,7 @@ static int parseopen(q, dev, flag, sflag)
*/
if (!notice)
{
- printf("%s: Copyright (c) 1991-1993, Frank Kardel\n", parsesync_vd.Drv_name);
+ printf("%s: Copyright (c) 1991-1994, Frank Kardel\n", parsesync_vd.Drv_name);
notice = 1;
}
@@ -535,6 +535,8 @@ static int parseopen(q, dev, flag, sflag)
}
else
{
+ kmem_free((caddr_t)parse, sizeof(parsestream_t));
+
#ifdef VDDRV
parsebusy--;
#endif
@@ -1074,6 +1076,11 @@ static void close_zs_linemon(q, my_q)
#define MAXDEPTH 50 /* maximum allowed stream crawl */
+#ifdef PPS_SYNC
+extern hardpps();
+extern struct timeval time;
+#endif
+
/*
* take external status interrupt (only CD interests us)
*/
@@ -1085,15 +1092,18 @@ static void zs_xsisr(zs)
register queue_t *q;
register unsigned char zsstatus;
register int loopcheck;
- register unsigned char cdstate;
register char *dname;
+#ifdef PPS_SYNC
+ register int s;
+ register long usec;
+#endif
/*
* pick up current state
*/
zsstatus = zsaddr->zscc_control;
- if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD))
+ if ((za->za_rr0 ^ zsstatus) & (ZSRR0_CD|ZSRR0_SYNC))
{
timestamp_t cdevent;
register int status;
@@ -1101,26 +1111,44 @@ static void zs_xsisr(zs)
/*
* CONDITIONAL external measurement support
*/
- SET_LED(cdstate); /*
+ SET_LED(zsstatus & (ZSRR0_CD|ZSRR0_SYNC)); /*
* inconsistent with upper SET_LED, but this
* is for oscilloscope business anyway and we
* are just interested in edge delays in the
* lower us range
*/
-
+#ifdef PPS_SYNC
+ s = splclock();
+ usec = time.tv_usec;
+#endif
/*
* time stamp
*/
uniqtime(&cdevent.tv);
-
- TIMEVAL_USADD(&cdevent.tv, xsdelay);
-
- q = za->za_ttycommon.t_readq;
+
+#ifdef PPS_SYNC
+ splx(s);
+#endif
/*
* logical state
*/
- status = cd_invert ? cdstate == 0 : cdstate != 0;
+ status = cd_invert ? (zsstatus & (ZSRR0_CD|ZSRR0_SYNC)) == 0 : (zsstatus & (ZSRR0_CD|ZSRR0_SYNC)) != 0;
+
+#ifdef PPS_SYNC
+ if (status)
+ {
+ usec = cdevent.tv.tv_usec - usec;
+ if (usec < 0)
+ usec += 1000000;
+
+ hardpps(&cdevent.tv, usec);
+ }
+#endif
+
+ TIMEVAL_USADD(&cdevent.tv, xsdelay);
+
+ q = za->za_ttycommon.t_readq;
/*
* ok - now the hard part - find ourself
@@ -1177,10 +1205,10 @@ static void zs_xsisr(zs)
/*
* only pretend that CD has been handled
*/
- za->za_rr0 = za->za_rr0 & ~ZSRR0_CD | zsstatus & ZSRR0_CD;
+ za->za_rr0 = za->za_rr0 & ~(ZSRR0_CD|ZSRR0_SYNC) | zsstatus & (ZSRR0_CD|ZSRR0_SYNC);
ZSDELAY(2);
- if (!((za->za_rr0 ^ zsstatus) & ~ZSRR0_CD))
+ if (!((za->za_rr0 ^ zsstatus) & ~(ZSRR0_CD|ZSRR0_SYNC)))
{
/*
* all done - kill status indication and return
@@ -1258,6 +1286,24 @@ static void zs_xsisr(zs)
* History:
*
* parsestreams.c,v
+ * Revision 3.19 1994/02/24 16:33:54 kardel
+ * CD events can also be posted on sync flag
+ *
+ * Revision 3.18 1994/02/24 14:12:58 kardel
+ * initial PPS_SYNC support version
+ *
+ * Revision 3.17 1994/02/20 15:18:02 kardel
+ * rcs id cleanup
+ *
+ * Revision 3.16 1994/02/15 22:39:50 kardel
+ * memory leak on open failure closed
+ *
+ * Revision 3.15 1994/02/13 19:16:50 kardel
+ * updated verbose Copyright message
+ *
+ * Revision 3.14 1994/02/02 17:45:38 kardel
+ * rcs ids fixed
+ *
* Revision 3.12 1994/01/25 19:05:30 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/parse/util/parsetest.c b/contrib/xntpd/parse/util/parsetest.c
index 9028b4cf4cf4..21e41289a1c6 100644
--- a/contrib/xntpd/parse/util/parsetest.c
+++ b/contrib/xntpd/parse/util/parsetest.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/kernel/parsetest.c,v 3.4 1993/03/17 17:16:57 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/util/parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp
*
- * parsetest.c,v 3.10 1994/01/23 17:22:18 kardel Exp
+ * parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp
*
* Copyright (c) 1989,1990,1991,1992,1993,1994
* Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
@@ -11,15 +11,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* parsetest.c,v
- * Revision 3.4 1993/03/17 17:16:57 kardel
- * DEC OSF/1 ALPHA Integration - 930314
+ * Revision 3.13 1994/02/20 13:04:46 kardel
+ * parse add/delete second support
*
- * Revision 3.3 1993/01/18 09:24:33 kardel
- * updated copyright conditions in conjunction with
- * conditions set up in the COPYRIGHT file
- *
- * Revision 3.2 1993/01/17 13:43:00 kardel
- * 1993 initial update
+ * Revision 3.12 1994/02/02 17:45:51 kardel
+ * rcs ids fixed
*
*/
@@ -198,7 +194,7 @@ main(argc, argv)
parsetime_t parsetime;
struct strioctl strioc;
- printf("parsetest.c,v 3.10 1994/01/23 17:22:18 kardel Exp\n");
+ printf("parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp\n");
while (ioctl(fd, I_POP, 0) == 0)
;
diff --git a/contrib/xntpd/parse/util/testdcf.c b/contrib/xntpd/parse/util/testdcf.c
index ebdfd2fded07..560ab27c4369 100644
--- a/contrib/xntpd/parse/util/testdcf.c
+++ b/contrib/xntpd/parse/util/testdcf.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/util/testdcf.c,v 3.9 1994/01/25 19:05:45 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/util/testdcf.c,v 3.11 1994/02/02 17:45:55 kardel Exp
*
- * testdcf.c,v 3.9 1994/01/25 19:05:45 kardel Exp
+ * testdcf.c,v 3.11 1994/02/02 17:45:55 kardel Exp
*
* simple DCF77 100/200ms pulse test program (via 50Baud serial line)
*
diff --git a/contrib/xntpd/ppsclock/ppstest/.keep_me b/contrib/xntpd/ppsclock/ppstest/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/ppstest/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/genassym/.keep_me b/contrib/xntpd/ppsclock/sys/genassym/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/genassym/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/os/.keep_me b/contrib/xntpd/ppsclock/sys/os/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/os/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sun/.keep_me b/contrib/xntpd/ppsclock/sys/sun/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sun/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sun4c/.keep_me b/contrib/xntpd/ppsclock/sys/sun4c/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sun4c/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sun4c/conf/.keep_me b/contrib/xntpd/ppsclock/sys/sun4c/conf/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sun4c/conf/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sun4m/conf/.keep_me b/contrib/xntpd/ppsclock/sys/sun4m/conf/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sun4m/conf/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sundev/.keep_me b/contrib/xntpd/ppsclock/sys/sundev/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sundev/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/ppsclock/sys/sys/.keep_me b/contrib/xntpd/ppsclock/sys/sys/.keep_me
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/contrib/xntpd/ppsclock/sys/sys/.keep_me
+++ /dev/null
diff --git a/contrib/xntpd/refclocks/rclk.TRAK b/contrib/xntpd/refclocks/rclk.TRAK
new file mode 100644
index 000000000000..188ffd4445bc
--- /dev/null
+++ b/contrib/xntpd/refclocks/rclk.TRAK
@@ -0,0 +1,29 @@
+#!/bin/sh -
+CMD="$1"
+shift;
+
+. refclocks/setup
+
+case "$CMD" in
+ info)
+ echo " TRAK - TRAK 8810 GPS station clock"
+ ;;
+ check)
+ if check "$RCONFIG" '$0 ~ /TRAK/'; then
+ echo "TRAK - TRAK 8810 GPS station clock"
+ fi
+ ;;
+ config)
+ if check "$REFCONF" '$0 ~ /TRAK/' ||
+ ( [ ! "$REFCONF" ] && query "Include TRAK 8810 GPS station clock (TRAK)" n); then
+ if check "$PPSFEATURES" '$0 ~ /CD/' &&
+ [ "$PPSOK" -eq 1 ] &&
+ (check "$REFCONF" '$0 ~ /TRAKPPS/' ||
+ ( [ ! "$REFCONF" ] && query " Use TRAK for PPS" n)); then
+ echo "-DTRAKPPS" >> $RCONFIG
+ else
+ echo "-DTRAK" >> $RCONFIG
+ fi
+ fi
+ ;;
+esac
diff --git a/contrib/xntpd/scripts/Guess.sh b/contrib/xntpd/scripts/Guess.sh
index c2be5697eab7..88dcb1a5ef86 100755
--- a/contrib/xntpd/scripts/Guess.sh
+++ b/contrib/xntpd/scripts/Guess.sh
@@ -40,7 +40,11 @@ if [ -f /bin/uname -o -f /usr/bin/uname ]; then
guess="ultrix"
;;
hp-ux) case "$3" in
- *.10.*) guess="hpux10+" ;;
+ *.10.*) guess="hpux-adj" ;;
+ *.09.03) case "$5" in
+ 9000/3*) guess="hpux-adj" ;;
+ *) guess="hpux" ;;
+ esac ;;
*) guess="hpux" ;;
esac
;;
@@ -74,7 +78,7 @@ if [ -f /bin/uname -o -f /usr/bin/uname ]; then
3.2.*)
case "$4" in
v*)
- (i386) >/dev/null 2>&1 && guess=ptx;;
+ (i386) >/dev/null 2>&1 && [ -f /usr/lib/libseq.a ] && guess=ptx;;
esac
esac
fi
diff --git a/contrib/xntpd/scripts/README b/contrib/xntpd/scripts/README
index 79f1792a43d4..7439c6c6c498 100644
--- a/contrib/xntpd/scripts/README
+++ b/contrib/xntpd/scripts/README
@@ -11,7 +11,7 @@ Guess.sh script to figure out what machine and operating system
autoconf awesome script swiped from Jeff Johnson (who may have
swiped it from GNU) which delves deep into the system
files to reveal dark secrets necessary to port NTP to
- everything exceptt sewing machines. Unfinished work.
+ everything except sewing machines. Unfinished work.
makeconfig.sh shell script that calles Guess.sh and then figures out
what compiler is available, then builds the
diff --git a/contrib/xntpd/scripts/stats/README b/contrib/xntpd/scripts/stats/README
index 5aa64d4c1db9..680896342acb 100644
--- a/contrib/xntpd/scripts/stats/README
+++ b/contrib/xntpd/scripts/stats/README
@@ -3,20 +3,27 @@ Statistics processing scripts (README)
This directory contains a number of scripts for use with the filegen
facility. Those files ending in .awk are for the Unix awk utility, while
those ending in .sh are for the csh utility. Normally, the summary.sh
-script is called from a cron job once per day. This script calls the
-peer.sh script to process the peerstats file and append the summary
-statistics to the peer_summary file. Then, it callse the loop.sh script
-to process the loopstats file and append the summary statistics to the
-loop_summary file. Finally, it calls the clock.sh script to process the
-clockstats file and append the summary statistics to the clock_summary
-file.
+script is called from a cron job once per day. This script processes the
+daily loopstats, peerstats and clockstats files produced by the daemon,
+updates the loop_summary, peer_summary and clock_summary archive files,
+and deletes the daily files.
-Each of the three shell scripts peer.sh, loop.sh and clock.sh invoke
-one or more awk scripts to actually produce the data. This may result
-in multiple scans of the same input file. The input file is deleted after
-processing. In fact, the shell scripts will process all input files
-found of the correct type in chronological order, deleting each one as
-it is scanned, except the current day file.
+In the case of the Austron 2201A GPS receiver, the clockstats file
+contains a wealth of additional monitoring data. These data are summarized
+and writted to the clock_summary file, then a series of special files are
+constructed for later processing by the S utility.
+
+The summary.sh script invokes a number of awk scripts to actually produce
+the data. This may result in multiple scans of the same input file.
+The input file is deleted after processing. In fact, the shell scripts will
+process all input files found of the correct type in chronological order,
+deleting each one as it is scanned, except the current day file.
+
+The summary.sh script can produce input files for the S utility, if it
+is found on the search path. This utility makes PostScript graphs of the
+loopstats data for each day, as well as various statistics produced by
+the Austorn 220aA GPS receiver. The S utility is automatically run
+as a background job. Its control files have the .S extension.
The psummary.awk script can be used to scan the peer_summary file and
construct an historical reprise of the daily summaries.
@@ -29,4 +36,4 @@ David L. Mills
University of Delaware
mills@udel.edu
1 November 1993
-
+Revised 12 April 1994
diff --git a/contrib/xntpd/scripts/stats/dupe.awk b/contrib/xntpd/scripts/stats/dupe.awk
index 3ddc1b6f9754..317c2a4faf84 100644
--- a/contrib/xntpd/scripts/stats/dupe.awk
+++ b/contrib/xntpd/scripts/stats/dupe.awk
@@ -1,4 +1,5 @@
-# program to delete duplicate lines in a file
+#
+# delete duplicate lines
#
{
if (old != $0)
diff --git a/contrib/xntpd/scripts/stats/ensemble.S b/contrib/xntpd/scripts/stats/ensemble.S
new file mode 100644
index 000000000000..32a4dbabb820
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/ensemble.S
@@ -0,0 +1,5 @@
+ensemble <- scan(file1, list(day=0, sec=0, gps=0, gpsw=0, loran=0, loranw=0, ensemble=0, std=0))
+str <- paste("eps/", file1, ".eps", sep="")
+postscript(str, , , , 5, pointsize=18)
+par(mgp=c(1, 0, 0), tck = 0.03, mar = c(2, 2, 1, 1))
+plot(ensemble$sec, ensemble$ensemble, type="l", xlab=paste("MJD", ensemble$day, "Time (s)"), ylab="Ensemble Offset (ns)", ylim=c(-400, 400))
diff --git a/contrib/xntpd/scripts/stats/etf.S b/contrib/xntpd/scripts/stats/etf.S
new file mode 100644
index 000000000000..9b9c68b937b5
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/etf.S
@@ -0,0 +1,15 @@
+options(digits=4)
+file2 <- "etf_summary"
+etf <- scan(file1, list(day=0, sec=0, offset=0, stab=0))
+r <- lsfit(etf$sec, etf$offset)
+count<-length(etf$sec)
+mean<-r$coef[[1]]
+std<-sqrt(var(r$residuals))
+slope<-r$coef[[2]] * 1000
+cat("\n", file=file2 , append=TRUE, fill=FALSE, sep="")
+cat(file1, "\n", file=file2, append=TRUE, fill=FALSE, sep="")
+cat("etf1 ", count, ", T ", mean, " ns, R ", slope, " ps/s, std ", std, " us\n", file=file2, append=TRUE, fill=FALSE, sep="")
+str <- paste("eps/", file1, ".eps", sep="")
+postscript(str, , , , 5, pointsize=18)
+par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1))
+plot(etf$sec, etf$offset, type="l", xlab=paste("MJD", etf$day, "Time (s)"), ylab="External Offset (ns)", ylim=c(-400, 400))
diff --git a/contrib/xntpd/scripts/stats/itf.S b/contrib/xntpd/scripts/stats/itf.S
new file mode 100644
index 000000000000..56c8c8d0cc7a
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/itf.S
@@ -0,0 +1,5 @@
+itf <- scan(file1, list(day=0, sec=0, offset=0, stab=0))
+str <- paste("eps/", file1, ".eps", sep="")
+postscript(str, , , , 5, pointsize=18)
+par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1))
+plot(itf$sec, itf$offset, type="l", xlab=paste("MJD", itf$day, "Time (s)"), ylab="Internal Offset (ns)", ylim=c(-400, 400))
diff --git a/contrib/xntpd/scripts/stats/loop.S b/contrib/xntpd/scripts/stats/loop.S
new file mode 100644
index 000000000000..8e564b67eb67
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/loop.S
@@ -0,0 +1,7 @@
+options(digits=4)
+loop <- scan(file1, list(day=0, sec=0, offset=0, freq=0, tc=0))
+loop$offset <- loop$offset * 1e6
+str <- paste("eps/", file1, ".eps", sep="")
+postscript(str, , , , 5, pointsize=18)
+par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1))
+plot(loop$sec, loop$offset, type="l", xlab=paste("MJD", loop$day, "Time (s)"), ylab="PLL Offset (us)", ylim=c(-400, 400))
diff --git a/contrib/xntpd/scripts/stats/loop.awk b/contrib/xntpd/scripts/stats/loop.awk
index 25d0bdb97d53..470b27c8bef5 100644
--- a/contrib/xntpd/scripts/stats/loop.awk
+++ b/contrib/xntpd/scripts/stats/loop.awk
@@ -35,15 +35,7 @@ BEGIN {
loop_time_rms = sqrt(loop_time_rms / loop_count - loop_time * loop_time)
loop_freq /= loop_count
loop_freq_rms = sqrt(loop_freq_rms / loop_count - loop_freq * loop_freq)
- loop_tmax = loop_tmax - loop_time
- loop_tmin = loop_time - loop_tmin
- if (loop_tmin > loop_tmax)
- loop_tmax = loop_tmin
- loop_fmax = loop_fmax - loop_freq
- loop_fmin = loop_time - loop_fmin
- if (loop_fmin > loop_fmax)
- loop_fmax = loop_fmin
- printf "loop %d, %.0f+/-%.1f, rms %.1f, freq %.2f+/-%0.3f, rms %.3f\n", loop_count, loop_time * 1e6, loop_tmax * 1e6, loop_time_rms * 1e6, loop_freq, loop_fmax, loop_freq_rms
+ printf "loop %d, %.0f+/-%.1f, rms %.1f, freq %.2f+/-%0.3f, var %.3f\n", loop_count, (loop_tmax + loop_tmin) / 2 * 1e6, (loop_tmax - loop_tmin) / 2 * 1e6, loop_time_rms * 1e6, (loop_fmax + loop_fmin) / 2, (loop_fmax - loop_fmin) / 2, loop_freq_rms
}
}
diff --git a/contrib/xntpd/scripts/stats/psummary.awk b/contrib/xntpd/scripts/stats/psummary.awk
index b7f0e922a7d6..5ef8d8eb5280 100644
--- a/contrib/xntpd/scripts/stats/psummary.awk
+++ b/contrib/xntpd/scripts/stats/psummary.awk
@@ -1,5 +1,7 @@
# program to scan peer_summary file and produce summary of daily summaries
#
+# usage: awk -f psummary.awk peer_summary
+#
{
if (NF < 8 || $1 == "ident")
continue
diff --git a/contrib/xntpd/scripts/stats/rms.awk b/contrib/xntpd/scripts/stats/rms.awk
new file mode 100644
index 000000000000..34d612ab3582
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/rms.awk
@@ -0,0 +1,41 @@
+# program to scan peer_summary file
+#
+{
+ if (NF < 8 || $1 == "ident")
+ continue
+ i = n
+ for (j = 0; j < n; j++) {
+ if ($1 == peer_ident[j])
+ i = j
+ }
+ if (i == n) {
+ peer_ident[i] = $1
+ n++
+ }
+ peer_count[i]++
+ if (($7 - $6 / 2) < 400) {
+ peer_count[i]++
+ peer_mean[i] += $3
+ peer_var[i] += $4 * $4
+ if ($5 > peer_max[i])
+ peer_max[i] = $5
+ if ($5 > 1)
+ peer_1[i]++
+ if ($5 > 5)
+ peer_2[i]++
+ if ($5 > 10)
+ peer_3[i]++
+ if ($5 > 50)
+ peer_4[i]++
+ }
+} END {
+ printf " host cnt mean sd max >1 >5 >10 >50\n"
+ printf "=================================================================\n"
+ for (i = 0; i < n; i++) {
+ if (peer_count[i] <= 0)
+ continue
+ peer_mean[i] /= peer_count[i]
+ peer_var[i] = sqrt(peer_var[i] / peer_count[i])
+ printf "%15s%4d%10.3f%10.3f%10.3f%4d%4d%4d%4d\n", peer_ident[i], peer_count[i], peer_mean[i], peer_var[i], peer_max[i], peer_1[i], peer_2[i], peer_3[i], peer_4[i]
+ }
+}
diff --git a/contrib/xntpd/scripts/stats/summary.sh b/contrib/xntpd/scripts/stats/summary.sh
index ab99f4d8e8d5..caac2b0c3bec 100755
--- a/contrib/xntpd/scripts/stats/summary.sh
+++ b/contrib/xntpd/scripts/stats/summary.sh
@@ -1,17 +1,88 @@
-#!/bin/csh
+#!/bin/sh
#
# Script to summarize ipeerstats, loopstats and clockstats files
#
# This script can be run from a cron job once per day, week or month. It
# runs the file-specific summary script and appends the summary data to
-# designated files, which must be created first.
-#
-if ( -e peer_summary ) then
- peer.sh >>peer_summary
-endif
-if ( -e loop_summary ) then
- loop.sh >>loop_summary
-endif
-if ( -e clock_summary ) then
- clock.sh >>clock_summary
-endif
+# designated files.
+#
+DATE=`date +19%y%m%d`
+SIN=S.in
+SOUT=S.out
+LOOP=loop_summary
+PEER=peer_summary
+CLOCK=clock_summary
+
+rm -f $SIN $SOUT
+S=0
+if [ -f `which S | cut -f1 -d" "` ]; then
+ S=1
+fi
+#
+# Summarize loopstats files
+#
+for f in loopstats.????????; do
+ d=`echo $f | cut -f2 -d.`
+ if [ $DATE != $d ]; then
+ echo " " >>$LOOP
+ echo $f >>$LOOP
+ awk -f loop.awk $f >>$LOOP
+ if [ $S ]; then
+ echo "file1<-"\"${f}\" >>$SIN
+ echo "source("\""loop.S"\"")" >>$SIN
+ fi
+ rm -f $f
+ fi
+done
+
+#
+# Summarize peerstats files
+#
+for f in peerstats.????????; do
+ d=`echo $f | cut -f2 -d.`
+ if [ $DATE != $d ]; then
+ echo " " >>$PEER
+ echo $f >>$PEER
+ awk -f peer.awk $f >>$PEER
+ rm -f $f
+ fi
+done
+
+#
+# Summarize clockstats files
+#
+for f in clockstats.????????; do
+ d=`echo $f | cut -f2 -d.`
+ if [ $DATE != $d ]; then
+ echo " " >>$CLOCK
+ echo $f >>$CLOCK
+ awk -f clock.awk $f >>$CLOCK
+ if [ -f /dev/gps* ]; then
+ awk -f itf.awk $f >itf.$d
+ awk -f etf.awk $f >etf.$d
+ awk -f ensemble.awk $f >ensemble.$d
+ awk -f tdata.awk $f >tdata.$d
+ fi
+ rm -f $f
+ fi
+done
+
+#
+# Process clockstat files with S and generate PostScript plots
+#
+for f in itf etf ensemble tdata; do
+ for d in ${f}.????????; do
+ if [ -f $d ]; then
+ if [ $S ]; then
+ echo "file1<-"\"${d}\" >>$SIN
+ echo "source("\"${f}.S\"")" >>$SIN
+ echo "unix("\""rm ${d}"\"")" >>$SIN
+ else
+ rm -f $d
+ fi
+ fi
+ done
+done
+if [ -f $SIN ]; then
+ S BATCH $SIN $SOUT
+fi
diff --git a/contrib/xntpd/scripts/stats/tdata.S b/contrib/xntpd/scripts/stats/tdata.S
new file mode 100644
index 000000000000..f360a248c06a
--- /dev/null
+++ b/contrib/xntpd/scripts/stats/tdata.S
@@ -0,0 +1,5 @@
+tdata <- scan(file1, list(day=0, sec=0, m=0, w=0, x=0, y=0, z=0))
+str <- paste("eps/", file1, ".eps", sep="")
+postscript(str, , , , 5, pointsize=18)
+par(mgp=c(1, 0, 0), tck=0.03, mar=c(2, 2, 1, 1))
+plot(tdata$sec, tdata$m, type="l", xlab=paste("MJD", tdata$day, "Time (s)"), ylab="LORAN-M SNR (dB)")
diff --git a/contrib/xntpd/scripts/support/bin/monl b/contrib/xntpd/scripts/support/bin/monl
index 44201d0d0f99..f0c48dbf5f3f 100755
--- a/contrib/xntpd/scripts/support/bin/monl
+++ b/contrib/xntpd/scripts/support/bin/monl
@@ -143,7 +143,8 @@ foreach $hostname (@ARGV)
{
chop;
split;
- ($host, $count, $mode, $version, $lasttime, $firsttime) = (@_[$[, $[+2 .. $[+6]);
+ ($host, $count, $mode, $version, $lasttime, $firsttime) =
+ (@_[$[, $[+2 .. $[+4, $#_-1,$#_]);
$Seen{$host, $mode} = 1;
diff --git a/contrib/xntpd/util/ntptime.c b/contrib/xntpd/util/ntptime.c
index c0512df90a87..858fe7cba481 100644
--- a/contrib/xntpd/util/ntptime.c
+++ b/contrib/xntpd/util/ntptime.c
@@ -15,27 +15,29 @@
#include <signal.h>
#include <errno.h>
-#include <sys/syscall.h>
-
#include "ntp_fp.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
#ifndef SYS_DECOSF1
#define BADCALL -1 /* this is supposed to be a bad syscall */
-#endif
-#include "ntp_timex.h"
+#endif /* SYS_DECOSF1 */
-#ifdef KERNEL_PLL
-#ifndef SYS_ntp_adjtime
+#ifdef KERNEL_PLL
+#include <sys/timex.h>
+#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
+#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
+#else /* KERNEL_PLL */
+#include "ntp_timex.h"
#define SYS_ntp_adjtime NTP_SYSCALL_ADJ
-#endif
-#ifndef SYS_ntp_gettime
#define SYS_ntp_gettime NTP_SYSCALL_GET
-#endif
-#endif /* KERNEL_PLL */
+#endif /* KERNEL_PLL */
+/*
+ * Function prototypes
+ */
extern int sigvec P((int, struct sigvec *, struct sigvec *));
+extern int syscall P((int, void *, ...));
void pll_trap P((void));
static struct sigvec newsigsys; /* new sigvec status */
@@ -56,50 +58,50 @@ main(argc, argv)
struct ntptimeval ntv;
struct timex ntx, _ntx;
int times[20];
- double ftemp;
+ double ftemp, gtemp;
l_fp ts;
int c;
int errflg = 0;
int cost = 0;
int rawtime = 0;
- ntx.mode = 0;
+ memset((char *)&ntx, 0, sizeof(ntx));
progname = argv[0];
while ((c = ntp_getopt(argc, argv, optargs)) != EOF) switch (c) {
case 'c':
cost++;
break;
case 'e':
- ntx.mode |= ADJ_ESTERROR;
+ ntx.modes |= MOD_ESTERROR;
ntx.esterror = atoi(ntp_optarg);
break;
case 'f':
- ntx.mode |= ADJ_FREQUENCY;
- ntx.frequency = (int) (atof(ntp_optarg)
- * (1 << SHIFT_USEC));
- if (ntx.frequency < (-100 << SHIFT_USEC)
- || ntx.frequency > ( 100 << SHIFT_USEC)) errflg++;
+ ntx.modes |= MOD_FREQUENCY;
+ ntx.freq = (int) (atof(ntp_optarg) *
+ (1 << SHIFT_USEC));
+ if (ntx.freq < (-100 << SHIFT_USEC)
+ || ntx.freq > ( 100 << SHIFT_USEC)) errflg++;
break;
case 'm':
- ntx.mode |= ADJ_MAXERROR;
+ ntx.modes |= MOD_MAXERROR;
ntx.maxerror = atoi(ntp_optarg);
break;
case 'o':
- ntx.mode |= ADJ_OFFSET;
+ ntx.modes |= MOD_OFFSET;
ntx.offset = atoi(ntp_optarg);
break;
case 'r':
rawtime++;
break;
case 's':
- ntx.mode |= ADJ_STATUS;
+ ntx.modes |= MOD_STATUS;
ntx.status = atoi(ntp_optarg);
if (ntx.status < 0 || ntx.status > 4) errflg++;
break;
case 't':
- ntx.mode |= ADJ_TIMECONST;
- ntx.time_constant = atoi(ntp_optarg);
- if (ntx.time_constant < 0 || ntx.time_constant > MAXTC)
+ ntx.modes |= MOD_TIMECONST;
+ ntx.constant = atoi(ntp_optarg);
+ if (ntx.constant < 0 || ntx.constant > MAXTC)
errflg++;
break;
default:
@@ -115,7 +117,7 @@ main(argc, argv)
-m maxerror max possible error (us)\n\
-o offset current offset (ms)\n\
-r print the unix and NTP time raw\n\
- -s status Set the status (0 .. 4)\n\
+ -l leap Set the leap bits\n\
-t timeconstant log2 of PLL time constant (0 .. %d)\n",
progname, optargs, MAXTC);
exit(2);
@@ -151,13 +153,13 @@ main(argc, argv)
times[c] = ntv.time.tv_usec;
}
if (pll_control >= 0) {
- printf("[ usec %06d:", times[0]);
+ printf("[ us %06d:", times[0]);
for (c=1; c< sizeof times / sizeof times[0]; c++) printf(" %d", times[c] - times[c-1]);
printf(" ]\n");
}
}
(void)ntp_gettime(&ntv);
- ntx.mode = 0; /* Ensure nothing is set */
+ _ntx.modes = 0; /* Ensure nothing is set */
(void)ntp_adjtime(&_ntx);
if (pll_control < 0) {
printf("NTP user interface routines are not configured in this kernel.\n");
@@ -175,9 +177,9 @@ main(argc, argv)
ts.l_uf += TS_ROUNDBIT; /* guaranteed not to overflow */
ts.l_ui += JAN_1970;
ts.l_uf &= TS_MASK;
- printf(" time: %s, (.%06d)\n",
+ printf(" time %s, (.%06d),\n",
prettydate(&ts), ntv.time.tv_usec);
- printf(" confidence interval: %ld usec, estimated error: %ld usec\n",
+ printf(" maximum error %ld us, estimated error %ld us.\n",
ntv.maxerror, ntv.esterror);
if (rawtime) printf(" ntptime=%x.%x unixtime=%x.%06d %s",
ts.l_ui, ts.l_uf,
@@ -189,15 +191,26 @@ main(argc, argv)
">> ntp_adjtime() call fails");
else {
printf("ntp_adjtime() returns code %d\n", status);
- ftemp = ntx.frequency;
+ ftemp = ntx.freq;
ftemp /= (1 << SHIFT_USEC);
- printf(" mode: %02x, offset: %ld usec, frequency: %6.3f ppm,\n",
- ntx.mode, ntx.offset, ftemp);
- printf(" confidence interval: %ld usec, estimated error: %ld usec,\n",
+ printf(" modes %04x, offset %ld us, frequency %.3f ppm, interval %d s,\n",
+ ntx.modes, ntx.offset, ftemp, 1 << ntx.shift);
+ printf(" maximum error %ld us, estimated error %ld us,\n",
ntx.maxerror, ntx.esterror);
- printf(" status: %d, time constant: %ld, precision: %ld usec, tolerance: %ld usec\n",
- ntx.status, ntx.time_constant, ntx.precision,
- ntx.tolerance);
+ ftemp = ntx.tolerance;
+ ftemp /= (1 << SHIFT_USEC);
+ printf(" status %04x, time constant %ld, precision %ld us, tolerance %.0f ppm,\n",
+ ntx.status, ntx.constant, ntx.precision, ftemp);
+ if (ntx.shift == 0)
+ return;
+ ftemp = ntx.ppsfreq;
+ ftemp /= (1 << SHIFT_USEC);
+ gtemp = ntx.stabil;
+ gtemp /= (1 << SHIFT_USEC);
+ printf(" pps frequency %.3f ppm, stability %.3f ppm, jitter %ld us,\n",
+ ftemp, gtemp, ntx.jitter);
+ printf(" intervals %ld, jitter exceeded %ld, stability exceeded %ld, errors %ld.\n",
+ ntx.calcnt, ntx.jitcnt, ntx.stbcnt, ntx.errcnt);
}
/*
diff --git a/contrib/xntpd/util/tickadj.c b/contrib/xntpd/util/tickadj.c
index ab10b3728a0e..caec06871795 100644
--- a/contrib/xntpd/util/tickadj.c
+++ b/contrib/xntpd/util/tickadj.c
@@ -1,4 +1,4 @@
-/* tickadj.c,v 3.1 1993/07/06 01:11:05 jbj Exp
+/*
* tickadj - read, and possibly modify, the kernel `tick' and
* `tickadj' variables, as well as `dosynctodr'. Note that
* this operates on the running kernel only. I'd like to be
@@ -6,6 +6,41 @@
* mastered this yet.
*/
#include <stdio.h>
+
+#ifdef SYS_LINUX
+#include <sys/timex.h>
+
+struct timex txc;
+
+int
+main(int argc, char ** argv)
+{
+ if (argc > 2)
+ {
+ fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]);
+ exit(-1);
+ }
+ else if (argc == 2)
+ {
+ if ( (txc.tick = atoi(argv[1])) < 1 )
+ {
+ fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
+ exit(-1);
+ }
+ txc.mode = ADJ_TICK;
+ }
+ else
+ txc.mode = 0;
+
+ if (__adjtimex(&txc) < 0)
+ perror("adjtimex");
+ else
+ printf("tick = %d\n", txc.tick);
+
+ return(0);
+}
+#else /* not Linux... kmem tweaking: */
+
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
@@ -298,10 +333,13 @@ getoffsets(filex, tick_off, tickadj_off, dosync_off, noprintf_off)
#if defined(SYS_AUX3) || defined(SYS_AUX2)
#define X_TICKADJ 0
-#define X_V 1
-#define X_TICK 2
+#define X_TICK 1
#define X_DEF
- static struct nlist nl[4];
+ static struct nlist nl[] =
+ { {"tickadj"},
+ {"tick"},
+ {""},
+ };
#endif
#ifdef NeXT
@@ -353,6 +391,22 @@ getoffsets(filex, tick_off, tickadj_off, dosync_off, noprintf_off)
#endif
#endif
+#if defined(SYS_HPUX)
+#define X_TICKADJ 0
+#define X_TICK 1
+#define X_DEF
+ static struct nlist nl[] =
+#ifdef hp9000s300
+ { {"_tickadj"},
+ {"_old_tick"},
+#else
+ { {"tickadj"},
+ {"old_tick"},
+#endif
+ {""},
+ };
+#endif
+
#if !defined(X_DEF)
#define X_TICKADJ 0
#define X_TICK 1
@@ -373,17 +427,11 @@ getoffsets(filex, tick_off, tickadj_off, dosync_off, noprintf_off)
"/kernel/unix",
"/386bsd",
"/netbsd",
+ "/hp-ux",
NULL
};
struct stat stbuf;
-#if defined(SYS_AUX3) || defined(SYS_AUX2)
- strcpy (nl[X_TICKADJ].n_name, "tickadj");
- strcpy (nl[X_V].n_name, "v");
- strcpy (nl[X_TICK].n_name, "tick");
- nl[3].n_name[0] = '\0';
-#endif
-
for (kname = kernels; *kname != NULL; kname++) {
if (stat(*kname, &stbuf) == -1)
continue;
@@ -513,3 +561,4 @@ readvar(fd, off, var)
exit(1);
}
}
+#endif /* not Linux */
diff --git a/contrib/xntpd/xntpd/Makefile b/contrib/xntpd/xntpd/Makefile
index 56f5dc2eb6eb..a4b083efde72 100644
--- a/contrib/xntpd/xntpd/Makefile
+++ b/contrib/xntpd/xntpd/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.4 1994/02/03 23:23:17 wollman Exp $
+# $Id: Makefile,v 1.5 1994/04/03 20:37:26 wollman Exp $
#
CFLAGS+= -I${.CURDIR}/../include
@@ -34,7 +34,7 @@ SRCS= ntp_config.c ntp_control.c ntp_io.c ntp_leap.c \
refclock_wwvb.c refclock_goes.c refclock_mx4200.c \
refclock_parse.c refclock_as2201.c refclock_omega.c \
refclock_tpro.c refclock_leitch.c refclock_irig.c \
- refclock_msfees.c refclock_gpstm.c ntp_intres.c \
+ refclock_msfees.c refclock_gpstm.c refclock_trak.c ntp_intres.c \
ntp_filegen.c version.c
beforedepend: version.c
diff --git a/contrib/xntpd/adjtime/.keep_me b/contrib/xntpd/xntpd/minpoll
index e69de29bb2d1..e69de29bb2d1 100644
--- a/contrib/xntpd/adjtime/.keep_me
+++ b/contrib/xntpd/xntpd/minpoll
diff --git a/contrib/xntpd/xntpd/ntp_config.c b/contrib/xntpd/xntpd/ntp_config.c
index 1b716f69fab5..8f356ac8c2e7 100644
--- a/contrib/xntpd/xntpd/ntp_config.c
+++ b/contrib/xntpd/xntpd/ntp_config.c
@@ -45,8 +45,9 @@
* peer 128.100.1.1 [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
* server 128.100.2.2 [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
* precision -7
- * broadcast 128.100.224.255 [ version 3 ] [ key 0 ]
- * broadcastclient yes|no
+ * broadcast 128.100.224.255 [ version 3 ] [ key 0 ] [ ttl 1 ]
+ * broadcastclient
+ * multicastclient [224.0.1.1]
* broadcastdelay 0.0102
* authenticate yes|no
* monitor yes|no
@@ -58,6 +59,16 @@
* statsdir /var/NTP/
* filegen peerstats [ file peerstats ] [ type day ] [ link ]
* resolver /path/progname
+ * clientlimit [ n ]
+ * clientperiod [ 3600 ]
+ * trustedkey [ key ]
+ * requestkey [ key]
+ * controlkey [ key ]
+ * trap [ address ]
+ * fudge [ ... ]
+ * pidfile [ ]
+ * logfile [ ]
+ * setvar [ ]
*
* And then some. See the manual page.
*/
@@ -84,22 +95,24 @@
#define CONFIG_CONTROLKEY 15
#define CONFIG_TRAP 16
#define CONFIG_FUDGE 17
-#define CONFIG_MAXSKEW 18
-#define CONFIG_RESOLVER 19
-#define CONFIG_SELECT 20
-#define CONFIG_STATSDIR 21
-#define CONFIG_FILEGEN 22
-#define CONFIG_STATISTICS 23
-#define CONFIG_PPS 24
-#define CONFIG_PIDFILE 25
-#define CONFIG_LOGFILE 26
-#define CONFIG_SETVAR 27
+#define CONFIG_RESOLVER 18
+#define CONFIG_STATSDIR 19
+#define CONFIG_FILEGEN 20
+#define CONFIG_STATISTICS 21
+#define CONFIG_PPS 22
+#define CONFIG_PIDFILE 23
+#define CONFIG_LOGFILE 24
+#define CONFIG_SETVAR 25
+#define CONFIG_CLIENTLIMIT 26
+#define CONFIG_CLIENTPERIOD 27
+#define CONFIG_MULTICASTCLIENT 28
#define CONF_MOD_VERSION 1
#define CONF_MOD_KEY 2
#define CONF_MOD_MINPOLL 3
#define CONF_MOD_MAXPOLL 4
#define CONF_MOD_PREFER 5
+#define CONF_MOD_TTL 6
#define CONF_PPS_DELAY 1
#define CONF_PPS_BAUD 2
@@ -114,6 +127,7 @@
#define CONF_RES_NOTRAP 8
#define CONF_RES_LPTRAP 9
#define CONF_RES_NTPPORT 10
+#define CONF_RES_LIMITED 11
#define CONF_TRAP_PORT 1
#define CONF_TRAP_INTERFACE 2
@@ -158,6 +172,7 @@ static struct keyword keywords[] = {
{ "driftfile", CONFIG_DRIFTFILE },
{ "broadcast", CONFIG_BROADCAST },
{ "broadcastclient", CONFIG_BROADCASTCLIENT },
+ { "multicastclient", CONFIG_MULTICASTCLIENT },
{ "authenticate", CONFIG_AUTHENTICATE },
{ "keys", CONFIG_KEYS },
{ "monitor", CONFIG_MONITOR },
@@ -170,15 +185,15 @@ static struct keyword keywords[] = {
{ "controlkey", CONFIG_CONTROLKEY },
{ "trap", CONFIG_TRAP },
{ "fudge", CONFIG_FUDGE },
- { "maxskew", CONFIG_MAXSKEW },
{ "resolver", CONFIG_RESOLVER },
- { "select", CONFIG_SELECT },
{ "statsdir", CONFIG_STATSDIR },
{ "filegen", CONFIG_FILEGEN },
{ "statistics", CONFIG_STATISTICS },
{ "pidfile", CONFIG_PIDFILE },
{ "logfile", CONFIG_LOGFILE },
{ "setvar", CONFIG_SETVAR },
+ { "clientlimit", CONFIG_CLIENTLIMIT },
+ { "clientperiod", CONFIG_CLIENTPERIOD },
{ "", CONFIG_UNKNOWN }
};
@@ -191,6 +206,7 @@ static struct keyword mod_keywords[] = {
{ "minpoll", CONF_MOD_MINPOLL },
{ "maxpoll", CONF_MOD_MAXPOLL },
{ "prefer", CONF_MOD_PREFER },
+ { "ttl", CONF_MOD_TTL },
{ "", CONFIG_UNKNOWN }
};
@@ -217,6 +233,7 @@ static struct keyword res_keywords[] = {
{ "notrap", CONF_RES_NOTRAP },
{ "lowpriotrap", CONF_RES_LPTRAP },
{ "ntpport", CONF_RES_NTPPORT },
+ { "limited", CONF_RES_LIMITED },
{ "", CONFIG_UNKNOWN }
};
@@ -318,12 +335,12 @@ extern int debug;
#endif
extern char *FindConfig();
char *progname;
-static char *xntp_options = "abc:de:f:k:l:p:r:s:t:v:V:";
+static char *xntp_options = "abc:de:f:k:l:mp:r:s:t:v:V:";
static int gettokens P((FILE *, char *, char **, int *));
static int matchkey P((char *, struct keyword *));
static int getnetnum P((char *, struct sockaddr_in *, int));
-static void save_resolve P((char *, int, int, int, int, int, U_LONG));
+static void save_resolve P((char *, int, int, int, int, int, int, U_LONG));
static void do_resolve P((char *, U_LONG, char *));
#ifdef RESOLVE_INTERNAL
static void do_resolve_internal P((void));
@@ -410,6 +427,7 @@ getconfig(argc, argv)
int peerversion;
int minpoll;
int maxpoll;
+ int ttl;
U_LONG peerkey;
int peerflags;
int hmode;
@@ -466,12 +484,15 @@ getconfig(argc, argv)
case 'a':
proto_config(PROTO_AUTHENTICATE, (LONG)1);
break;
+
case 'b':
proto_config(PROTO_BROADCLIENT, (LONG)1);
break;
+
case 'c':
config_file = ntp_optarg;
break;
+
case 'd':
#ifdef DEBUG
debug++;
@@ -516,6 +537,10 @@ getconfig(argc, argv)
}
break;
+ case 'm':
+ proto_config(PROTO_MULTICAST_ADD, INADDR_NTP);
+ break;
+
case 'p':
stats_config(STATS_PID_FILE, ntp_optarg);
break;
@@ -624,6 +649,7 @@ getconfig(argc, argv)
maxpoll = NTP_MAXPOLL;
peerkey = 0;
peerflags = 0;
+ ttl = 1;
for (i = 2; i < ntokens; i++)
switch (matchkey(tokens[i], mod_keywords)) {
case CONF_MOD_VERSION:
@@ -689,6 +715,16 @@ getconfig(argc, argv)
peerflags |= FLAG_PREFER;
break;
+ case CONF_MOD_TTL:
+ if (i >= ntokens-1) {
+ syslog(LOG_ERR,
+ "ttl: argument required");
+ errflg = 1;
+ break;
+ }
+ ttl = atoi(tokens[++i]);
+ break;
+
case CONFIG_UNKNOWN:
errflg = 1;
break;
@@ -700,14 +736,15 @@ getconfig(argc, argv)
if (errflg == 0) {
if (peer_config(&peeraddr,
(struct interface *)0, hmode, peerversion,
- minpoll, maxpoll, peerkey, peerflags) == 0) {
+ minpoll, maxpoll, peerflags, ttl, peerkey)
+ == 0) {
syslog(LOG_ERR,
"configuration of %s failed",
ntoa(&peeraddr));
}
} else if (errflg == -1) {
save_resolve(tokens[1], hmode, peerversion,
- minpoll, maxpoll, peerflags, peerkey);
+ minpoll, maxpoll, peerflags, ttl, peerkey);
}
break;
@@ -764,23 +801,20 @@ getconfig(argc, argv)
} break;
case CONFIG_BROADCASTCLIENT:
- errflg = 0;
- if (ntokens >= 2) {
- if (STREQ(tokens[1], "yes"))
- proto_config(PROTO_BROADCLIENT, (LONG)1);
- else if (STREQ(tokens[1], "no"))
- proto_config(PROTO_BROADCLIENT, (LONG)0);
- else
- errflg++;
- } else {
- errflg++;
- }
-
- if (errflg)
- syslog(LOG_ERR,
- "should be `broadcastclient yes|no'");
+ proto_config(PROTO_BROADCLIENT, (U_LONG)1);
break;
+ case CONFIG_MULTICASTCLIENT:
+ if (ntokens > 1) {
+ for (i = 1; i < ntokens; i++) {
+ if (getnetnum(tokens[i], &peeraddr, 1));
+ proto_config(PROTO_MULTICAST_ADD,
+ peeraddr.sin_addr.s_addr);
+ }
+ } else
+ proto_config(PROTO_MULTICAST_ADD, INADDR_NTP);
+ break;
+
case CONFIG_AUTHENTICATE:
errflg = 0;
if (ntokens >= 2) {
@@ -817,9 +851,9 @@ getconfig(argc, argv)
errflg = 0;
if (ntokens >= 2) {
if (STREQ(tokens[1], "yes"))
- mon_start();
+ mon_start(MON_ON);
else if (STREQ(tokens[1], "no"))
- mon_stop();
+ mon_stop(MON_ON);
else
errflg++;
} else {
@@ -965,6 +999,10 @@ getconfig(argc, argv)
peerkey |= RESM_NTPONLY;
break;
+ case CONF_RES_LIMITED:
+ peerversion |= RES_LIMITED;
+ break;
+
case CONFIG_UNKNOWN:
errflg++;
break;
@@ -1252,26 +1290,6 @@ getconfig(argc, argv)
#endif
break;
- case CONFIG_MAXSKEW:
- if (ntokens >= 2) {
- l_fp tmp;
- u_fp utmp;
-
- if (!atolfp(tokens[1], &tmp)) {
- syslog(LOG_ERR,
- "maxskew value %s undecodable",
- tokens[1]);
- } else if (tmp.l_ui != 0) {
- syslog(LOG_ERR,
- "maxskew value %s is unlikely",
- tokens[1]);
- } else {
- utmp = LFPTOFP(&tmp);
- proto_config(PROTO_MAXSKEW, (LONG)utmp);
- }
- }
- break;
-
case CONFIG_RESOLVER:
if (ntokens >= 2) {
if (strlen(tokens[1]) >= (size_t)MAXFILENAME) {
@@ -1288,18 +1306,6 @@ getconfig(argc, argv)
}
break;
- case CONFIG_SELECT:
- if (ntokens >= 2) {
- i = atoi(tokens[1]);
- if (i < SELECT_1 || i > SELECT_5)
- syslog(LOG_ERR,
- "invalid selection algorithm %s, line ignored",
- tokens[1]);
- else
- proto_config(PROTO_SELECT, (LONG)i);
- }
- break;
-
case CONFIG_STATSDIR:
if (ntokens >= 2) {
stats_config(STATS_STATSDIR,tokens[1]);
@@ -1414,6 +1420,60 @@ getconfig(argc, argv)
((((ntokens > 2) && !strcmp(tokens[2], "default"))) ? DEF : 0));
}
break;
+
+ case CONFIG_CLIENTLIMIT:
+ if (ntokens < 2)
+ {
+ syslog(LOG_ERR,
+ "no value for clientlimit command - line ignored");
+ }
+ else
+ {
+ U_LONG i;
+ if (!atouint(tokens[1], &i) || !i)
+ {
+ syslog(LOG_ERR,
+ "illegal value for clientlimit command - line ignored");
+ }
+ else
+ {
+ extern U_LONG client_limit;
+ char bp[80];
+
+ sprintf(bp, "client_limit=%d", i);
+ set_sys_var(bp, strlen(bp)+1, RO);
+
+ client_limit = i;
+ }
+ }
+ break;
+
+ case CONFIG_CLIENTPERIOD:
+ if (ntokens < 2)
+ {
+ syslog(LOG_ERR,
+ "no value for clientperiod command - line ignored");
+ }
+ else
+ {
+ U_LONG i;
+ if (!atouint(tokens[1], &i) || i < 64)
+ {
+ syslog(LOG_ERR,
+ "illegal value for clientperiod command - line ignored");
+ }
+ else
+ {
+ extern U_LONG client_limit_period;
+ char bp[80];
+
+ sprintf(bp, "client_limit_period=%d", i);
+ set_sys_var(bp, strlen(bp)+1, RO);
+
+ client_limit_period = i;
+ }
+ }
+ break;
}
}
(void) fclose(fp);
@@ -1643,13 +1703,14 @@ int sig;
* save_resolve - save configuration info into a file for later name resolution
*/
static void
-save_resolve(name, mode, version, minpoll, maxpoll, flags, keyid)
+save_resolve(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
char *name;
int mode;
int version;
int minpoll;
int maxpoll;
int flags;
+ int ttl;
U_LONG keyid;
{
if (res_fp == NULL) {
@@ -1668,8 +1729,8 @@ save_resolve(name, mode, version, minpoll, maxpoll, flags, keyid)
}
#endif
- (void) fprintf(res_fp, "%s %d %d %d %d %d %lu\n", name, mode,
- version, minpoll, maxpoll, flags, keyid);
+ (void) fprintf(res_fp, "%s %d %d %d %d %d %d %lu\n", name, mode,
+ version, minpoll, maxpoll, flags, ttl, keyid);
}
diff --git a/contrib/xntpd/xntpd/ntp_control.c b/contrib/xntpd/xntpd/ntp_control.c
index 1c7849f48820..ef9c37a6751d 100644
--- a/contrib/xntpd/xntpd/ntp_control.c
+++ b/contrib/xntpd/xntpd/ntp_control.c
@@ -264,8 +264,20 @@ static u_char def_clock_var[] = {
/*
* System and processor definitions. These will change for the gizmo board.
*/
+#ifndef HAVE_UNAME
+#ifndef STR_SYSTEM
+#define STR_SYSTEM "UNIX"
+#endif
+#ifndef STR_PROCESSOR
+#define STR_PROCESSOR "unknown"
+#endif
+
+static char str_system[] = STR_SYSTEM;
+static char str_processor[] = STR_PROCESSOR;
+#else
#include <sys/utsname.h>
static struct utsname utsname;
+#endif /* HAVE_UNAME */
/*
* Trap structures. We only allow a few of these, and send
@@ -294,7 +306,7 @@ static struct utsname utsname;
static u_char clocktypes[] = {
CTL_SST_TS_NTP, /* REFCLK_NONE */
CTL_SST_TS_UNSPEC, /* REFCLK_LOCALCLOCK */
- CTL_SST_TS_HF, /* REFCLK_WWV_HEATH */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_TRAK */
CTL_SST_TS_HF, /* REFCLK_WWV_PST */
CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM */
CTL_SST_TS_UHF, /* REFCLK_GOES_TRUETIME */
@@ -379,6 +391,7 @@ extern struct peer *sys_peer;
extern l_fp last_offset;
extern s_fp drift_comp;
extern int time_constant;
+extern int pll_control;
/*
* Imported from the leap module
*/
@@ -426,7 +439,9 @@ init_control()
{
int i;
+#ifdef HAVE_UNAME
uname(&utsname);
+#endif /* HAVE_UNAME */
ctl_clr_stats();
@@ -716,10 +731,12 @@ ctlsysstatus()
if (sys_peer != 0)
if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC)
clock = sys_peer->sstclktype;
- else
+ else {
if (sys_peer->refclktype < sizeof(clocktypes))
clock = clocktypes[sys_peer->refclktype];
-
+ if (pps_control)
+ clock |= CTL_SST_TS_PPS;
+ }
return (u_short)CTL_SYS_STATUS(sys_leap, clock,
ctl_sys_num_events, ctl_sys_last_event);
}
@@ -1262,12 +1279,22 @@ ctl_putsys(varid)
ctl_putuint(sys_var[CS_LEAPWARNING].text, (U_LONG)leap_warning);
break;
case CS_PROCESSOR:
+#ifndef HAVE_UNAME
+ ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
+ sizeof(str_processor) - 1);
+#else
ctl_putstr(sys_var[CS_PROCESSOR].text, utsname.machine,
strlen(utsname.machine));
+#endif /* HAVE_UNAME */
break;
case CS_SYSTEM:
- ctl_putstr(sys_var[CS_SYSTEM].text, utsname.sysname,
+#ifndef HAVE_UNAME
+ ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
+ sizeof(str_system) - 1);
+#else
+ ctl_putstr(sys_var[CS_SYSTEM].text, utsname.sysname,
strlen(utsname.sysname));
+#endif /* HAVE_UNAME */
break;
case CS_KEYID:
ctl_putuint(sys_var[CS_KEYID].text, (U_LONG)0);
diff --git a/contrib/xntpd/xntpd/ntp_intres.c b/contrib/xntpd/xntpd/ntp_intres.c
index 20561e91b82d..5ff4af4d8242 100644
--- a/contrib/xntpd/xntpd/ntp_intres.c
+++ b/contrib/xntpd/xntpd/ntp_intres.c
@@ -48,6 +48,7 @@ struct conf_entry {
#define ce_minpoll ce_config.minpoll
#define ce_maxpoll ce_config.maxpoll
#define ce_flags ce_config.flags
+#define ce_ttl ce_config.ttl
#define ce_keyid ce_config.keyid
/*
@@ -102,8 +103,9 @@ static int resolve_value; /* next value of resolve timer */
#define TOK_MINPOLL 3
#define TOK_MAXPOLL 4
#define TOK_FLAGS 5
-#define TOK_KEYID 6
-#define NUMTOK 7
+#define TOK_TTL 6
+#define TOK_KEYID 7
+#define NUMTOK 8
#define MAXLINESIZE 512
@@ -128,7 +130,7 @@ extern int errno;
static RETSIGTYPE bong P((int));
static void checkparent P((void));
static void removeentry P((struct conf_entry *));
-static void addentry P((char *, int, int, int, int, int, U_LONG));
+static void addentry P((char *, int, int, int, int, int, int, U_LONG));
static int findhostaddr P((struct conf_entry *));
static void openntp P((void));
static int request P((struct conf_peer *));
@@ -279,13 +281,14 @@ removeentry(entry)
* addentry - add an entry to the configuration list
*/
static void
-addentry(name, mode, version, minpoll, maxpoll, flags, keyid)
+addentry(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
char *name;
int mode;
int version;
int minpoll;
int maxpoll;
int flags;
+ int ttl;
U_LONG keyid;
{
register char *cp;
@@ -304,6 +307,7 @@ addentry(name, mode, version, minpoll, maxpoll, flags, keyid)
ce->ce_minpoll = (u_char)minpoll;
ce->ce_maxpoll = (u_char)maxpoll;
ce->ce_flags = (u_char)flags;
+ ce->ce_ttl = (u_char)ttl;
ce->ce_keyid = htonl(keyid);
ce->ce_next = NULL;
@@ -751,7 +755,8 @@ readconf(fp, name)
*/
addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
(int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
- (int)intval[TOK_MAXPOLL], flags, intval[TOK_KEYID]);
+ (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
+ intval[TOK_KEYID]);
}
}
diff --git a/contrib/xntpd/xntpd/ntp_io.c b/contrib/xntpd/xntpd/ntp_io.c
index 614d5c52bde9..551df510dc37 100644
--- a/contrib/xntpd/xntpd/ntp_io.c
+++ b/contrib/xntpd/xntpd/ntp_io.c
@@ -10,6 +10,10 @@
#include <sys/ioctl.h>
#include <sys/time.h>
+#ifdef MCAST
+#include "ntp_in.h"
+#endif /* MCAST */
+
#include "ntpd.h"
#include "ntp_select.h"
#include "ntp_io.h"
@@ -53,7 +57,6 @@
/*
* Block the interrupt, for critical sections.
*/
-
#if defined(HAVE_SIGNALED_IO)
#define BLOCKIO() ((void) block_sigio())
#define UNBLOCKIO() ((void) unblock_sigio())
@@ -228,6 +231,9 @@ create_sockets(port)
inter_list[0].sent = 0;
inter_list[0].notsent = 0;
inter_list[0].flags = INT_BROADCAST;
+#ifdef MCAST
+ inter_list[0].flags |= INT_MULTICAST;
+#endif /* MCAST */
#ifdef USE_STREAMS_DEVICE_FOR_IF_CONFIG
if ((vs = open("/dev/ip", O_RDONLY)) < 0) {
@@ -394,7 +400,7 @@ create_sockets(port)
maxactivefd = 0;
FD_ZERO(&activefds);
-
+
for (i = 0; i < ninterfaces; i++) {
inter_list[i].fd = open_socket(&inter_list[i].sin,
inter_list[i].flags & INT_BROADCAST);
@@ -458,23 +464,72 @@ io_setbclient()
}
+#ifdef MCAST
+/*
+ * io_multicast_add() - add multicast group address
+ */
+void
+io_multicast_add(addr)
+ U_LONG addr;
+{
+ int fd = inter_list[0].fd;
+ struct ip_mreq mreq;
+
+ if (!IN_CLASSD(addr))
+ return;
+ /*
+ * enable reception of multicast packets
+ */
+ mreq.imr_multiaddr.s_addr = addr;
+ mreq.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ syslog(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP fails: %m");
+}
+#endif /* MCAST */
+
+
/*
* io_unsetbclient - close the broadcast client sockets
*/
void
io_unsetbclient()
{
- int i;
+ int i;
for (i = 1; i < ninterfaces; i++) {
if (!(inter_list[i].flags & INT_BCASTOPEN))
continue;
close_socket(inter_list[i].bfd);
inter_list[i].flags &= ~INT_BCASTOPEN;
- }
+ }
}
+#ifdef MCAST
+/*
+ * io_multicast_del() - delete multicast group address
+ */
+void
+io_multicast_del(addr)
+ U_LONG addr;
+{
+ int fd = inter_list[0].fd;
+ struct ip_mreq mreq;
+
+ if (!IN_CLASSD(addr))
+ return;
+ /*
+ * disable reception of multicast packets
+ */
+ mreq.imr_multiaddr.s_addr = addr;
+ mreq.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ syslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails: %m");
+}
+#endif /* MCAST */
+
/*
* open_socket - open a socket, returning the file descriptor
@@ -510,7 +565,8 @@ open_socket(addr, bcast)
*/
if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
char buff[160];
- sprintf(buff, "bind() fd %d, family %d, port %d, addr %08x, bcast=%d fails: %%m",
+ sprintf(buff,
+ "bind() fd %d, family %d, port %d, addr %08x, bcast=%d fails: %%m",
fd,
addr->sin_family,
addr->sin_port,
@@ -557,6 +613,19 @@ Need non blocking I/O
syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
}
+#ifdef MCAST
+ /* for the moment we use the bcast option to set multicast ttl */
+
+ if (bcast) {
+ unsigned char mttl = 127;
+
+ /* set the multicast ttl for outgoing packets */
+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ &mttl, sizeof(mttl)) == -1) {
+ syslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m");
+ }
+ }
+#endif /* MCAST */
#ifdef SO_BROADCAST
/* if this interface can support broadcast, set SO_BROADCAST */
@@ -566,7 +635,7 @@ Need non blocking I/O
syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
}
}
-#endif
+#endif /* SO_BROADCAST */
#ifdef DEBUG
if (debug > 1)
@@ -608,7 +677,7 @@ struct interface *
findbcastinter(addr)
struct sockaddr_in *addr;
{
-#ifdef SIOCGIFCONF
+#ifdef SIOCGIFCONF
register int i;
register U_LONG netnum;
@@ -622,7 +691,7 @@ findbcastinter(addr)
== (netnum & NSRCADR(&inter_list[i].mask)))
return &inter_list[i];
}
-#endif
+#endif /* SIOCGIFCONF */
return any_interface;
}
@@ -744,7 +813,7 @@ sendpkt(dest, inter, pkt, len)
#ifdef DEBUG
if (debug)
- printf("sendpkt(%s, %s, %d)\n", ntoa(dest),
+ printf("sendpkt(fd=%d %s, %s, %d)\n", inter->fd, ntoa(dest),
ntoa(&inter->sin), len);
#endif
@@ -902,11 +971,16 @@ again:
}
if (FD_ISSET(fd, &fds)) {
n--;
+
/*
* Get a buffer and read the frame. If we
* haven't got a buffer, or this is received
* on the wild card socket, just dump the packet.
*/
+
+ if (!(free_recvbufs && i == 0 &&
+ inter_list[i].flags & INT_MULTICAST)) {
+
#ifdef UDP_WILDCARD_DELIVERY
/*
* these guys manage to put properly addressed packets into the wildcard queue
@@ -932,6 +1006,7 @@ again:
packets_dropped++;
continue;
}
+ }
rb = freelist;
freelist = rb->next;
@@ -958,7 +1033,7 @@ again:
if (debug)
printf("input_handler: fd=%d length %d\n", fd, rb->recv_length);
#endif
-
+
/*
* Got one. Mark how and when it got here,
* put it on the full list and do bookkeeping.
diff --git a/contrib/xntpd/xntpd/ntp_loopfilter.c b/contrib/xntpd/xntpd/ntp_loopfilter.c
index 6d79c5d52ff4..13cbd61b6741 100644
--- a/contrib/xntpd/xntpd/ntp_loopfilter.c
+++ b/contrib/xntpd/xntpd/ntp_loopfilter.c
@@ -9,9 +9,6 @@
#include "ntpd.h"
#include "ntp_io.h"
-#if defined(KERNEL_PLL)
-#include "ntp_timex.h"
-#endif /* KERNEL_PLL */
#include "ntp_unixtime.h"
#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
@@ -46,11 +43,13 @@
#include "ntp_stdlib.h"
-#ifdef KERNEL_PLL
-#ifndef SYS_ntp_adjtime
-#define SYS_ntp_adjtime NTP_SYSCALL_ADJ
+#ifdef KERNEL_PLL
+#include <sys/timex.h>
+#ifndef NTP_SYSCALLS_LIBC
+#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
+#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
#endif
-#endif /* KERNEL_PLL */
+#endif /* KERNEL_PLL */
/*
* The loop filter is implemented in slavish adherence to the
@@ -95,17 +94,14 @@
#define RSH_DRIFT_TO_FRAC (CLOCK_DSCALE - 16)
#define RSH_DRIFT_TO_ADJ (RSH_DRIFT_TO_FRAC - CLOCK_ADJ)
#define RSH_FRAC_TO_FREQ (CLOCK_FREQ + CLOCK_ADJ - RSH_DRIFT_TO_FRAC)
+#define PPS_MAXAGE 120 /* pps signal timeout (s) */
+#define PPS_MAXUPDATE 600 /* pps update timeout (s) */
/*
- * Imported from the ntp_proto module
+ * Program variables
*/
-extern u_char sys_stratum;
-extern s_fp sys_rootdelay;
-extern u_fp sys_rootdispersion;
-extern s_char sys_precision;
-
l_fp last_offset; /* last adjustment done */
-static LONG clock_adjust; /* clock adjust register (fraction only) */
+static LONG clock_adjust; /* clock adjust (fraction only) */
s_fp drift_comp; /* drift compensation register */
static s_fp max_comp; /* drift limit imposed by max host clock slew */
@@ -114,11 +110,15 @@ static s_fp max_comp; /* drift limit imposed by max host clock slew */
static U_LONG tcadj_time; /* last time-constant adjust time */
U_LONG watchdog_timer; /* watchdog timer, in seconds */
-static int first_adjustment; /* set to 1 if waiting for first adjustment */
+static int first_adjustment; /* 1 if waiting for first adjustment */
static int tc_counter; /* time-constant hold counter */
- int pll_control; /* set nonzero if pll implemented in kernel */
- int pps_control; /* set nonzero if pps signal valid */
+static l_fp pps_offset; /* filtered pps offset */
+static u_fp pps_dispersion; /* pps dispersion */
+static U_LONG pps_time; /* last pps sample time */
+
+ int pps_control; /* true if working pps signal */
+ int pll_control; /* true if working kernel pll */
static l_fp pps_delay; /* pps tuning offset */
U_LONG pps_update; /* last pps update time */
int fdpps = -1; /* pps file descriptor */
@@ -154,29 +154,35 @@ static l_fp pps_delay; /* pps tuning offset */
( i == 300 ? B300 : 0 ))))))))
#define PPS_BAUD B38400 /* default serial port speed */
-#define PPS_MAXAGE 120 /* seconds after which we disbelieve pps */
-#define PPS_MAXUPDATE 600 /* seconds after which we disbelieve timecode */
+timecode */
#define PPS_DEV "/dev/pps" /* pps port */
#define PPS_FAC 3 /* pps shift (log2 trimmed samples) */
-#define NPPS 12 /* pps filter size (1<<PPS_FAC+2*PPS_TRIM) */
-#define PPS_TRIM 2 /* samples trimmed from median filter */
+#define PPS_TRIM 6 /* samples trimmed from median filter */
+#define NPPS ((1 << PPS_FAC) + 2 * PPS_TRIM) /* pps filter size */
#define PPS_XCPT "\377" /* intercept character */
#if defined(PPSCLK)
static struct refclockio io; /* given to the I/O handler */
static int pps_baud; /* baud rate of PPS line */
#endif /* PPSCLK */
-static l_fp pps_offset; /* filtered pps offset */
-static U_LONG pps_time; /* last pps sample time */
static U_LONG nsamples; /* number of pps samples collected */
static LONG samples[NPPS]; /* median filter for pps samples */
+
+#endif /* PPS || PPSCLK || PPSPPS */
+
+/*
+ * Imported from the ntp_proto module
+ */
+extern u_char sys_stratum;
+extern s_fp sys_rootdelay;
+extern u_fp sys_rootdispersion;
+extern s_char sys_precision;
+
/*
* Imported from ntp_io.c
*/
extern struct interface *loopback_interface;
-#endif /* PPS || PPSCLK || PPSPPS */
-
/*
* Imported from ntpd module
*/
@@ -191,10 +197,16 @@ extern U_LONG current_time; /* like it says, in seconds */
* sys_poll and sys_refskew are set here
*/
extern u_char sys_poll; /* log2 of system poll interval */
+extern u_char sys_leap; /* system leap bits */
extern l_fp sys_refskew; /* accumulated skew since last update */
extern u_fp sys_maxd; /* max dispersion of survivor list */
/*
+ * Imported from leap module
+ */
+extern u_char leapbits; /* sanitized leap bits */
+
+/*
* Function prototypes
*/
#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
@@ -205,9 +217,15 @@ static void pps_receive P((struct recvbuf *));
#endif /* PPS || PPSCLK || PPSPPS */
#if defined(KERNEL_PLL)
+#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
+ MOD_STATUS | MOD_TIMECONST)
extern int sigvec P((int, struct sigvec *, struct sigvec *));
+#ifndef NTP_SYSCALLS_LIBC
+extern int syscall P((int, void *, ...));
+#endif /* no NTP syscalls in libc */
void pll_trap P((void));
+static int pll_status; /* status bits for kernel pll */
static struct sigvec sigsys; /* current sigvec status */
static struct sigvec newsigsys; /* new sigvec status */
#endif /* KERNEL_PLL */
@@ -350,8 +368,8 @@ init_loopfilter()
}
}
#endif /* HAVE_BSD_TTYS */
- fdpps = fd232;
#endif /* HPUXGADGET */
+ fdpps = fd232;
/*
* Insert in device list.
@@ -399,7 +417,7 @@ local_clock(fp_offset, peer)
#ifdef DEBUG
if (debug > 1)
- printf("local_clock(%s, %s)\n", lfptoa(fp_offset, 9),
+ printf("local_clock(%s, %s)\n", lfptoa(fp_offset, 6),
ntoa(&peer->srcadr));
#endif
@@ -432,33 +450,26 @@ local_clock(fp_offset, peer)
last_offset = *fp_offset;
/*
- * If the magnitude of the offset is greater than CLOCK.MAX, step
- * the time and reset the registers.
+ * If the magnitude of the offset is greater than CLOCK.MAX,
+ * step the time and reset the registers.
*/
if (tmp_ui > CLOCK_MAX_I || (tmp_ui == CLOCK_MAX_I
&& (U_LONG)tmp_uf >= (U_LONG)CLOCK_MAX_F)) {
if (watchdog_timer < CLOCK_MINSTEP) {
/* Mustn't step yet, pretend we adjusted. */
-#ifdef SLEWALWAYS
syslog(LOG_INFO,
- "adjust: SLEW dropped (%s offset %s)\n",
- ntoa(&peer->srcadr), lfptoa(fp_offset, 9));
-#else
- syslog(LOG_INFO,
- "adjust: STEP dropped (%s offset %s)\n",
- ntoa(&peer->srcadr), lfptoa(fp_offset, 9));
-#endif
+ "clock correction %s too large (ignored)\n",
+ lfptoa(fp_offset, 6));
return (0);
}
+ syslog(LOG_NOTICE, "clock reset (%s) %s\n",
#ifdef SLEWALWAYS
- syslog(LOG_NOTICE, " ** adjust: SLEW %s offset %s **\n",
- ntoa(&peer->srcadr), lfptoa(fp_offset, 9));
+ "slew",
#else
- syslog(LOG_NOTICE, " ** adjust: STEP %s offset %s **\n",
- ntoa(&peer->srcadr), lfptoa(fp_offset, 9));
+ "step",
#endif
+ lfptoa(fp_offset, 6));
step_systime(fp_offset);
-
clock_adjust = 0;
watchdog_timer = 0;
first_adjustment = 1;
@@ -480,20 +491,24 @@ local_clock(fp_offset, peer)
* The time constant update goes after adjust and skew updates,
* as in appendix G.
*/
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
/*
* If pps samples are valid, update offset, root delay and
- * root dispersion. This may be a dramatic surprise to high-
- * stratum clients, since all of a sudden this server looks
- * like a stratum-1 clock.
+ * root dispersion. Also, set the system stratum to 1, even if
+ * the source of approximate time runs at a higher stratum. This
+ * may be a dramatic surprise to high-stratum clients, since all
+ * of a sudden this server looks like a stratum-1 clock.
*/
if (pps_control) {
last_offset = pps_offset;
+ sys_maxd = pps_dispersion;
sys_stratum = 1;
sys_rootdelay = 0;
- sys_rootdispersion = sys_maxd;
+ offset = LFPTOFP(&pps_offset);
+ if (offset < 0)
+ offset = -offset;
+ sys_rootdispersion = offset + pps_dispersion;
}
-#endif /* PPS || PPSCLK || PPSPPS */
+ offset = last_offset.l_f;
/*
* The pll_control is active when the phase-lock code is
@@ -504,26 +519,56 @@ local_clock(fp_offset, peer)
* know the scaling of the frequency variable (s_fp) is the
* same as the kernel variable (1 << SHIFT_USEC = 16).
*
+ * For kernels with the PPS discipline, the current offset and
+ * dispersion are set from kernel variables to maintain
+ * beauteous displays, but don't do much of anything.
+ *
* In the case of stock kernels the phase-lock loop is
* implemented the hard way and the clock_adjust and drift_comp
* computed as required.
*/
- offset = last_offset.l_f;
if (pll_control) {
#if defined(KERNEL_PLL)
- ntv.mode = ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR |
- ADJ_ESTERROR;
+ memset((char *)&ntv, 0, sizeof ntv);
+ ntv.modes = MOD_BITS;
if (offset >= 0) {
TSFTOTVU(offset, ntv.offset);
} else {
TSFTOTVU(-offset, ntv.offset);
ntv.offset = -ntv.offset;
}
- ntv.maxerror = sys_rootdispersion + sys_rootdelay / 2;
- ntv.esterror = sys_rootdispersion;
- ntv.time_constant = time_constant;
+ TSFTOTVU(sys_rootdispersion + sys_rootdelay / 2, ntv.maxerror);
+ TSFTOTVU(sys_rootdispersion, ntv.esterror);
+ ntv.status = pll_status;
+ if (pps_update)
+ ntv.status |= STA_PPSTIME;
+ if (sys_leap & LEAP_ADDSECOND &&
+ sys_leap & LEAP_DELSECOND)
+ ntv.status |= STA_UNSYNC;
+ else if (sys_leap & LEAP_ADDSECOND)
+ ntv.status |= STA_INS;
+ else if (sys_leap & LEAP_DELSECOND)
+ ntv.status |= STA_DEL;
+ ntv.constant = time_constant;
(void)ntp_adjtime(&ntv);
- drift_comp = ntv.frequency;
+ drift_comp = ntv.freq;
+ if (ntv.status & STA_PPSTIME && ntv.status & STA_PPSSIGNAL
+ && ntv.shift) {
+ if (ntv.offset >= 0) {
+ TVUTOTSF(ntv.offset, offset);
+ } else {
+ TVUTOTSF(-ntv.offset, offset);
+ offset = -offset;
+ }
+ pps_offset.l_i = pps_offset.l_f = 0;
+ M_ADDF(pps_offset.l_i, pps_offset.l_f, offset);
+ TVUTOTSF(ntv.jitter, tmp);
+ pps_dispersion = (tmp >> 16) & 0xffff;
+ pps_time = current_time;
+ record_peer_stats(&loopback_interface->sin,
+ ctlsysstatus(), &pps_offset, 0, pps_dispersion);
+ } else
+ pps_time = 0;
#endif /* KERNEL_PLL */
} else {
if (offset < 0) {
@@ -533,21 +578,14 @@ local_clock(fp_offset, peer)
}
/*
- * Calculate the new frequency error. The factor given in the
- * spec gives the adjustment per 2**CLOCK_ADJ seconds, but we
- * want it as a (scaled) pure ratio, so we include that factor
- * now and remove it later.
+ * Calculate the new frequency error. The factor given
+ * in the spec gives the adjustment per 2**CLOCK_ADJ
+ * seconds, but we want it as a (scaled) pure ratio, so
+ * we include that factor now and remove it later.
*/
if (first_adjustment) {
first_adjustment = 0;
} else {
- /*
- * Clamp the integration interval to maxpoll.
- * The bitcounting in Section 5 gives (n+1)-6 for 2**n,
- * but has a factor 2**6 missing from CLOCK_FREQ.
- * We make 2**n give n instead. If watchdog_timer is
- * zero, pretend it's one.
- */
tmp = peer->maxpoll;
tmp_uf = watchdog_timer;
if (tmp_uf == 0)
@@ -558,10 +596,11 @@ local_clock(fp_offset, peer)
}
/*
- * We apply the frequency scaling at the same time as
- * the sample interval; this ensures a safe right-shift.
- * (as long as it keeps below 31 bits, which current
- * parameters should ensure.
+ * We apply the frequency scaling at the same
+ * time as the sample interval; this ensures a
+ * safe right-shift. (as long as it keeps below
+ * 31 bits, which current parameters should
+ * ensure.
*/
tmp = (RSH_FRAC_TO_FREQ - tmp) +
time_constant + time_constant;
@@ -581,7 +620,9 @@ local_clock(fp_offset, peer)
/*
* Determine when to adjust the time constant and poll interval.
*/
- if (current_time - tcadj_time >= (1 << sys_poll)) {
+ if (pps_control)
+ time_constant = 0;
+ else if (current_time - tcadj_time >= (1 << sys_poll) && !pps_control) {
tcadj_time = current_time;
tmp = offset;
if (tmp < 0)
@@ -607,8 +648,8 @@ local_clock(fp_offset, peer)
#ifdef DEBUG
if (debug > 1)
printf("adj %s, drft %s, tau %3i\n",
- mfptoa((clock_adjust<0?-1:0), clock_adjust, 9),
- fptoa(drift_comp, 9), time_constant);
+ mfptoa((clock_adjust<0?-1:0), clock_adjust, 6),
+ fptoa(drift_comp, 6), time_constant);
#endif /* DEBUG */
(void) record_loop_stats(&last_offset, &drift_comp, time_constant);
@@ -662,20 +703,20 @@ adj_host_clock()
}
}
#endif /* PPSPPS */
- if (pps_time != 0 && current_time - pps_time > PPS_MAXAGE)
- pps_time = 0;
- if (pps_update != 0 && current_time - pps_update > PPS_MAXUPDATE)
- pps_update = 0;
- if (pps_time != 0 && pps_update != 0) {
+#endif /* PPS || PPSCLK || PPSPPS */
+ if (pps_time && current_time - pps_time > PPS_MAXAGE)
+ pps_time = 0;
+ if (pps_update && current_time - pps_update > PPS_MAXUPDATE)
+ pps_update = 0;
+ if (pps_time && pps_update) {
if (!pps_control)
- syslog(LOG_INFO, "pps synch");
+ syslog(LOG_INFO, "PPS synch");
pps_control = 1;
} else {
if (pps_control)
- syslog(LOG_INFO, "pps synch lost");
+ syslog(LOG_INFO, "PPS synch lost");
pps_control = 0;
}
-#endif /* PPS || PPSCLK || PPSPPS */
/*
* Resist the following code if the phase-lock loop has been
@@ -722,22 +763,27 @@ loop_config(item, lfp_value, int_value)
tmp = LFPTOFP(lfp_value);
if (tmp >= max_comp || tmp <= -max_comp) {
syslog(LOG_ERR,
- "loop_config: skew compensation %s too large",
+ "loop_config: frequency offset %s in ntp.conf file is too large",
fptoa(tmp, 5));
} else {
drift_comp = tmp;
#if defined(KERNEL_PLL)
/*
- * If the phase-lock code is implemented in the kernel,
- * give the time_constant and saved frequency offset
- * to the kernel. If not, no harm is done.
+ * If the phase-lock code is implemented in the
+ * kernel, give the time_constant and saved
+ * frequency offset to the kernel. If not, no
+ * harm is done.
*/
pll_control = 1;
- ntv.mode = ADJ_FREQUENCY | ADJ_STATUS | ADJ_TIMECONST;
- ntv.status = TIME_BAD;
- ntv.time_constant = time_constant;
- ntv.frequency = drift_comp;
+ pll_status = STA_PLL | STA_PPSFREQ;
+ ntv.modes = MOD_BITS | MOD_FREQUENCY;
+ ntv.offset = 0;
+ ntv.freq = drift_comp;
+ ntv.maxerror = NTP_MAXDISPERSE;
+ ntv.esterror = NTP_MAXDISPERSE;
+ ntv.status = pll_status | STA_UNSYNC;
+ ntv.constant = time_constant;
newsigsys.sv_handler = pll_trap;
newsigsys.sv_mask = 0;
newsigsys.sv_flags = 0;
@@ -748,13 +794,13 @@ loop_config(item, lfp_value, int_value)
if ((sigvec(SIGSYS, &sigsys, (struct sigvec *)NULL)))
syslog(LOG_ERR,
"sigvec() fails to restore SIGSYS trap: %m\n");
- syslog(LOG_NOTICE,
- "%susing kernel phase-lock loop",
- (pll_control) ? "" : "Not ");
-#if DEBUG
- if (debug)
- printf("pll_control %d\n", pll_control);
-#endif
+ if (pll_control)
+ syslog(LOG_NOTICE,
+ "using kernel phase-lock loop %04x",
+ ntv.status);
+ else
+ syslog(LOG_NOTICE,
+ "using xntpd phase-lock loop");
#endif /* KERNEL_PLL */
}
@@ -812,7 +858,7 @@ loop_config(item, lfp_value, int_value)
* _trap - trap processor for undefined syscalls
*
* This nugget is called by the kernel when the SYS_ntp_adjtime()
- * syscall bombs because the silly thing has not been implemented int
+ * syscall bombs because the silly thing has not been implemented in
* the kernel. In this case the phase-lock loop is emulated by
* the stock adjtime() syscall and a lot of indelicate abuse.
*/
@@ -873,12 +919,14 @@ int pps_sample(tsr)
int i, j; /* temp ints */
LONG sort[NPPS]; /* temp array for sorting */
l_fp lftemp, ts; /* l_fp temps */
+ u_fp utemp; /* u_fp temp */
LONG ltemp; /* long temp */
/*
* Note the seconds offset is already in the low-order timestamp
- * doubleword, so all we have to do is sign-extend and invert it.
- * The resulting offset is believed only if within CLOCK_MAX.
+ * doubleword, so all we have to do is sign-extend and invert
+ * it. The resulting offset is believed only if within
+ * CLOCK_MAX.
*/
ts = *tsr;
lftemp.l_i = lftemp.l_f = 0;
@@ -934,14 +982,14 @@ int pps_sample(tsr)
}
lftemp.l_i = 0;
lftemp.l_f = sort[NPPS-1-PPS_TRIM] - sort[PPS_TRIM];
- sys_maxd = LFPTOFP(&lftemp);
+ pps_dispersion = LFPTOFP(&lftemp);
#ifdef DEBUG
if (debug)
printf("pps_filter: %s %s %s\n", lfptoa(&pps_delay, 6),
lfptoa(&pps_offset, 6), lfptoa(&lftemp, 5));
#endif /* DEBUG */
- record_peer_stats(&loopback_interface->sin, ctlsysstatus(), &pps_offset,
- sys_rootdelay, sys_rootdispersion);
+ record_peer_stats(&loopback_interface->sin, ctlsysstatus(),
+ &pps_offset, 0, pps_dispersion);
return (0);
}
#endif /* PPS || PPSCLK || PPSPPS */
diff --git a/contrib/xntpd/xntpd/ntp_monitor.c b/contrib/xntpd/xntpd/ntp_monitor.c
index 63af8d4d4d97..e2d2eb51adac 100644
--- a/contrib/xntpd/xntpd/ntp_monitor.c
+++ b/contrib/xntpd/xntpd/ntp_monitor.c
@@ -58,7 +58,7 @@
static struct mon_data *mon_hash; /* Pointer to array of hash buckets */
static int *mon_hash_count; /* Point to hash count stats keeper */
struct mon_data mon_mru_list;
-
+ struct mon_data mon_fifo_list;
/*
* List of free structures structures, and counters of free and total
* structures. The free structures are linked with the hash_next field.
@@ -93,7 +93,7 @@ init_mon()
* Don't do much of anything here. We don't allocate memory
* until someone explicitly starts us.
*/
- mon_enabled = 0;
+ mon_enabled = MON_OFF;
mon_have_memory = 0;
mon_free_mem = 0;
@@ -103,6 +103,7 @@ init_mon()
mon_hash = 0;
mon_hash_count = 0;
memset((char *)&mon_mru_list, 0, sizeof mon_mru_list);
+ memset((char *)&mon_fifo_list, 0, sizeof mon_fifo_list);
}
@@ -110,13 +111,18 @@ init_mon()
* mon_start - start up the monitoring software
*/
void
-mon_start()
+mon_start(mode)
+ int mode;
{
register struct mon_data *md;
register int i;
- if (mon_enabled)
+ if (mon_enabled != MON_OFF) {
+ mon_enabled |= mode;
return;
+ }
+ if (mode == MON_OFF)
+ return; /* Ooops.. */
if (!mon_have_memory) {
mon_hash = (struct mon_data *)
@@ -142,7 +148,10 @@ mon_start()
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
- mon_enabled = 1;
+ mon_fifo_list.fifo_next = &mon_fifo_list;
+ mon_fifo_list.fifo_prev = &mon_fifo_list;
+
+ mon_enabled = mode;
}
@@ -150,12 +159,19 @@ mon_start()
* mon_stop - stop the monitoring software
*/
void
-mon_stop()
+mon_stop(mode)
+ int mode;
{
register struct mon_data *md;
register int i;
- if (!mon_enabled)
+ if (mon_enabled == MON_OFF)
+ return;
+ if ((mon_enabled & mode) == 0 || mode == MON_OFF)
+ return;
+
+ mon_enabled &= ~mode;
+ if (mon_enabled != MON_OFF)
return;
/*
@@ -176,7 +192,8 @@ mon_stop()
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
- mon_enabled = 0;
+ mon_fifo_list.fifo_next = &mon_fifo_list;
+ mon_fifo_list.fifo_prev = &mon_fifo_list;
}
@@ -194,7 +211,7 @@ monitor(rbufp)
register int mode;
register struct mon_data *mdhash;
- if (!mon_enabled)
+ if (mon_enabled == MON_OFF)
return;
pkt = &rbufp->recv_pkt;
@@ -220,6 +237,7 @@ monitor(rbufp)
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
+
return;
}
md = md->hash_next;
@@ -240,6 +258,12 @@ monitor(rbufp)
md->hash_next->hash_prev = md->hash_prev;
md->hash_prev->hash_next = md->hash_next;
*(mon_hash_count + MON_HASH(md->rmtadr)) -= 1;
+ /*
+ * Get it from FIFO list
+ */
+ md->fifo_prev->fifo_next = md->fifo_next;
+ md->fifo_next->fifo_prev = md->fifo_prev;
+
} else {
if (mon_free_mem == 0)
mon_getmoremem();
@@ -252,6 +276,7 @@ monitor(rbufp)
* Got one, initialize it
*/
md->lasttime = md->firsttime = current_time;
+ md->lastdrop = 0;
md->count = 1;
md->rmtadr = netnum;
md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
@@ -260,7 +285,8 @@ monitor(rbufp)
/*
* Shuffle him into the hash table, inserting him at the
- * end. Also put him on top of the MRU list.
+ * end. Also put him on top of the MRU list
+ * and at bottom of FIFO list
*/
mdhash = mon_hash + MON_HASH(netnum);
md->hash_next = mdhash;
@@ -273,6 +299,11 @@ monitor(rbufp)
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
+
+ md->fifo_prev = mon_fifo_list.fifo_prev;
+ md->fifo_next = &mon_fifo_list;
+ mon_fifo_list.fifo_prev->fifo_next = md;
+ mon_fifo_list.fifo_prev = md;
}
diff --git a/contrib/xntpd/xntpd/ntp_peer.c b/contrib/xntpd/xntpd/ntp_peer.c
index cadd415346a9..9d8ec35dee78 100644
--- a/contrib/xntpd/xntpd/ntp_peer.c
+++ b/contrib/xntpd/xntpd/ntp_peer.c
@@ -340,22 +340,24 @@ unpeer(peer_to_remove)
* peer_config - configure a new peer
*/
struct peer *
-peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, key, flags)
+peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, flags, ttl, key)
struct sockaddr_in *srcadr;
struct interface *dstadr;
int hmode;
int version;
int minpoll;
int maxpoll;
- U_LONG key;
int flags;
+ int ttl;
+ U_LONG key;
{
register struct peer *peer;
#ifdef DEBUG
if (debug)
- printf("peer_config: addr %s mode %d version %d minpoll %d maxpoll %d key %u\n",
- ntoa(srcadr), hmode, version, minpoll, maxpoll, key);
+ printf("peer_config: addr %s mode %d version %d minpoll %d maxpoll %d flags %d ttl %d key %u\n",
+ ntoa(srcadr), hmode, version, minpoll, maxpoll, flags,
+ ttl, key);
#endif
/*
* See if we have this guy in the tables already. If
@@ -387,6 +389,7 @@ peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, key, flags)
peer->ppoll = peer->minpoll;
peer->flags = ((u_char)(flags|FLAG_CONFIG))
|(peer->flags & (FLAG_REFCLOCK|FLAG_DEFBDELAY));
+ peer->ttl = (u_char)ttl;
peer->keyid = key;
return peer;
}
@@ -395,7 +398,8 @@ peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, key, flags)
* If we're here this guy is unknown to us. Make a new peer
* structure for him.
*/
- peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, key);
+ peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
+ ttl, key);
if (peer != 0)
peer->flags |= (u_char)(flags|FLAG_CONFIG);
return peer;
@@ -406,13 +410,14 @@ peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, key, flags)
* newpeer - initialize a new peer association
*/
struct peer *
-newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, key)
+newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, ttl, key)
struct sockaddr_in *srcadr;
struct interface *dstadr;
int hmode;
int version;
int minpoll;
int maxpoll;
+ int ttl;
U_LONG key;
{
register struct peer *peer;
@@ -454,13 +459,10 @@ newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, key)
peer->maxpoll = (u_char)maxpoll;
peer->hpoll = peer->minpoll;
peer->ppoll = peer->minpoll;
+ peer->ttl = ttl;
peer->keyid = key;
-
- if (hmode == MODE_BCLIENT) {
- peer->estbdelay = sys_bdelay;
- peer->flags |= FLAG_DEFBDELAY;
- }
-
+ peer->estbdelay = sys_bdelay;
+ peer->flags |= FLAG_DEFBDELAY;
peer->leap = LEAP_NOTINSYNC;
peer->precision = DEFPRECISION;
peer->dispersion = NTP_MAXDISPERSE;
diff --git a/contrib/xntpd/xntpd/ntp_proto.c b/contrib/xntpd/xntpd/ntp_proto.c
index 88e95bbf8d13..a3f744eae881 100644
--- a/contrib/xntpd/xntpd/ntp_proto.c
+++ b/contrib/xntpd/xntpd/ntp_proto.c
@@ -25,7 +25,7 @@ l_fp sys_reftime; /* time we were last updated */
l_fp sys_refskew; /* accumulated skew since last update */
struct peer *sys_peer; /* our current peer */
u_char sys_poll; /* log2 of desired system poll interval */
-LONG sys_clock; /* second part of current time */
+extern LONG sys_clock; /* second part of current time - now in systime.c */
LONG sys_lastselect; /* sys_clock at last synch-dist update */
/*
@@ -48,7 +48,7 @@ U_LONG sys_unknownversion; /* don't know version packets */
U_LONG sys_badlength; /* packets with bad length */
U_LONG sys_processed; /* packets processed */
U_LONG sys_badauth; /* packets dropped because of authorization */
-U_LONG sys_wanderhold; /* sys_peer held to prevent wandering */
+U_LONG sys_limitrejected; /* pkts rejected due toclient count per net */
/*
* Imported from ntp_timer.c
@@ -90,7 +90,8 @@ transmit(peer)
struct pkt xpkt; /* packet to send */
U_LONG peer_timer;
- if (peer->hmode != MODE_BCLIENT) {
+ if ((peer->hmode != MODE_BROADCAST && peer->hmode != MODE_BCLIENT) ||
+ (peer->hmode == MODE_BROADCAST && sys_leap != LEAP_NOTINSYNC)) {
U_LONG xkeyid;
/*
@@ -239,17 +240,14 @@ transmit(peer)
/*
* Finally, adjust the hpoll variable for special conditions.
*/
- if (peer->flags & FLAG_SYSPEER && peer->hpoll > sys_poll) {
- /* clamp it */
+ if (peer->hmode == MODE_BCLIENT)
+ peer->hpoll = peer->ppoll;
+ else if (peer->flags & FLAG_SYSPEER &&
+ peer->hpoll > sys_poll)
peer->hpoll = max(peer->minpoll, sys_poll);
- }
- if (peer->hmode == MODE_BROADCAST || peer->hmode == MODE_BCLIENT) {
- /* clamp it */
- peer->hpoll = peer->minpoll;
- }
/*
- * Arrange for our next time out. hpoll will be less than
+ * Arrange for our next timeout. hpoll will be less than
* maxpoll for sure.
*/
if (peer->event_timer.next != 0)
@@ -262,37 +260,6 @@ transmit(peer)
TIMER_ENQUEUE(timerqueue, &peer->event_timer);
}
-#if 0
-static void
-ct_die(after)
-{
- syslog(LOG_ERR, "timers garbled (%s)", after?"after":"before");
- abort();
-}
-
-void
-check_timers(after)
-{
- register int i;
- register struct event *p, *q;
-
- for (i = 0; i < TIMER_NSLOTS; i++) {
- p = &timerqueue[i];
- if (p->event_time != 0)
- ct_die(after);
- do {
- q = p;
- if ((p = p->next) == 0)
- ct_die(after);
- if (p->prev != q)
- ct_die(after);
- } while (p->event_time != 0);
- if (p != &timerqueue[i])
- ct_die(after);
- }
-}
-#endif
-
/*
* receive - Receive Procedure. See section 3.4.2 in the specification.
*/
@@ -373,6 +340,21 @@ receive(rbufp)
return;
/*
+ * See if we only accept limited number of clients
+ * from the net this guy is from.
+ * Note: the flag is determined dynamically within restrictions()
+ */
+ if (restrict & RES_LIMITED) {
+ extern U_LONG client_limit;
+
+ sys_limitrejected++;
+ syslog(LOG_NOTICE,
+ "rejected mode %d request from %s - per net client limit (%d) exceeded",
+ PKT_MODE(pkt->li_vn_mode),
+ ntoa(&rbufp->recv_srcadr), client_limit);
+ return;
+ }
+ /*
* Dump anything with a putrid stratum. These will most likely
* come from someone trying to poll us with ntpdc.
*/
@@ -517,6 +499,9 @@ receive(rbufp)
break;
case MODE_PASSIVE:
+#ifdef MCAST
+ /* process the packet to determine the rt-delay */
+#endif /* MCAST */
case MODE_SERVER:
/*
* These are obvious errors. Ignore.
@@ -534,8 +519,10 @@ receive(rbufp)
/*
* Sort of a repeat of the above...
*/
+/*
if ((restrict & RES_NOPEER) || !sys_bclient)
return;
+*/
mymode = MODE_BCLIENT;
break;
}
@@ -546,7 +533,7 @@ receive(rbufp)
*/
peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, mymode,
PKT_VERSION(pkt->li_vn_mode), NTP_MINDPOLL,
- NTP_MAXPOLL, hiskeyid);
+ NTP_MAXPOLL, 0, hiskeyid);
if (peer == 0) {
/*
* The only way this can happen is if the
@@ -706,12 +693,11 @@ receive(rbufp)
* out to be bad.
*/
peer2 = newpeer(&rbufp->recv_srcadr,
- rbufp->dstadr, MODE_PASSIVE,
- PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXPOLL,
- hiskeyid);
+ rbufp->dstadr, MODE_PASSIVE,
+ PKT_VERSION(pkt->li_vn_mode),
+ NTP_MINDPOLL, NTP_MAXPOLL, 0, hiskeyid);
if (process_packet(peer2, pkt, &rbufp->recv_time,
- has_mac, trustable) == 0) {
+ has_mac, trustable) == 0) {
/*
* Strange situation. We've been receiving
* broadcasts from him which we liked, but
@@ -769,20 +755,21 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
sys_processed++;
peer->processed++;
-
- peer->rec = *recv_ts;
p_dist = NTOHS_FP(pkt->rootdelay);
p_disp = NTOHS_FP(pkt->rootdispersion);
NTOHL_FP(&pkt->rec, &p_rec);
NTOHL_FP(&pkt->xmt, &p_xmt);
- NTOHL_FP(&pkt->org, &p_org);
+ if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST)
+ NTOHL_FP(&pkt->org, &p_org);
+ else
+ p_org = peer->rec;
+ peer->rec = *recv_ts;
peer->flash = 0;
randomize = POLL_RANDOMCHANGE;
/*
* Test for old or duplicate packets (tests 1 through 3).
*/
-
if (L_ISHIS(&peer->org, &p_xmt)) /* count old packets */
peer->oldpkt++;
if (L_ISEQU(&peer->org, &p_xmt)) /* test 1 */
@@ -796,6 +783,9 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
if ((p_rec.l_ui == 0 && p_rec.l_uf == 0) ||
(p_org.l_ui == 0 && p_org.l_uf == 0))
peer->flash |= TEST3; /* unsynchronized */
+ } else {
+ if (p_org.l_ui == 0 && p_org.l_uf == 0)
+ peer->flash |= TEST3; /* unsynchronized */
}
peer->org = p_xmt; /* reuse byte-swapped pkt->xmt */
peer->ppoll = pkt->ppoll;
@@ -901,39 +891,23 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
ci.l_ui = t10_ui;
ci.l_uf = t10_uf;
ei = (FP_SECOND >> (-(int)sys_precision));
- if (peer->hmode == MODE_BCLIENT) {
-#ifdef notdef
- if (PKT_MODE(pkt->li_vn_mode) == MODE_CLIENT) {
- /*
- * A client mode packet, used for delay computation.
- * Give the data to the filter.
- */
- bdelay_filter(peer, t23_ui, t23_uf, t10_ui, t10_uf);
- }
-#endif
- M_ADDUF(ci.l_ui, ci.l_uf, peer->estbdelay>>1);
+
+ /*
+ * If broadcast mode, time of last reception has been fiddled
+ * to p_org, rather than originate timestamp. We use this to
+ * augment dispersion and previously calcuated estbdelay as
+ * the delay. We know NTP_SKEWFACTOR == 16, which accounts for
+ * the simplified ei calculation.
+ */
+ if (PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST) {
+ M_ADDUF(ci.l_ui, ci.l_uf, peer->estbdelay >> 1);
di = MFPTOFP(0, peer->estbdelay);
+ ei += peer->rec.l_ui - p_org.l_ui;
} else {
M_ADD(ci.l_ui, ci.l_uf, t23_ui, t23_uf);
M_RSHIFT(ci.l_i, ci.l_uf);
-
- /*
- * Calculate di in t23 in full precision, then truncate
- * to an s_fp.
- */
M_SUB(t23_ui, t23_uf, t10_ui, t10_uf);
di = MFPTOFP(t23_ui, t23_uf);
- /*
- * Calculate (t3 - t0) in t23 in full precision, convert
- * to single, shift down by MAXSKEW and add to ei.
- * We know NTP_SKEWFACTOR == 16
- */
-#if 0
- t23_ui = peer->rec.l_ui; /* peer->rec == t0 */
- t23_uf = peer->rec.l_uf;
- M_SUB(t23_ui, t23_uf, p_org.l_ui, p_org.l_uf); /*pkt->org==t3*/
- ei += (MFPTOFP(t23_ui, t23_uf) >> NTP_SKEWFACTOR);
-#endif
ei += peer->rec.l_ui - p_org.l_ui;
}
#ifdef DEBUG
@@ -1057,9 +1031,7 @@ clock_update(peer)
if (d < 0)
d = -d;
sys_rootdelay = peer->rootdelay + d;
- sys_maxd = peer->dispersion;
- if (peer->flags & FLAG_PREFER)
- sys_maxd += peer->selectdisp;
+ sys_maxd = peer->dispersion + peer->selectdisp;
d = peer->soffset;
if (d < 0)
d = -d;
@@ -1155,7 +1127,7 @@ poll_update(peer, new_hpoll, randomize)
* Catch reference clocks here. The polling interval for a
* reference clock is fixed and needn't be maintained by us.
*/
- if (peer->flags & FLAG_REFCLOCK)
+ if (peer->flags & FLAG_REFCLOCK || peer->hmode == MODE_BROADCAST)
return;
/*
@@ -1177,7 +1149,9 @@ poll_update(peer, new_hpoll, randomize)
* less that peer.timer, update peer.timer.
*/
oldpoll = peer->hpoll;
- if ((peer->flags & FLAG_SYSPEER) && new_hpoll > sys_poll)
+ if (peer->hmode == MODE_BCLIENT)
+ peer->hpoll = peer->ppoll;
+ else if ((peer->flags & FLAG_SYSPEER) && new_hpoll > sys_poll)
peer->hpoll = max(peer->minpoll, sys_poll);
else {
if (new_hpoll > peer->maxpoll)
@@ -1192,10 +1166,10 @@ poll_update(peer, new_hpoll, randomize)
newpoll = max((u_char)min(peer->ppoll, peer->hpoll), peer->minpoll);
if (randomize == POLL_MAKERANDOM ||
(randomize == POLL_RANDOMCHANGE && newpoll != oldpoll))
- new_timer = (1<<(newpoll - 1))
+ new_timer = (1 << (newpoll - 1))
+ ranp2(newpoll - 1) + current_time;
else
- new_timer = (1<<newpoll) + current_time;
+ new_timer = (1 << newpoll) + current_time;
evp = &(peer->event_timer);
if (evp->next == 0 || evp->event_time > new_timer) {
TIMER_DEQUEUE(evp);
@@ -1342,26 +1316,10 @@ clock_filter(peer, sample_offset, sample_delay, sample_error)
/*
* Find where he goes in, then shift everyone else down
*/
- if (peer->hmode == MODE_BCLIENT) {
- register s_fp *soffsetp;
- /*
- * Sort by offset. The most positive offset
- * should correspond to the minimum delay.
- */
- soffsetp = peer->filter_soffset;
- for (i = 0; i < NTP_SHIFT-1; i++)
- if (errorp[ord[i]] >= NTP_MAXDISPERSE
- || sample_soffset >= soffsetp[ord[i]])
- break;
- } else {
- /*
- * Sort by distance.
- */
- for (i = 0; i < NTP_SHIFT-1; i++)
- if (errorp[ord[i]] >= NTP_MAXDISPERSE
- || sample_distance <= distance[ord[i]])
- break;
- }
+ for (i = 0; i < NTP_SHIFT-1; i++)
+ if (errorp[ord[i]] >= NTP_MAXDISPERSE
+ || sample_distance <= distance[ord[i]])
+ break;
for (j = NTP_SHIFT-1; j > i; j--)
ord[j] = ord[j-1];
@@ -1676,7 +1634,7 @@ clock_select()
if (d < 0)
d = -d;
sdisp += d;
- sdisp = ((sdisp>>1) + sdisp) >> 1;
+ sdisp = ((sdisp >> 1) + sdisp) >> 1;
}
peer_list[i]->selectdisp = sdisp;
if (sdisp > maxd) {
@@ -1729,9 +1687,7 @@ clock_select()
for (i = 1; i < nlist; i++)
if (peer_list[i] == sys_peer)
break;
- if (i < nlist)
- sys_wanderhold++;
- else
+ if (i >= nlist)
sys_peer = peer_list[0];
}
@@ -2064,7 +2020,6 @@ init_proto()
sys_unknownversion = 0;
sys_processed = 0;
sys_badauth = 0;
- sys_wanderhold = 0;
syslog(LOG_NOTICE, "default precision is initialized to 2**%d", sys_precision);
}
@@ -2076,7 +2031,7 @@ init_proto()
void
proto_config(item, value)
int item;
- LONG value;
+ U_LONG value;
{
/*
* Figure out what he wants to change, then do it
@@ -2087,11 +2042,33 @@ proto_config(item, value)
* Turn on/off facility to listen to broadcasts
*/
sys_bclient = (int)value;
- if (sys_bclient)
+ if (value)
io_setbclient();
else
io_unsetbclient();
break;
+
+ case PROTO_MULTICAST_ADD:
+ /*
+ * Add multicast group address
+ */
+ if (!sys_bclient) {
+ sys_bclient = 1;
+ io_setbclient();
+ }
+#ifdef MCAST
+ io_multicast_add(value);
+#endif /* MCAST */
+ break;
+
+ case PROTO_MULTICAST_DEL:
+ /*
+ * Delete multicast group address
+ */
+#ifdef MCAST
+ io_multicast_del(value);
+#endif /* MCAST */
+ break;
case PROTO_PRECISION:
/*
@@ -2104,7 +2081,7 @@ proto_config(item, value)
/*
* Set default broadcast delay
*/
- sys_bdelay = (((U_LONG)value) + 0x00000800) & 0xfffff000;
+ sys_bdelay = ((value) + 0x00000800) & 0xfffff000;
break;
case PROTO_AUTHENTICATE:
@@ -2120,23 +2097,7 @@ proto_config(item, value)
* Provide an authentication delay value. Round it to
* the microsecond. This is crude.
*/
- sys_authdelay = (((U_LONG)value) + 0x00000800) & 0xfffff000;
- break;
-
- case PROTO_MAXSKEW:
- /*
- * Set the maximum skew value
- */
- syslog(LOG_ERR,
- "proto_config: attempt to set maxskew (obsolete)");
- break;
-
- case PROTO_SELECT:
- /*
- * Set the selection algorithm.
- */
- syslog(LOG_ERR,
- "proto_config: attempt to set selection algorithm (obsolete)");
+ sys_authdelay = ((value) + 0x00000800) & 0xfffff000;
break;
default:
@@ -2163,6 +2124,6 @@ proto_clr_stats()
sys_badlength = 0;
sys_processed = 0;
sys_badauth = 0;
- sys_wanderhold = 0;
sys_stattime = current_time;
+ sys_limitrejected = 0;
}
diff --git a/contrib/xntpd/xntpd/ntp_refclock.c b/contrib/xntpd/xntpd/ntp_refclock.c
index 5199a1acbd26..2cb7cc29d9a4 100644
--- a/contrib/xntpd/xntpd/ntp_refclock.c
+++ b/contrib/xntpd/xntpd/ntp_refclock.c
@@ -93,17 +93,6 @@ refclock_newpeer(peer)
peer->stratum = STRATUM_REFCLOCK;
peer->ppoll = peer->minpoll;
peer->hpoll = peer->minpoll;
- peer->maxpoll = peer->minpoll;
-
- /*
- * Check the flags. If the peer is configured in client mode
- * but prefers the broadcast client filter algorithm, change
- * him over.
- */
- if (peer->hmode == MODE_CLIENT
- && refclock_conf[clktype]->clock_flags & REF_FLAG_BCLIENT)
- peer->hmode = MODE_BCLIENT;
-
peer->event_timer.peer = peer;
peer->event_timer.event_handler = refclock_transmit;
@@ -201,20 +190,14 @@ refclock_transmit(peer)
l_fp off;
- if (peer->valid > 0) peer->valid--;
- if (peer->hpoll > peer->minpoll) peer->hpoll--;
+ if (peer->valid > 0)
+ peer->valid--;
off.l_ui = off.l_uf = 0;
clock_filter(peer, &off, 0, NTP_MAXDISPERSE);
if (peer->flags & FLAG_SYSPEER)
- clock_select();
- } else {
- if (peer->valid < NTP_SHIFT) {
- peer->valid++;
- } else {
- if (peer->hpoll < peer->maxpoll)
- peer->hpoll++;
- }
- }
+ clock_select();
+ } else if (peer->valid < NTP_SHIFT)
+ peer->valid++;
/*
* If he wants to be polled, do it.
@@ -313,9 +296,6 @@ refclock_receive(peer, offset, delay, dispersion, reftime, rectime, leap)
case MODE_CLIENT:
peer->pmode = MODE_SERVER;
break;
- case MODE_BCLIENT:
- peer->pmode = MODE_BROADCAST;
- break;
default:
syslog(LOG_ERR, "refclock_receive: internal error, mode = %d",
peer->hmode);
diff --git a/contrib/xntpd/xntpd/ntp_request.c b/contrib/xntpd/xntpd/ntp_request.c
index c19d1925a818..355b13b42b28 100644
--- a/contrib/xntpd/xntpd/ntp_request.c
+++ b/contrib/xntpd/xntpd/ntp_request.c
@@ -16,6 +16,14 @@
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#ifdef KERNEL_PLL
+#include <sys/timex.h>
+#ifndef NTP_SYSCALLS_LIBC
+#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
+#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
+#endif
+#endif /* KERNEL_PLL */
+
/*
* Structure to hold request procedure information
*/
@@ -56,7 +64,7 @@ static void do_conf P((struct sockaddr_in *, struct interface *, struct req_pkt
static void do_unconf P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void set_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void clr_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void setclr_flags P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
+static void setclr_flags P((struct sockaddr_in *, struct interface *, struct req_pkt *, U_LONG));
static void do_monitor P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_nomonitor P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void list_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *));
@@ -83,13 +91,14 @@ static void set_request_keyid P((struct sockaddr_in *, struct interface *, struc
static void set_control_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void get_ctl_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void get_leap_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+#ifdef KERNEL_PLL
+static void get_kernel_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+#endif /* KERNEL_PLL */
#ifdef REFCLOCK
static void get_clock_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void set_clock_fudge P((struct sockaddr_in *, struct interface *, struct req_pkt *));
#endif /* REFCLOCK */
-static void set_maxskew P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void set_precision P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void set_select_code P((struct sockaddr_in *, struct interface *, struct req_pkt *));
#ifdef REFCLOCK
static void get_clkbug_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
#endif /* REFCLOCK */
@@ -134,9 +143,10 @@ static struct req_proc xntp_codes[] = {
{ REQ_CONTROL_KEY, AUTH, sizeof(U_LONG), set_control_keyid },
{ REQ_GET_CTLSTATS, NOAUTH, 0, get_ctl_stats },
{ REQ_GET_LEAPINFO, NOAUTH, 0, get_leap_info },
- { REQ_SET_MAXSKEW, AUTH, sizeof(u_fp), set_maxskew },
{ REQ_SET_PRECISION, AUTH, sizeof(LONG), set_precision },
- { REQ_SET_SELECT_CODE, AUTH, sizeof(U_LONG), set_select_code },
+#ifdef KERNEL_PLL
+ { REQ_GET_KERNEL, NOAUTH, 0, get_kernel_info },
+#endif /* KERNEL_PLL */
#ifdef REFCLOCK
{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(U_LONG), get_clock_info },
{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), set_clock_fudge },
@@ -162,6 +172,10 @@ U_LONG numresppkts; /* number of resp packets sent with data */
U_LONG errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */
/* by the error code */
+#if defined(KERNEL_PLL) && !defined(NTP_SYSCALLS_LIBC)
+extern int syscall P((int, void *, ...));
+#endif /* KERNEL_PLL */
+
/*
* Imported from the I/O module
*/
@@ -178,6 +192,11 @@ extern int debug;
extern U_LONG current_time;
/*
+ * Imported from ntp_loopfilter.c
+ */
+extern int pll_control;
+
+/*
* A hack. To keep the authentication module clear of xntp-ism's, we
* include a time reset variable for its stats here.
*/
@@ -657,6 +676,7 @@ peer_list_sum(srcadr, inter, inpkt)
ips->delay = HTONS_FP(pp->delay);
HTONL_FP(&pp->offset, &ips->offset);
ips->dispersion = HTONS_FP(pp->dispersion);
+
pp = pp->next;
ips = (struct info_peer_summary *)more_pkt();
}
@@ -724,7 +744,9 @@ peer_info (srcadr, inter, inpkt)
ip->valid = pp->valid;
ip->reach = pp->reach;
ip->unreach = pp->unreach;
- ip->trust = 0;
+ ip->flash = pp->flash;
+ ip->estbdelay = htonl(pp->estbdelay);
+ ip->ttl = pp->ttl;
ip->associd = htons(pp->associd);
ip->rootdelay = HTONS_FP(pp->rootdelay);
ip->rootdispersion = HTONS_FP(pp->rootdispersion);
@@ -745,12 +767,10 @@ peer_info (srcadr, inter, inpkt)
if (ip->order[i] >= NTP_SHIFT)
ip->order[i] -= NTP_SHIFT;
}
- ip->delay = HTONS_FP(pp->delay);
HTONL_FP(&pp->offset, &ip->offset);
+ ip->delay = HTONS_FP(pp->delay);
ip->dispersion = HTONS_FP(pp->dispersion);
- for (i = 0; i < NTP_SHIFT; i++)
- ip->bdelay[i] = 0;
- ip->estbdelay = htonl(pp->estbdelay);
+ ip->selectdisp = HTONS_FP(pp->selectdisp);
ip = (struct info_peer *)more_pkt();
}
flush_pkt();
@@ -882,12 +902,8 @@ sys_info(srcadr, inter, inpkt)
is->flags |= INFO_FLAG_BCLIENT;
if (sys_authenticate)
is->flags |= INFO_FLAG_AUTHENABLE;
- is->selection = 0; /* Obsolete */
-
HTONL_UF(sys_bdelay, &is->bdelay);
HTONL_UF(sys_authdelay, &is->authdelay);
- is->maxskew = 0;
-
(void) more_pkt();
flush_pkt();
}
@@ -915,7 +931,7 @@ sys_stats(srcadr, inter, inpkt)
extern U_LONG sys_badlength;
extern U_LONG sys_processed;
extern U_LONG sys_badauth;
- extern U_LONG sys_wanderhold;
+ extern U_LONG sys_limitrejected;
ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_sys_stats));
@@ -929,8 +945,7 @@ sys_stats(srcadr, inter, inpkt)
ss->badlength = htonl(sys_badlength);
ss->processed = htonl(sys_processed);
ss->badauth = htonl(sys_badauth);
- ss->wanderhold = htonl(sys_wanderhold);
-
+ ss->limitrejected = htonl(sys_limitrejected);
(void) more_pkt();
flush_pkt();
}
@@ -1167,7 +1182,7 @@ do_conf(srcadr, inter, inpkt)
/* XXX W2DO? minpoll/maxpoll arguments ??? */
if (peer_config(&peeraddr, (struct interface *)0,
cp->hmode, cp->version, cp->minpoll, cp->maxpoll,
- cp->keyid, fl) == 0) {
+ fl, cp->ttl, cp->keyid) == 0) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
@@ -1252,7 +1267,7 @@ set_sys_flag(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- setclr_flags(srcadr, inter, inpkt, 1);
+ setclr_flags(srcadr, inter, inpkt, (U_LONG)1);
}
@@ -1265,7 +1280,7 @@ clr_sys_flag(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- setclr_flags(srcadr, inter, inpkt, 0);
+ setclr_flags(srcadr, inter, inpkt, (U_LONG)0);
}
@@ -1277,7 +1292,7 @@ setclr_flags(srcadr, inter, inpkt, set)
struct sockaddr_in *srcadr;
struct interface *inter;
struct req_pkt *inpkt;
- int set;
+ U_LONG set;
{
register U_LONG flags;
@@ -1289,15 +1304,20 @@ setclr_flags(srcadr, inter, inpkt, set)
flags = ((struct conf_sys_flags *)inpkt->data)->flags;
if (flags
- & ~(SYS_FLAG_BCLIENT|SYS_FLAG_AUTHENTICATE)) {
+ & ~(SYS_FLAG_BCLIENT | SYS_FLAG_MCLIENT | SYS_FLAG_AUTHENTICATE)) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if (flags & SYS_FLAG_BCLIENT)
- proto_config(PROTO_BROADCLIENT, (LONG)set);
+ proto_config(PROTO_BROADCLIENT, set);
+ if (flags & SYS_FLAG_MCLIENT)
+ if (set)
+ proto_config(PROTO_MULTICAST_ADD, INADDR_NTP);
+ else
+ proto_config(PROTO_MULTICAST_DEL, INADDR_NTP);
if (flags & SYS_FLAG_AUTHENTICATE)
- proto_config(PROTO_AUTHENTICATE, (LONG)set);
+ proto_config(PROTO_AUTHENTICATE, set);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1311,7 +1331,7 @@ do_monitor(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- mon_start();
+ mon_start(MON_ON);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1325,7 +1345,7 @@ do_nomonitor(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- mon_stop();
+ mon_stop(MON_ON);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1497,6 +1517,10 @@ mon_getlist(srcadr, inter, inpkt)
md = md->mru_next) {
im->lasttime = htonl(current_time - md->lasttime);
im->firsttime = htonl(current_time - md->firsttime);
+ if (md->lastdrop)
+ im->lastdrop = htonl(current_time - md->lastdrop);
+ else
+ im->lastdrop = 0;
im->count = htonl(md->count);
im->addr = md->rmtadr;
im->port = md->rmtport;
@@ -2079,6 +2103,57 @@ get_leap_info(srcadr, inter, inpkt)
}
+#ifdef KERNEL_PLL
+/*
+ * get_kernel_info - get kernel pll/pps information
+ */
+static void
+get_kernel_info(srcadr, inter, inpkt)
+ struct sockaddr_in *srcadr;
+ struct interface *inter;
+ struct req_pkt *inpkt;
+{
+ register struct info_kernel *ik;
+ struct timex ntx;
+
+ if (!pll_control)
+ return;
+ memset((char *)&ntx, 0, sizeof(ntx));
+ (void)ntp_adjtime(&ntx);
+
+ ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
+ sizeof(struct info_kernel));
+
+ /*
+ * pll variables
+ */
+ ik->offset = htonl(ntx.offset);
+ ik->freq = htonl(ntx.freq);
+ ik->maxerror = htonl(ntx.maxerror);
+ ik->esterror = htonl(ntx.esterror);
+ ik->status = htons(ntx.status);
+ ik->constant = htonl(ntx.constant);
+ ik->precision = htonl(ntx.precision);
+ ik->tolerance = htonl(ntx.tolerance);
+
+ /*
+ * pps variables
+ */
+ ik->ppsfreq = htonl(ntx.ppsfreq);
+ ik->jitter = htonl(ntx.jitter);
+ ik->shift = htons(ntx.shift);
+ ik->stabil = htonl(ntx.stabil);
+ ik->jitcnt = htonl(ntx.jitcnt);
+ ik->calcnt = htonl(ntx.calcnt);
+ ik->errcnt = htonl(ntx.errcnt);
+ ik->stbcnt = htonl(ntx.stbcnt);
+
+ (void) more_pkt();
+ flush_pkt();
+}
+#endif /* KERNEL_PLL */
+
+
#ifdef REFCLOCK
/*
* get_clock_info - get info about a clock
@@ -2204,29 +2279,6 @@ set_clock_fudge(srcadr, inter, inpkt)
#endif
/*
- * set_maxskew - set the system maxskew parameter
- */
-static void
-set_maxskew(srcadr, inter, inpkt)
- struct sockaddr_in *srcadr;
- struct interface *inter;
- struct req_pkt *inpkt;
-{
- register u_fp maxskew;
-
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- maxskew = NTOHS_FP(*(u_fp *)(inpkt->data));
-
- proto_config(PROTO_MAXSKEW, (LONG)maxskew);
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
* set_precision - set the system precision
*/
static void
@@ -2249,31 +2301,6 @@ set_precision(srcadr, inter, inpkt)
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
-
-/*
- * set_select_code - set a select code to use
- */
-static void
-set_select_code(srcadr, inter, inpkt)
- struct sockaddr_in *srcadr;
- struct interface *inter;
- struct req_pkt *inpkt;
-{
- register U_LONG select_code;
-
- select_code = ntohl(*(U_LONG *)(inpkt->data));
-
- if (INFO_NITEMS(inpkt->err_nitems) > 1 ||
- select_code < SELECT_1 || select_code > SELECT_5) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- proto_config(PROTO_SELECT, (LONG)select_code);
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
#ifdef REFCLOCK
/*
* get_clkbug_info - get debugging info about a clock
diff --git a/contrib/xntpd/xntpd/ntp_restrict.c b/contrib/xntpd/xntpd/ntp_restrict.c
index 51d896806207..43f01f296624 100644
--- a/contrib/xntpd/xntpd/ntp_restrict.c
+++ b/contrib/xntpd/xntpd/ntp_restrict.c
@@ -1,4 +1,4 @@
-/* ntp_restrict.c,v 3.1 1993/07/06 01:11:28 jbj Exp
+/*
* ntp_restrict.c - find out what restrictions this host is running under
*/
#include <stdio.h>
@@ -60,6 +60,21 @@ U_LONG res_not_found;
U_LONG res_timereset;
/*
+ * Parameters of the RES_LIMITED restriction option.
+ * client_limit is the number of hosts allowed per source net
+ * client_limit_period is the number of seconds after which an entry
+ * is no longer considered for client limit determination
+ */
+U_LONG client_limit;
+U_LONG client_limit_period;
+/*
+ * count number of restriction entries referring to RES_LIMITED
+ * controls activation/deactivation of monitoring
+ * (with respect ro RES_LIMITED control)
+ */
+U_LONG res_limited_refcnt;
+
+/*
* Our initial allocation of list entries.
*/
static struct restrictlist resinit[INITRESLIST];
@@ -70,12 +85,18 @@ static struct restrictlist resinit[INITRESLIST];
extern U_LONG current_time;
/*
+ * debug flag
+ */
+extern int debug;
+
+/*
* init_restrict - initialize the restriction data structures
*/
void
init_restrict()
{
register int i;
+ char bp[80];
/*
* Zero the list and put all but one on the free list
@@ -108,6 +129,18 @@ init_restrict()
res_found = 0;
res_not_found = 0;
res_timereset = 0;
+
+ /*
+ * set default values for RES_LIMIT functionality
+ */
+ client_limit = 3;
+ client_limit_period = 3600;
+ res_limited_refcnt = 0;
+
+ sprintf(bp, "client_limit=%d", client_limit);
+ set_sys_var(bp, strlen(bp)+1, RO);
+ sprintf(bp, "client_limit_period=%d", client_limit_period);
+ set_sys_var(bp, strlen(bp)+1, RO);
}
@@ -150,6 +183,120 @@ restrictions(srcadr)
else
res_found++;
+ /*
+ * The following implements limiting the number of clients
+ * accepted from a given network. The notion of "same network"
+ * is determined by the mask and addr fields of the restrict
+ * list entry. The monitor mechanism has to be enabled for
+ * collecting info on current clients.
+ *
+ * The policy is as follows:
+ * - take the list of clients recorded
+ * from the given "network" seen within the last
+ * client_limit_period seconds
+ * - if there are at most client_limit entries:
+ * --> access allowed
+ * - otherwise sort by time first seen
+ * - current client among the first client_limit seen
+ * hosts?
+ * if yes: access allowed
+ * else: eccess denied
+ */
+ if (match->flags & RES_LIMITED) {
+ int lcnt;
+ struct mon_data *md, *this_client;
+ extern int mon_enabled;
+ extern struct mon_data mon_fifo_list, mon_mru_list;
+
+#ifdef DEBUG
+ if (debug > 2)
+ printf("limited clients check: %d clients, period %d seconds, net is 0x%X\n",
+ client_limit, client_limit_period,
+ netof(hostaddr));
+#endif /*DEBUG*/
+ if (mon_enabled == MON_OFF) {
+#ifdef DEBUG
+ if (debug > 4)
+ printf("no limit - monitoring is off\n");
+#endif
+ return (int)(match->flags & ~RES_LIMITED);
+ }
+
+ /*
+ * How nice, MRU list provides our current client as the
+ * first entry in the list.
+ * Monitoring was verified to be active above, thus we
+ * know an entry for our client must exist, or some
+ * brain dead set the memory limit for mon entries to ZERO!!!
+ */
+ this_client = mon_mru_list.mru_next;
+
+ for (md = mon_fifo_list.fifo_next,lcnt = 0;
+ md != &mon_fifo_list;
+ md = md->fifo_next) {
+ if ((current_time - md->lasttime)
+ > client_limit_period) {
+#ifdef DEBUG
+ if (debug > 5)
+ printf("checking: %s: ignore: too old: %d\n",
+ numtoa(md->rmtadr),
+ current_time - md->lasttime);
+#endif
+ continue;
+ }
+ if (md->mode == MODE_BROADCAST ||
+ md->mode == MODE_CONTROL ||
+ md->mode == MODE_PRIVATE) {
+#ifdef DEBUG
+ if (debug > 5)
+ printf("checking: %s: ignore mode %d\n",
+ numtoa(md->rmtadr),
+ md->mode);
+#endif
+ continue;
+ }
+ if (netof(md->rmtadr) !=
+ netof(hostaddr)) {
+#ifdef DEBUG
+ if (debug > 5)
+ printf("checking: %s: different net 0x%X\n",
+ numtoa(md->rmtadr),
+ netof(md->rmtadr));
+#endif
+ continue;
+ }
+ lcnt++;
+ if (lcnt > client_limit ||
+ md->rmtadr == hostaddr) {
+#ifdef DEBUG
+ if (debug > 5)
+ printf("considering %s: found host\n",
+ numtoa(md->rmtadr));
+#endif
+ break;
+ }
+#ifdef DEBUG
+ else {
+ if (debug > 5)
+ printf("considering %s: same net\n",
+ numtoa(md->rmtadr));
+ }
+#endif
+
+ }
+#ifdef DEBUG
+ if (debug > 4)
+ printf("this one is rank %d in list, limit is %d: %s\n",
+ lcnt, client_limit,
+ (lcnt <= client_limit) ? "ALLOW" : "REJECT");
+#endif
+ if (lcnt <= client_limit) {
+ this_client->lastdrop = 0;
+ return (int)(match->flags & ~RES_LIMITED);
+ } else {
+ this_client->lastdrop = current_time;
+ }
+ }
return (int)match->flags;
}
@@ -257,6 +404,10 @@ restrict(op, resaddr, resmask, mflags, flags)
rlprev->next = rl;
restrictcount++;
}
+ if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
+ res_limited_refcnt++;
+ mon_start(MON_RES); /* ensure data gets collected */
+ }
rl->flags |= (u_short)flags;
break;
@@ -265,8 +416,14 @@ restrict(op, resaddr, resmask, mflags, flags)
* Remove some bits from the flags. If we didn't
* find this one, just return.
*/
- if (rl != 0)
+ if (rl != 0) {
+ if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
+ res_limited_refcnt--;
+ if (res_limited_refcnt == 0)
+ mon_stop(MON_RES);
+ }
rl->flags &= (u_short)~flags;
+ }
break;
case RESTRICT_REMOVE:
@@ -280,6 +437,11 @@ restrict(op, resaddr, resmask, mflags, flags)
&& !(rl->mflags & RESM_INTERFACE)) {
rlprev->next = rl->next;
restrictcount--;
+ if (rl->flags & RES_LIMITED) {
+ res_limited_refcnt--;
+ if (res_limited_refcnt == 0)
+ mon_stop(MON_RES);
+ }
memset((char *)rl, 0, sizeof(struct restrictlist));
rl->next = resfree;
diff --git a/contrib/xntpd/xntpd/ntp_unixclock.c b/contrib/xntpd/xntpd/ntp_unixclock.c
index 6b661835dbb7..1950d8c06fb3 100644
--- a/contrib/xntpd/xntpd/ntp_unixclock.c
+++ b/contrib/xntpd/xntpd/ntp_unixclock.c
@@ -251,10 +251,23 @@ clock_parms(tickadj, tick)
* Note that this version grovels about in /dev/kmem to determine
* these values. This probably should be elsewhere.
*/
-
-/* Define the following to be what the tick and tickadj variables are
- * called in your kernel.
+#if defined(SYS_UNIXWARE1)
+/*
+ * clock_parms - return the local clock tickadj and tick parameters
+ *
+ * The values set here were determined experimentally on a 486 system
+ * I'm not confident in them. - RAS
+ *
*/
+static void
+clock_parms(tickadj, tick)
+ U_LONG *tickadj;
+ U_LONG *tick;
+{
+ *tick = 10000; /* microseconds */
+ *tickadj = 80; /* microseconds */
+}
+#else /* SYS_UNIXWARE1 */
#if defined(SYS_AUX3) || defined(SYS_AUX2) || defined(SYS_SVR4) || defined(SYS_PTX)
#define K_TICKADJ_NAME "tickadj"
@@ -373,6 +386,7 @@ clock_parms(tickadj, tick)
#undef K_TICK_NAME
#undef N_NAME
}
+#endif /* SYS_UNIXWARE1 */
#endif /* HAVE_READKMEM */
#if defined(SOLARIS)&&defined(ADJTIME_IS_ACCURATE)
@@ -421,7 +435,6 @@ clock_parms(tickadj, tick)
}
#endif /* sgi */
-
#ifdef NOKMEM
#ifndef HZ
@@ -556,13 +569,18 @@ clock_parms(tickadj, tick)
#endif /* SOLARIS */
#ifdef SYS_LINUX
-/* XXX should look this up somewhere ! */
+#include <sys/timex.h>
static void
clock_parms(tickadj, tick)
U_LONG *tickadj;
U_LONG *tick;
{
- *tickadj = (U_LONG)1;
- *tick = (U_LONG)10000;
+ struct timex txc;
+
+ txc.mode = 0;
+ __adjtimex(&txc);
+
+ *tickadj = (U_LONG)1; /* our adjtime is accurate */
+ *tick = (U_LONG)txc.tick;
}
#endif /* SYS_LINUX */
diff --git a/contrib/xntpd/xntpd/ntpd.c b/contrib/xntpd/xntpd/ntpd.c
index abe86d945151..9ed43c5c4a81 100644
--- a/contrib/xntpd/xntpd/ntpd.c
+++ b/contrib/xntpd/xntpd/ntpd.c
@@ -14,7 +14,7 @@
#include <sys/rtprio.h>
#endif
-#if defined(SYS_SVR4)
+#if defined(SYS_SVR4) || defined (SYS_UNIXWARE1)
#include <termios.h>
#endif
@@ -28,8 +28,12 @@
#include "ntp_stdlib.h"
#ifdef LOCK_PROCESS
+#ifdef SYS_SOLARIS
+#include <sys/mman.h>
+#else
#include <sys/lock.h>
#endif
+#endif
/*
* Signals we catch for debugging. If not debugging we ignore them.
@@ -139,7 +143,7 @@ main(argc, argv)
(void) dup2(0, 1);
(void) dup2(0, 2);
#ifdef NTP_POSIX_SOURCE
-#if defined(SOLARIS) || defined(SYS_PTX) || defined(SYS_AUX3) || defined(SYS_AIX)
+#if defined(SOLARIS) || defined(SYS_PTX) || defined(SYS_AUX3) || defined(SYS_AIX) || defined(SYS_ULTRIX)
(void) setsid();
#else
(void) setpgid(0, 0);
@@ -219,13 +223,23 @@ main(argc, argv)
if (rtprio(0, 120) < 0)
syslog(LOG_ERR, "rtprio() error: %m");
#else
-#if defined(PROCLOCK) && defined(LOCK_PROCESS)
+#if defined(LOCK_PROCESS)
+#if defined(MCL_CURRENT) && defined(MCL_FUTURE)
+ /*
+ * lock the process into memory
+ */
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
+ syslog(LOG_ERR, "mlockall(): %m");
+#else
+#if defined(PROCLOCK)
/*
* lock the process into memory
*/
if (plock(PROCLOCK) < 0)
syslog(LOG_ERR, "plock(): %m");
#endif
+#endif
+#endif
#if defined(NTPD_PRIO) && NTPD_PRIO != 0
/*
* Set the priority.
diff --git a/contrib/xntpd/xntpd/refclock_chu.c b/contrib/xntpd/xntpd/refclock_chu.c
index 1c7c3bfa61c1..4596db22e2f5 100644
--- a/contrib/xntpd/xntpd/refclock_chu.c
+++ b/contrib/xntpd/xntpd/refclock_chu.c
@@ -599,6 +599,25 @@ chu_receive(rbufp)
chu->lastupdate = current_time;
/*
+ * Just for fun, we can debug the whole frame if
+ * we want.
+ */
+
+#ifdef CHU_DEBUG
+ syslog(LOG_DEBUG, "CHU %s packet:", (chuc->chutype == CHU_YEAR)?
+ "year":"time");
+ for (i=0; i < NCHUCHARS; i++) {
+ char c[64];
+
+ sprintf(c,"%c%c %s",hexstring[chuc->codechars[i]&0xf],
+ hexstring[chuc->codechars[i]>>4],
+ ctime(&(chuc->codetimes[i].tv_sec)));
+ c[strlen(c)-1]=0; /* ctime() adds a damn \n */
+ syslog(LOG_DEBUG, "%s .%06d", c, chuc->codetimes[i].tv_usec);
+ }
+#endif
+
+ /*
* At this point we're assured that both halves of the
* data match because of what the kernel has done.
* But there's more than one data format. We need to
diff --git a/contrib/xntpd/xntpd/refclock_conf.c b/contrib/xntpd/xntpd/refclock_conf.c
index 430c4a60f3fa..535ca27e9ebe 100644
--- a/contrib/xntpd/xntpd/refclock_conf.c
+++ b/contrib/xntpd/xntpd/refclock_conf.c
@@ -20,6 +20,12 @@ extern struct refclock refclock_local;
#define refclock_local refclock_none
#endif
+#if defined(TRAK) || defined(TRAKCLK) || defined(TRAKPPS)
+extern struct refclock refclock_trak;
+#else
+#define refclock_trak refclock_none
+#endif
+
#if defined(PST) || defined(PSTCLK) || defined(PSTPPS)
extern struct refclock refclock_pst;
#else
@@ -107,7 +113,7 @@ extern struct refclock refclock_gpstm;
struct refclock *refclock_conf[] = {
&refclock_none, /* 0 REFCLK_NONE */
&refclock_local, /* 1 REFCLK_LOCAL */
- &refclock_none, /* 2 REFCLK_WWV_HEATH */
+ &refclock_trak, /* 2 REFCLK_GPS_TRAK */
&refclock_pst, /* 3 REFCLK_WWV_PST */
&refclock_wwvb, /* 4 REFCLK_WWVB_SPECTRACOM */
&refclock_goes, /* 5 REFCLK_GOES_TRUETIME */
diff --git a/contrib/xntpd/xntpd/refclock_irig.c b/contrib/xntpd/xntpd/refclock_irig.c
index 40345bbefde7..6167af2784ee 100644
--- a/contrib/xntpd/xntpd/refclock_irig.c
+++ b/contrib/xntpd/xntpd/refclock_irig.c
@@ -19,7 +19,7 @@
* This driver supports the IRIG audio decoder. This clever gadget uses
* a modified BSD audio driver for the Sun SPARCstation which provides
* a timestamp, raw binary timecode, status byte and decoded ASCII
- # timecode. The data are represented in the structure:
+ * timecode. The data are represented in the structure:
*
* struct irig_time {
* struct timeval stamp; timestamp
@@ -418,7 +418,9 @@ struct peer *peer;
irig->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
irig->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
irig->second = MULBY10(cp[10] - '0') + cp[11] - '0';
- if (cp[12] != ' ')
+ if (cp[12] = ' ')
+ irig->leap = 0;
+ else
irig->leap = LEAP_NOTINSYNC;
if (irig->day < 1 || irig->day > 366) {
irig->baddata++;
diff --git a/contrib/xntpd/xntpd/refclock_msfees.c b/contrib/xntpd/xntpd/refclock_msfees.c
index b301bc2ebb23..c2a882abb919 100644
--- a/contrib/xntpd/xntpd/refclock_msfees.c
+++ b/contrib/xntpd/xntpd/refclock_msfees.c
@@ -139,7 +139,7 @@
#define INH_DELAY_PPS BITS_TO_L_FP( 0, 9600)
#ifndef STREAM_PP1
-#define STREAM_PP1 "ppsclockd\0<-- patch space for module name1 -->"
+#define STREAM_PP1 "ppsclocd\0<-- patch space for module name1 -->"
#endif
#ifndef STREAM_PP2
#define STREAM_PP2 "ppsclock\0<-- patch space for module name2 -->"
diff --git a/contrib/xntpd/xntpd/refclock_parse.c b/contrib/xntpd/xntpd/refclock_parse.c
index 69e483764354..0d95d18908a5 100644
--- a/contrib/xntpd/xntpd/refclock_parse.c
+++ b/contrib/xntpd/xntpd/refclock_parse.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
/*
- * /src/NTP/REPOSITORY/v3/xntpd/refclock_parse.c,v 3.45 1994/01/25 19:06:27 kardel Exp
+ * /src/NTP/REPOSITORY/v3/xntpd/refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp
*
- * refclock_parse.c,v 3.45 1994/01/25 19:06:27 kardel Exp
+ * refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp
*
* generic reference clock driver for receivers
*
@@ -30,6 +30,8 @@
* PPS - supply loopfilter with PPS samples (if configured)
* PPSPPS - notify loopfilter of PPS file descriptor
*
+ * FREEBSD_CONRAD - Make very cheap "Conrad DCF77 RS-232" gadget work
+ * with FreeBSD.
* TTY defines:
* HAVE_BSD_TTYS - currently unsupported
* HAVE_SYSV_TTYS - will use termio.h
@@ -82,6 +84,9 @@
#include <time.h>
#include <sys/errno.h>
+#ifdef FREEBSD_CONRAD
+#include <sys/ioctl.h>
+#endif
extern int errno;
#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
@@ -129,7 +134,7 @@ CURRENTLY NO BSD TTY SUPPORT
#include "parse.h"
#if !defined(NO_SCCSID) && !defined(lint) && !defined(__GNUC__)
-static char rcsid[]="refclock_parse.c,v 3.45 1994/01/25 19:06:27 kardel Exp";
+static char rcsid[]="refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp";
#endif
/**===========================================================================
@@ -440,7 +445,12 @@ static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
#define RAWDCF_ROOTDELAY 0x00000364 /* 13 ms */
#define RAWDCF_FORMAT "RAW DCF77 Timecode"
#define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */
+
+#ifdef FREEBSD_CONRAD
+#define RAWDCF_CFLAG (CS8|CREAD|CLOCAL)
+#else
#define RAWDCF_CFLAG (B50|CS8|CREAD|CLOCAL)
+#endif
#define RAWDCF_IFLAG 0
#define RAWDCF_OFLAG 0
#define RAWDCF_LFLAG 0
@@ -1482,11 +1492,22 @@ local_receive(rbufp)
struct parseunit *parse = (struct parseunit *)rbufp->recv_srcclock;
register int count;
register char *s;
+#ifdef FREEBSD_CONRAD
+ struct timeval foo;
+#endif
+
/*
* eat all characters, parsing then and feeding complete samples
*/
count = rbufp->recv_length;
s = rbufp->recv_buffer;
+#ifdef FREEBSD_CONRAD
+ ioctl(parse->fd,TIOCTIMESTAMP,&foo);
+ TVTOTS(&foo, &rbufp->recv_time);
+ rbufp->recv_time.l_uf += TS_ROUNDBIT;
+ rbufp->recv_time.l_ui += JAN_1970;
+ rbufp->recv_time.l_uf &= TS_MASK;
+#endif
while (count--)
{
@@ -1653,7 +1674,8 @@ local_poll(parse)
* done if no more characters are available
*/
FD_SET(fd, &fdmask);
- if (select(fd + 1, &fdmask, 0, 0, &null_time) == 0)
+ if ((i == 0) &&
+ (select(fd + 1, &fdmask, 0, 0, &null_time) == 0))
return;
}
}
@@ -1706,7 +1728,8 @@ parsestate(state, buffer)
{ PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
{ PARSEB_DST, "DST" },
{ PARSEB_UTC, "UTC DISPLAY" },
- { PARSEB_LEAP, "LEAP WARNING" },
+ { PARSEB_LEAPADD, "LEAP ADD WARNING" },
+ { PARSEB_LEAPDEL, "LEAP DELETE WARNING" },
{ PARSEB_LEAPSECOND, "LEAP SECOND" },
{ PARSEB_ALTERNATE,"ALTERNATE ANTENNA" },
{ PARSEB_TIMECODE, "TIME CODE" },
@@ -2269,7 +2292,10 @@ parse_start(sysunit, peer)
tm.c_iflag = clockinfo[type].cl_iflag;
tm.c_oflag = clockinfo[type].cl_oflag;
tm.c_lflag = clockinfo[type].cl_lflag;
-
+#ifdef FREEBSD_CONRAD
+ tm.c_ispeed = 50;
+ tm.c_ospeed = 50;
+#endif
if (TTY_SETATTR(fd232, &tm) == -1)
{
syslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tm): %m", unit, fd232);
@@ -2312,6 +2338,21 @@ parse_start(sysunit, peer)
return 0; /* well, ok - special initialisation broke */
}
+#ifdef FREEBSD_CONRAD
+ {
+ int i,j;
+ struct timeval tv;
+ ioctl(parse->fd,TIOCTIMESTAMP,&tv);
+ j = TIOCM_RTS;
+ i = ioctl(fd232, TIOCMBIC, &j);
+ if (i < 0) {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: lowrts_poll: failed to lower RTS: %m",
+ CL_UNIT(parse->unit));
+ }
+ }
+#endif
+
strcpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format);
tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
@@ -2539,9 +2580,10 @@ static void
parse_leap()
{
/*
- * PARSE does encode a leap warning... we are aware but not afraid of that
- * as long as we get a little help for the direction from the operator until
* PARSE encodes the LEAP correction direction.
+ * For timecodes that do not pass on the leap correction direction
+ * the default PARSEB_LEAPADD must be used. It may then be modified
+ * with a fudge flag (flag2).
*/
}
@@ -2821,7 +2863,7 @@ parse_control(unit, in, out)
sprintf(tt, "refclock_iomode=\"%s\"", parse->binding->bd_description);
tt = add_var(&out->kv_list, 128, RO);
- sprintf(tt, "refclock_driver_version=\"refclock_parse.c,v 3.45 1994/01/25 19:06:27 kardel Exp\"");
+ sprintf(tt, "refclock_driver_version=\"refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp\"");
out->lencode = strlen(outstatus);
out->lastcode = outstatus;
@@ -3100,7 +3142,11 @@ parse_process(parse, parsetime)
L_ADD(&off, &offset);
rectime = off; /* this makes org time and xmt time somewhat artificial */
- if (parse->flags & PARSE_STAT_FILTER)
+ L_SUB(&off, &parsetime->parse_stime.fp);
+
+ if ((parse->flags & PARSE_STAT_FILTER) &&
+ (off.l_i > -60) &&
+ (off.l_i < 60)) /* take usec error only if within +- 60 secs */
{
struct timeval usecerror;
/*
@@ -3112,10 +3158,6 @@ parse_process(parse, parsetime)
sTVTOTS(&usecerror, &off);
L_ADD(&off, &offset);
}
- else
- {
- L_SUB(&off, &parsetime->parse_stime.fp);
- }
}
if (PARSE_PPS(parsetime->parse_state) && CL_PPS(parse->unit))
@@ -3245,14 +3287,24 @@ parse_process(parse, parsetime)
}
else
{
- if (PARSE_LEAP(parsetime->parse_state))
+ if (PARSE_LEAPADD(parsetime->parse_state))
{
+ /*
+ * we pick this state also for time code that pass leap warnings
+ * without direction information (as earth is currently slowing
+ * down).
+ */
leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
}
else
- {
- leap = LEAP_NOWARNING;
- }
+ if (PARSE_LEAPDEL(parsetime->parse_state))
+ {
+ leap = LEAP_DELSECOND;
+ }
+ else
+ {
+ leap = LEAP_NOWARNING;
+ }
}
refclock_receive(parse->peer, &off, 0, LFPTOFP(&dispersion), &reftime, &rectime, leap);
@@ -3396,6 +3448,21 @@ trimble_init(parse)
* History:
*
* refclock_parse.c,v
+ * Revision 3.53 1994/03/25 13:07:39 kardel
+ * fixed offset calculation for large (>4 Min) offsets
+ *
+ * Revision 3.52 1994/03/03 09:58:00 kardel
+ * stick -kv in cvs is no fun
+ *
+ * Revision 3.49 1994/02/20 13:26:00 kardel
+ * rcs id cleanup
+ *
+ * Revision 3.48 1994/02/20 13:04:56 kardel
+ * parse add/delete second support
+ *
+ * Revision 3.47 1994/02/02 17:44:30 kardel
+ * rcs ids fixed
+ *
* Revision 3.45 1994/01/25 19:06:27 kardel
* 94/01/23 reconcilation
*
diff --git a/contrib/xntpd/xntpd/refclock_trak.c b/contrib/xntpd/xntpd/refclock_trak.c
new file mode 100644
index 000000000000..f2b3eb11fc9d
--- /dev/null
+++ b/contrib/xntpd/xntpd/refclock_trak.c
@@ -0,0 +1,1006 @@
+/*
+ * refclock_trak.c - clock driver for the TRAK 8810 GPS STATION CLOCK
+ * Tsuruoka Tomoaki Oct 30, 1993
+ * tsuruoka@nc.fukuoka-u.ac.jp
+ * Faculty of Engineering,
+ * Fukuoka University, Fukuoka, JAPAN
+ */
+#if defined(REFCLOCK) && (defined(TRAK) || defined(TRAKCLK) || defined(TRAKPPS))
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+
+static void gps_send();
+
+#if defined(HAVE_BSD_TTYS)
+#include <sgtty.h>
+#endif /* HAVE_BSD_TTYS */
+
+#if defined(HAVE_SYSV_TTYS)
+#include <termio.h>
+#endif /* HAVE_SYSV_TTYS */
+
+#if defined(STREAM)
+#include <termios.h>
+#include <stropts.h>
+#if defined(TRAKCLK)
+#include <sys/clkdefs.h>
+#endif /* TRAKCLK */
+#endif /* STREAM */
+
+#if defined (TRAKPPS)
+#include <sys/ppsclock.h>
+#endif /* TRAKPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the TRAK 8810 GPS Receiver with
+ * Buffered RS-232-C Interface Module.
+ *
+ * Most of codes are copied from refclock_as2201.c, Thanks a lot.
+ *
+ * The program expects the radio responses once per seccond
+ * ( by "rqts,u" command or panel control )
+ * of the form "*RQTS U,ddd:hh:mm:ss.0,Q\r\n for UTC" where
+ * ddd= day of year
+ * hh= hours
+ * mm= minutes
+ * ss= seconds
+ * Q= Quality byte. Q=0 Phase error > 20 us
+ * Q=6 Pahse error < 20 us
+ * > 10 us
+ * Q=5 Pahse error < 10 us
+ * > 1 us
+ * Q=4 Pahse error < 1 us
+ * > 100 ns
+ * Q=3 Pahse error < 100 ns
+ * > 10 ns
+ * Q=2 Pahse error < 10 ns
+ * (note that my clock almost stable at 1 us per 10 hours)
+ *
+ * Request leap second status - if needed.
+ * send: rqls\n
+ * reply: RQLS yy,mm,dd
+ * where: yy is year
+ * mm is month
+ * dd is day of month.baud
+ * Note: Default data is all zeros
+ * i.e. RQLS 00,00,00
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* max number of GPS units */
+#define GPS232 "/dev/gps%d" /* name of radio device */
+#define SPEED232 B9600 /* uart speed (9600 bps) */
+
+/*
+ * Radio interface parameters
+ */
+#define GPSPRECISION (-20) /* precision assumed (about 1 us) */
+#define GPSREFID "GPS" /* reference id */
+#define GPSDESCRIPTION "TRAK 8810 GPS station clock" /* who we are */
+#define GPSHSREFID 0x7f7f020a /* 127.127.2.10 refid hi strata */
+#define GMT 0 /* hour offset from Greenwich */
+#define NCODES 3 /* stages of median filter */
+#define LENTOC 25 /* *RQTS U,ddd:hh:mm:ss.0,Q datecode length */
+#define BMAX 100 /* timecode buffer length */
+#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
+
+/*
+ * Hack to avoid excercising the multiplier. I have no pride.
+ */
+#define MULBY10(x) (((x)<<3) + ((x)<<1))
+
+/*
+ * Imported from ntp_timer module
+ */
+extern U_LONG current_time; /* current time (s) */
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * GPS unit control structure.
+ */
+struct gpsunit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp lastrec; /* last data receive time */
+ l_fp lastref; /* last timecode time */
+ l_fp offset[NCODES]; /* recent sample offsets */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short polled; /* when polled, means a last sample */
+ u_char lencode; /* length of last received ASCII string */
+ U_LONG lasttime; /* last time clock heard from */
+#ifdef TRAKPPS
+ U_LONG lastev; /* last ppsclock second */
+#endif /* TRAKPPS */
+ u_char unit; /* unit number for this guy */
+ u_char status; /* clock status */
+ u_char lastevent; /* last clock event */
+ u_char reason; /* reason for last abort */
+ u_char year; /* year of eternity */
+ u_short day; /* day of year */
+ u_char hour; /* hour of day */
+ u_char minute; /* minute of hour */
+ u_char second; /* seconds of minute */
+ u_short msec; /* milliseconds of second */
+ u_char leap; /* leap indicators */
+ U_LONG yearstart; /* start of current year */
+ /*
+ * Status tallies
+ */
+ U_LONG polls; /* polls sent */
+ U_LONG noreply; /* no replies to polls */
+ U_LONG coderecv; /* timecodes received */
+ U_LONG badformat; /* bad format */
+ U_LONG baddata; /* bad data */
+ U_LONG timestarted; /* time we started this */
+};
+
+
+/*
+ * Data space for the unit structures. Note that we allocate these on
+ * the fly, but never give them back.
+ */
+static struct gpsunit *gpsunits[MAXUNITS];
+static u_char unitinuse[MAXUNITS];
+
+/*
+ * Keep the fudge factors separately so they can be set even
+ * when no clock is configured.
+ */
+static l_fp fudgefactor[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char sloppyclockflag[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void trak_init P(());
+static int trak_start P((u_int, struct peer *));
+static void trak_shutdown P((int));
+static void trak_report_event P((struct gpsunit *, int));
+static void trak_receive P((struct recvbuf *));
+static char trak_process P((struct gpsunit *, l_fp *, u_fp *));
+static void trak_poll P((int unit, struct peer *));
+static void trak_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void trak_buginfo P((int, struct refclockbug *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_trak = {
+ trak_start, trak_shutdown, trak_poll,
+ trak_control, trak_init, trak_buginfo, NOFLAGS
+};
+
+/*
+ * trak_init - initialize internal gps driver data
+ */
+static void
+trak_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)gpsunits, 0, sizeof gpsunits);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor[i].l_ui = 0;
+ fudgefactor[i].l_uf = 0;
+ stratumtouse[i] = 0;
+ sloppyclockflag[i] = 0;
+ }
+}
+
+
+/*
+ * trak_start - open the GPS devices and initialize data for processing
+ */
+static int
+trak_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct gpsunit *gps;
+ register int i;
+ int fd232;
+ char trakdev[20];
+#ifdef TRAKPPS
+ struct ppsclockev ev;
+#endif /* TRAKPPS */
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "trak_start: unit %d invalid", unit);
+ return (0);
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "trak_start: unit %d in use", unit);
+ return (0);
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(trakdev, GPS232, unit);
+ fd232 = open(trakdev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "trak_start: open of %s: %m", trakdev);
+ return (0);
+ }
+
+#if defined(HAVE_SYSV_TTYS)
+ /*
+ * System V serial line parameters (termio interface)
+ *
+ */
+ { struct termio ttyb;
+ if (ioctl(fd232, TCGETA, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, TCGETA): %m", trakdev);
+ goto screwed;
+ }
+ ttyb.c_iflag = IGNBRK|IGNPAR|ICRNL;
+ ttyb.c_oflag = 0;
+ ttyb.c_cflag = SPEED232|CS8|CLOCAL|CREAD;
+ ttyb.c_lflag = ICANON;
+ ttyb.c_cc[VERASE] = ttyb.c_cc[VKILL] = '\0';
+ if (ioctl(fd232, TCSETA, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, TCSETA): %m", trakdev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(STREAM)
+ /*
+ * POSIX/STREAMS serial line parameters (termios interface)
+ *
+ * The TRAKCLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The TRAKPPS option provides timestamping at the driver level.
+ * It uses a 1-pps signal and level converter (gadget box) and
+ * requires the ppsclock streams module and SunOS 4.1.1 or
+ * later.
+ */
+ { struct termios ttyb, *ttyp;
+
+ ttyp = &ttyb;
+ if (tcgetattr(fd232, ttyp) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: tcgetattr(%s): %m", trakdev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR;
+ ttyp->c_oflag = 0;
+ ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
+ ttyp->c_lflag = ICANON;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+ if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: tcsetattr(%s): %m", trakdev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: tcflush(%s): %m", trakdev);
+ goto screwed;
+ }
+#if defined(TRAKCLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, I_PUSH, clk): %m", trakdev);
+ if (ioctl(fd232, CLK_SETSTR, "*") < 0)
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, CLK_SETSTR): %m", trakdev);
+#endif /* TRAKCLK */
+#if defined(TRAKPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, I_PUSH, ppsclock): %m", trakdev);
+ else
+ fdpps = fd232;
+#endif /* TRAKPPS */
+ }
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The TRAKCLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(TRAKCLK)
+ int ldisc = CLKLDISC;
+#endif /* TRAKCLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, TIOCGETP): %m", trakdev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(TRAKCLK)
+ ttyb.sg_erase = ttyb.sg_kill = '\r';
+ ttyb.sg_flags = RAW;
+#else
+ ttyb.sg_erase = ttyb.sg_kill = '\0';
+ ttyb.sg_flags = EVENP|ODDP|CRMOD;
+#endif /* TRAKCLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, TIOCSETP): %m", trakdev);
+ goto screwed;
+ }
+#if defined(TRAKCLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, TIOCSETD): %m",trakdev);
+ goto screwed;
+ }
+#endif /* TRAKCLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (gpsunits[unit] != 0) {
+ gps = gpsunits[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && gpsunits[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ gps = gpsunits[i];
+ gpsunits[i] = 0;
+ } else {
+ gps = (struct gpsunit *)
+ emalloc(sizeof(struct gpsunit));
+ }
+ }
+ bzero((char *)gps, sizeof(struct gpsunit));
+ gpsunits[unit] = gps;
+
+ /*
+ * Set up the structures
+ */
+ gps->peer = peer;
+ gps->unit = (u_char)unit;
+ gps->timestarted = current_time;
+
+ gps->io.clock_recv = trak_receive;
+ gps->io.srcclock = (caddr_t)gps;
+ gps->io.datalen = 0;
+ gps->io.fd = fd232;
+#ifdef TRAKPPS
+ if (ioctl(fd232, CIOGETEV, (caddr_t)&ev) < 0) {
+ syslog(LOG_ERR,
+ "trak_start: ioctl(%s, CIOGETEV): %m", trakdev);
+ goto screwed;
+ } else
+ gps->lastev = ev.tv.tv_sec;
+#endif /* TRAKPPS */
+ if (!io_addclock(&gps->io)) {
+ goto screwed;
+ }
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success. Note that root delay and root dispersion are
+ * always zero for this clock.
+ */
+ peer->precision = GPSPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1)
+ bcopy(GPSREFID, (char *)&peer->refid, 4);
+ else
+ peer->refid = htonl(GPSHSREFID);
+ unitinuse[unit] = 1;
+ /*
+ * request to give time code
+ */
+ {
+ void gps_send();
+ gps_send(gps,"\rRQTS,U\r");
+ gps_send(gps,"SEL 00\r");
+ }
+
+ return (1);
+
+ /*
+ * Something broke; abandon ship.
+ */
+screwed:
+ (void) close(fd232);
+ return (0);
+}
+
+/*
+ * trak_shutdown - shut down a GPS clock
+ */
+static void
+trak_shutdown(unit)
+ int unit;
+{
+ register struct gpsunit *gps;
+ void gps_send();
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "trak_shutdown: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "trak_shutdown: unit %d not in use", unit);
+ return;
+ }
+ gps = gpsunits[unit];
+ /*
+ * request not to give time code any more
+ */
+ gps_send(gps,"RQTX\r");
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ io_closeclock(&gps->io);
+
+ unitinuse[unit] = 0;
+}
+
+
+/*
+ * trak_report_event - note the occurance of an event
+ *
+ * This routine presently just remembers the report and logs it, but
+ * does nothing heroic for the trap handler.
+ */
+static void
+trak_report_event(gps, code)
+ struct gpsunit *gps;
+ int code;
+{
+ struct peer *peer;
+
+ peer = gps->peer;
+ if (gps->status != (u_char)code) {
+ gps->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ gps->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "clock %s event %x\n", ntoa(&peer->srcadr), code);
+ }
+}
+
+
+/*
+ * trak_receive - receive data from the serial interface
+ */
+static void
+trak_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int i,cmdtype;
+ register struct gpsunit *gps;
+
+#if defined(TRAKPPS)
+ struct ppsclockev ev;
+ l_fp trtmp;
+#endif /* TRAKPPS */
+ register u_char *dpt;
+ register u_char *cp;
+ register u_char *dpend;
+ l_fp tstmp;
+ u_fp dispersion;
+
+ /*
+ * Get the clock this applies to and pointers to the data.
+ * Edit the timecode to remove control chars and trashbits.
+ */
+ gps = (struct gpsunit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+ dpend = dpt + rbufp->recv_length;
+ cp = (u_char *)gps->lastcode;
+
+ while (dpt < dpend) {
+#ifdef TRAKCLK /* prior to TRAKPPS due to timestamp */
+ if ((*cp = 0x7f & *dpt++) != '*' ) cp++;
+ else if (*cp == '*' ) { /* caught magic character */
+ if ( dpend - dpt < 8) {
+ /* short timestamp */
+ if(debug) puts("gps: short timestamp.");
+ return;
+ }
+ if (!buftvtots(dpt,&gps->lastrec)) {
+ /* screwy timestamp */
+ if(debug) puts("gps: screwy timestamp.");
+ return;
+ }
+ dpt += 8;
+ }
+#else
+#ifdef TRAKPPS
+ if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
+#else
+ /* both are not specified */
+#endif /* TRAKPPS */
+#endif /* TRAKCLK */
+ }
+ *cp = '\0';
+ gps->lencode = cp - (u_char *)gps->lastcode;
+ if (gps->lencode == 0) return;
+
+#ifdef DEBUG
+ if (debug)
+ printf("gps: timecode %d %s\n",
+ gps->lencode, gps->lastcode);
+#endif
+
+ /*
+ * We check the timecode format and decode its contents. The
+ * timecode has format *........RQTS U,ddd:hh:mm:ss.0,Q\r\n).
+ * 012345678901234567890123
+ */
+#define RQTS 0
+#define RQLS 1
+ cp = (u_char *)gps->lastcode;
+ gps->leap = 0;
+ cmdtype=0;
+ if(strncmp(cp,"*RQTS",5)==0) {
+ cmdtype=RQTS;
+ cp += 8;
+ }
+ else if(strncmp(cp,"RQTS",4)==0) {
+ cmdtype=RQTS;
+ cp += 7;
+ }
+ else if(strncmp(cp,"RQLS",4)==0) {
+ cmdtype=RQLS;
+ cp += 5;
+ }
+ else
+ return;
+
+ switch( cmdtype ) {
+ case RQTS:
+ /*
+ * Check time code format of TRAK 8810
+ */
+ if( !isdigit(cp[0]) ||
+ !isdigit(cp[1]) ||
+ !isdigit(cp[2]) ||
+ cp[3] != ':' ||
+ !isdigit(cp[4]) ||
+ !isdigit(cp[5]) ||
+ cp[6] != ':' ||
+ !isdigit(cp[7]) ||
+ !isdigit(cp[8]) ||
+ cp[9] != ':' ||
+ !isdigit(cp[10])||
+ !isdigit(cp[11])) {
+ gps->badformat++;
+ trak_report_event(gps, CEVNT_BADREPLY);
+ return;
+ }
+ break;
+ case RQLS:
+ /*
+ * reply for leap second request
+ */
+ if (cp[0] !='0' || cp[1] != '0' ) gps->leap = LEAP_ADDSECOND;
+ return;
+ default:
+ return;
+
+ }
+
+ /*
+ * Convert date and check values.
+ */
+ gps->day = cp[0] - '0';
+ gps->day = MULBY10(gps->day) + cp[1] - '0';
+ gps->day = MULBY10(gps->day) + cp[2] - '0';
+ if (gps->day < 1 || gps->day > 366) {
+ gps->baddata++;
+ trak_report_event(gps, CEVNT_BADDATE);
+ return;
+ }
+ /*
+ * Convert time and check values.
+ */
+ gps->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
+ gps->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
+ gps->second = MULBY10(cp[10] - '0') + cp[11] - '0';
+ gps->msec = 0;
+ if (gps->hour > 23 || gps->minute > 59 || gps->second > 59) {
+ gps->baddata++;
+ trak_report_event(gps, CEVNT_BADTIME);
+ return;
+ }
+
+ if (!gps->polled) return;
+
+ /*
+ * Test for synchronization Check for quality byte.
+ */
+/*
+ switch( cp[15] ) {
+ case '0':
+ if(gps->peer->stratum == stratumtouse[gps->unit]) {
+ gps->peer->stratum = 10 ;
+ bzero(&gps->peer->refid,4);
+ }
+ break;
+ default:
+ if(gps->peer->stratum != stratumtouse[gps->unit]) {
+ gps->peer->stratum = stratumtouse[gps->unit] ;
+ bcopy(GPSREFID,&gps->peer->refid,4);
+ }
+ break;
+ }
+*/
+ if( cp[15] == '0') /* TRAK derailed from tracking satellites */
+ {
+ gps->leap = LEAP_NOTINSYNC;
+ gps->noreply++;
+ trak_report_event(gps, CEVNT_TIMEOUT);
+ }
+ else
+ {
+ gps->lasttime = current_time;
+ if( gps->lastevent == CEVNT_TIMEOUT ) {
+ gps->status = CEVNT_NOMINAL;
+ trak_report_event(gps, CEVNT_NOMINAL);
+ }
+ }
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the second, which presumably is the one which
+ * occured at the last pps pulse and which was captured by the
+ * loop_filter module. All we have to do here is present a
+ * reasonable facsimile of the time at that pulse so the clock-
+ * filter and selection machinery declares us truechimer. The
+ * precision offset within the second is really tuned by the
+ * loop_filter module. Note that this code does not yet know how
+ * to do the years and relies on the clock-calendar chip for
+ * sanity.
+ */
+
+#if defined(TRAKPPS)
+
+ /*
+ * timestamp must be greater than previous one.
+ */
+ if (ioctl(fdpps, CIOGETEV, (caddr_t)&ev) >= 0) {
+ ev.tv.tv_sec += (U_LONG)JAN_1970;
+ TVTOTS(&ev.tv,&gps->lastrec);
+ if (gps->lastev < ev.tv.tv_sec) {
+ gps->lastev = ev.tv.tv_sec;
+ } else { /* in case of 1-pps missing */
+ gps->lastev = ev.tv.tv_sec;
+ return;
+ }
+ }
+ else
+ return; /* failed to get timestamp */
+#endif /* TRAKPPS */
+
+ if (!clocktime(gps->day, gps->hour, gps->minute,
+ gps->second, GMT, gps->lastrec.l_ui,
+ &gps->yearstart, &gps->lastref.l_ui)) {
+ gps->baddata++;
+ trak_report_event(gps, CEVNT_BADTIME);
+#ifdef DEBUG
+ if(debug) printf("gps: bad date \n");
+#endif
+ return;
+ }
+ MSUTOTSF(gps->msec, gps->lastref.l_uf);
+ tstmp = gps->lastref;
+
+ L_SUB(&tstmp, &gps->lastrec);
+ L_ADD(&tstmp, &(fudgefactor[gps->unit]));
+ i = ((int)(gps->coderecv)) % NCODES;
+ gps->offset[i] = tstmp;
+ gps->coderecv++;
+#if DEBUG
+ if (debug)
+ printf("gps: times %s %s %s\n",
+ ulfptoa(&gps->lastref, 6), ulfptoa(&gps->lastrec, 6),
+ lfptoa(&tstmp, 6));
+#endif
+/* if( tstmp.l_ui != 0 ) return; something wrong */
+
+ /*
+ * Process the samples in the median filter, add the fudge
+ * factor and pass the offset and dispersion along. We use
+ * lastref as both the reference time and receive time in order
+ * to avoid being cute, like setting the reference time later
+ * than the receive time, which may cause a paranoid protocol
+ * module to chuck out the data.
+ */
+ if (gps->coderecv < NCODES)
+ return;
+ if (!trak_process(gps, &tstmp, &dispersion)) {
+ gps->baddata++;
+ trak_report_event(gps, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(gps->peer, &tstmp, GMT, dispersion,
+ &gps->lastrec, &gps->lastrec, gps->leap);
+ /*
+ * after all, clear polled flag
+ */
+ gps->polled = 0;
+}
+
+/*
+ * ==================================================================
+ * gps_send(gps,cmd) Sends a command to the GPS receiver.
+ * as gps_send(gps,"rqts,u\r");
+ * ==================================================================
+ */
+static void
+gps_send(gps,cmd)
+ struct gpsunit *gps;
+ char *cmd;
+{
+ if (write(gps->io.fd, cmd, strlen(cmd)) == -1) {
+ syslog(LOG_ERR, "gps_send: unit %d: %m", gps->unit);
+ trak_report_event(gps,CEVNT_FAULT);
+ } else {
+ gps->polls++;
+ }
+}
+
+/*
+ * trak_process - process a pile of samples from the clock
+ *
+ * This routine uses a three-stage median filter to calculate offset and
+ * dispersion and reduce jitter. The dispersion is calculated as the
+ * span of the filter (max - min).
+ */
+static char
+trak_process(gps, offset, dispersion)
+ struct gpsunit *gps;
+ l_fp *offset;
+ u_fp *dispersion;
+{
+ register int i, j;
+ register U_LONG tmp_ui, tmp_uf;
+ int not_median1 = -1; /* XXX correct? */
+ int not_median2 = -1; /* XXX correct? */
+ int median;
+ u_fp disp_tmp, disp_tmp2;
+
+ /*
+ * This code implements a three-stage median filter. First, we
+ * check if the samples are within 125 ms of each other. If not,
+ * dump the sample set. We take the median of the three offsets
+ * and use that as the sample offset. There probably is not much
+ * to be gained by a longer filter, since the clock filter in
+ * ntp_proto should do its thing.
+ */
+ disp_tmp2 = 0;
+ for (i = 0; i < NCODES-1; i++) {
+ for (j = i+1; j < NCODES; j++) {
+ tmp_ui = gps->offset[i].l_ui;
+ tmp_uf = gps->offset[i].l_uf;
+ M_SUB(tmp_ui, tmp_uf, gps->offset[j].l_ui,
+ gps->offset[j].l_uf);
+ if (M_ISNEG(tmp_ui, tmp_uf)) {
+ M_NEG(tmp_ui, tmp_uf);
+ }
+ if (tmp_ui != 0 || tmp_uf > CODEDIFF) {
+ return (0);
+ }
+ disp_tmp = MFPTOFP(0, tmp_uf);
+ if (disp_tmp > disp_tmp2) {
+ disp_tmp2 = disp_tmp;
+ not_median1 = i;
+ not_median2 = j;
+ }
+ }
+ }
+ if (gps->lasttime == 0)
+ disp_tmp2 = NTP_MAXDISPERSE;
+ else
+ disp_tmp2 = current_time - gps->lasttime;
+ if (not_median1 == 0) {
+ if (not_median2 == 1)
+ median = 2;
+ else
+ median = 1;
+ } else {
+ median = 0;
+ }
+ *offset = gps->offset[median];
+ *dispersion = disp_tmp2;
+ return (1);
+}
+
+/*
+ * trak_poll - called by the transmit procedure
+ *
+ * We go to great pains to avoid changing state here, since there may be
+ * more than one eavesdropper receiving the same timecode.
+ */
+static void
+trak_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct gpsunit *gps;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "trak_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "trak_poll: unit %d not in use", unit);
+ return;
+ }
+ gps = gpsunits[unit];
+ if ((current_time - gps->lasttime) > 150)
+ trak_report_event(gpsunits[unit], CEVNT_TIMEOUT);
+ /*
+ * usually trak_receive can get a timestamp every second
+ */
+#if !defined(TRAKPPS) && !defined(TRAKCLK)
+ gettstamp(&gps->lastrec);
+#endif
+ gps->polls++;
+ /*
+ * may be polled every 16 seconds (minpoll 4)
+ */
+ gps->polled = 1;
+}
+
+/*
+ * trak_control - set fudge factors, return statistics
+ */
+static void
+trak_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct gpsunit *gps;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "trak_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVEVAL1) {
+ stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf);
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ /*
+ * Should actually reselect clock, but
+ * will wait for the next timecode
+ */
+ gps = gpsunits[unit];
+ peer = gps->peer;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1)
+ bcopy(GPSREFID, (char *)&peer->refid,
+ 4);
+ else
+ peer->refid = htonl(GPSHSREFID);
+ }
+ }
+ }
+
+ if (out != 0) {
+ out->type = REFCLK_GPS_TRAK;
+ out->haveflags
+ = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2;
+ out->clockdesc = GPSDESCRIPTION;
+ out->fudgetime1 = fudgefactor[unit];
+ out->fudgetime2.l_ui = 0;
+ out->fudgetime2.l_uf = 0;
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = 0;
+ out->flags = sloppyclockflag[unit];
+ if (unitinuse[unit]) {
+ gps = gpsunits[unit];
+ out->lencode = gps->lencode; /* LENTOC */;
+ out->lastcode = gps->lastcode;
+ out->timereset = current_time - gps->timestarted;
+ out->polls = gps->polls;
+ out->noresponse = gps->noreply;
+ out->badformat = gps->badformat;
+ out->baddata = gps->baddata;
+ out->lastevent = gps->lastevent;
+ out->currentstatus = gps->status;
+ } else {
+ out->lencode = 0;
+ out->lastcode = "";
+ out->polls = out->noresponse = 0;
+ out->badformat = out->baddata = 0;
+ out->timereset = 0;
+ out->currentstatus = out->lastevent = CEVNT_NOMINAL;
+ }
+ }
+}
+
+/*
+ * trak_buginfo - return clock dependent debugging info
+ */
+static void
+trak_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct gpsunit *gps;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "trak_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ gps = gpsunits[unit];
+
+ bug->nvalues = 10;
+ bug->ntimes = 5;
+ if (gps->lasttime != 0)
+ bug->values[0] = current_time - gps->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = (U_LONG)gps->reason;
+ bug->values[2] = (U_LONG)gps->year;
+ bug->values[3] = (U_LONG)gps->day;
+ bug->values[4] = (U_LONG)gps->hour;
+ bug->values[5] = (U_LONG)gps->minute;
+ bug->values[6] = (U_LONG)gps->second;
+ bug->values[7] = (U_LONG)gps->msec;
+ bug->values[8] = gps->noreply;
+ bug->values[9] = gps->yearstart;
+ bug->stimes = 0x1c;
+ bug->times[0] = gps->lastref;
+ bug->times[1] = gps->lastrec;
+ bug->times[2] = gps->offset[0];
+ bug->times[3] = gps->offset[1];
+ bug->times[4] = gps->offset[2];
+}
+#endif
diff --git a/contrib/xntpd/xntpdc/ntpdc.c b/contrib/xntpd/xntpdc/ntpdc.c
index 001bd77c1e55..3113c9ff7817 100644
--- a/contrib/xntpd/xntpdc/ntpdc.c
+++ b/contrib/xntpd/xntpdc/ntpdc.c
@@ -53,7 +53,7 @@ static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **));
static int getarg P((char *, int, arg_v *));
static int getnetnum P((char *, U_LONG *, char *));
static void help P((struct parse *, FILE *));
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
static int helpsort P((const void *, const void *));
#else
static int helpsort P((char **, char **));
@@ -598,8 +598,12 @@ again:
/*
* So far, so good. Copy this data into the output array.
*/
- if ((datap + datasize) > (pktdata + pktdatasize))
+ if ((datap + datasize) > (pktdata + pktdatasize)) {
+ int offset = datap - pktdata;
growpktdata();
+ *rdata = pktdata; /* might have been realloced ! */
+ datap = pktdata + offset;
+ }
memmove(datap, (char *)rpkt.data, datasize);
datap += datasize;
if (firstpkt) {
@@ -1149,7 +1153,7 @@ help(pcmd, fp)
for (xcp = opcmds; xcp->keyword != 0; xcp++)
cmdsort[n++] = xcp->keyword;
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
qsort((void *)cmdsort, n, sizeof(char *), helpsort);
#else
qsort((char *)cmdsort, n, sizeof(char *), helpsort);
@@ -1195,7 +1199,7 @@ help(pcmd, fp)
* helpsort - do hostname qsort comparisons
*/
static int
-#if defined(sgi) || defined(SYS_BSDI)
+#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
helpsort(t1, t2)
const void *t1;
const void *t2;
diff --git a/contrib/xntpd/xntpdc/ntpdc_ops.c b/contrib/xntpd/xntpdc/ntpdc_ops.c
index 55483faeba10..4fa9324784cc 100644
--- a/contrib/xntpd/xntpdc/ntpdc_ops.c
+++ b/contrib/xntpd/xntpdc/ntpdc_ops.c
@@ -66,10 +66,9 @@ static void ctlstats P((struct parse *, FILE *));
static void leapinfo P((struct parse *, FILE *));
static void clockstat P((struct parse *, FILE *));
static void fudge P((struct parse *, FILE *));
-static void maxskew P((struct parse *, FILE *));
static void clkbug P((struct parse *, FILE *));
static void setprecision P((struct parse *, FILE *));
-static void setselect P((struct parse *, FILE *));
+static void kerninfo P((struct parse *, FILE *));
/*
* Commands we understand. Ntpdc imports this.
@@ -77,37 +76,37 @@ static void setselect P((struct parse *, FILE *));
struct xcmd opcmds[] = {
{ "listpeers", peerlist, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print list of peers the server knows about" },
+ "display list of peers the server knows about" },
{ "peers", peers, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print peer summary information" },
+ "display peer summary information" },
{ "dmpeers", dmpeers, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print peer summary info the way Dave Mills likes it" },
+ "display peer summary info the way Dave Mills likes it" },
{ "showpeer", showpeer, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
- "print detailed information for one or more peers" },
+ "display detailed information for one or more peers" },
{ "pstats", peerstats, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
- "print statistical information for one or more peers" },
+ "display statistical information for one or more peers" },
{ "loopinfo", loopinfo, { OPT|STR, NO, NO, NO },
{ "oneline|multiline", "", "", "" },
- "print loop filter information" },
+ "display loop filter information" },
{ "sysinfo", sysinfo, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print local server information" },
+ "display local server information" },
{ "sysstats", sysstats, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print local server statistics" },
+ "display local server statistics" },
{ "memstats", memstats, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print peer memory usage statistics" },
+ "display peer memory usage statistics" },
{ "iostats", iostats, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print I/O subsystem statistics" },
+ "display I/O subsystem statistics" },
{ "timerstats", timerstats, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print event timer subsystem statistics" },
+ "display event timer subsystem statistics" },
{ "addpeer", addpeer, { ADD, OPT|UINT, OPT|UINT, OPT|STR },
{ "addr", "keyid", "version", "minpoll|prefer" },
"configure a new peer association" },
@@ -121,14 +120,14 @@ struct xcmd opcmds[] = {
{ "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
"unconfigure existing peer assocations" },
{ "set", set, { STR, OPT|STR, OPT|STR, OPT|STR },
- { "bclient|auth", "...", "...", "..." },
- "set a system flag (bclient, authenticate)" },
+ { "bclient|mclient|auth", "...", "...", "..." },
+ "set a system flag (bclient, mclient, auth)" },
{ "clear", sys_clear, { STR, OPT|STR, OPT|STR, OPT|STR },
- { "bclient|auth", "...", "...", "..." },
- "clear a system flag (bclient, authenticate)" },
+ { "bclient|mclient|auth", "...", "...", "..." },
+ "clear a system flag (bclient, mclient, auth)" },
{ "reslist", reslist, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print the server's restrict list" },
+ "display the server's restrict list" },
{ "restrict", restrict, { ADD, ADD, STR, OPT|STR },
{ "address", "mask",
"ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer",
@@ -144,7 +143,7 @@ struct xcmd opcmds[] = {
"delete a restrict entry" },
{ "monlist", monlist, { NO, NO, NO, NO },
{ "", "", "", "" },
- "print data the server's monitor routines have collected" },
+ "display data the server's monitor routines have collected" },
{ "monitor", monitor, { STR, NO, NO, NO },
{ "on|off", "", "", "" },
"turn the server's monitoring facility on or off" },
@@ -171,10 +170,10 @@ struct xcmd opcmds[] = {
"remove one or more key ID's from the trusted list" },
{ "authinfo", authinfo, { NO, NO, NO, NO },
{ "", "", "", "" },
- "obtain information concerning the state of the authentication code" },
+ "display the state of the authentication code" },
{ "traps", traps, { NO, NO, NO, NO },
{ "", "", "", "" },
- "obtain information about traps set in server" },
+ "display the traps set in the server" },
{ "addtrap", addtrap, { ADD, OPT|UINT, OPT|ADD, NO },
{ "address", "port", "interface", "" },
"configure a trap in the server" },
@@ -189,28 +188,26 @@ struct xcmd opcmds[] = {
"change the keyid the server uses to authenticate control messages" },
{ "ctlstats", ctlstats, { NO, NO, NO, NO },
{ "", "", "", "" },
- "obtain packet count statistics from the control module" },
+ "display packet count statistics from the control module" },
{ "leapinfo", leapinfo, { NO, NO, NO, NO },
{ "", "", "", "" },
- "obtain information about the current leap second state" },
+ "display the current leap second state" },
{ "clockstat", clockstat, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "address", "address", "address", "address" },
- "obtain status information about the specified clock" },
+ "display clock status information" },
{ "fudge", fudge, { ADD, STR, STR, NO },
{ "address", "time1|time2|val1|val2|flags", "value", "" },
"set/change one of a clock's fudge factors" },
- { "maxskew", maxskew, { STR, NO, NO, NO },
- { "maximum_skew", "", "", "" },
- "set the server's maximum skew parameter" },
{ "clkbug", clkbug, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "address", "address", "address", "address" },
- "obtain debugging information from the specified clock" },
+ "display clock debugging information" },
{ "setprecision", setprecision, { INT, NO, NO, NO },
{ "sys_precision", "", "", "" },
"set the server's advertised precision" },
- { "setselect", setselect, { UINT, NO, NO, NO },
- { "select_algorithm_number", "", "", "" },
- "change the selection weighting algorithm used by the server" },
+ { "kerninfo", kerninfo, { NO, NO, NO, NO },
+ { "", "", "", "" },
+ "display the kernel pll/pps variables" },
+
{ 0, 0, { NO, NO, NO, NO },
{ "", "", "", "" }, "" }
};
@@ -374,9 +371,9 @@ dopeers(pcmd, fp, dmstyle)
return;
(void) fprintf(fp,
- " remote local st poll reach delay offset disp\n");
+ " remote local st poll reach delay offset disp\n");
(void) fprintf(fp,
- "======================================================================\n");
+ "=======================================================================\n");
while (items > 0) {
if (!dmstyle) {
if (plist->flags & INFO_FLAG_SYSPEER)
@@ -407,13 +404,14 @@ dopeers(pcmd, fp, dmstyle)
ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
NTP_MINPOLL);
(void) fprintf(fp,
- "%c%-15.15s %-15.15s %2d %4d %3o %7.7s %9.9s %6.6s\n",
+ "%c%-15.15s %-15.15s %2d %4d %3o %7.7s %9.9s %7.7s\n",
c, nntohost(plist->srcadr),
numtoa(plist->dstadr),
plist->stratum, ntp_poll, plist->reach,
- fptoa(NTOHS_FP(plist->delay), 4),
+ fptoa(NTOHS_FP(plist->delay), 5),
lfptoa(&tempts, 6),
- ufptoa(NTOHS_FP(plist->dispersion), 4));
+ ufptoa(NTOHS_FP(plist->dispersion), 5));
+
plist++;
items--;
}
@@ -451,16 +449,19 @@ printpeer(pp, fp)
"leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
pp->leap & 0x2 ? '1' : '0',
pp->leap & 0x1 ? '1' : '0',
- str, ufptoa(HTONS_FP(pp->rootdelay), 4),
- ufptoa(HTONS_FP(pp->rootdispersion), 4));
+ str, ufptoa(HTONS_FP(pp->rootdelay), 5),
+ ufptoa(HTONS_FP(pp->rootdispersion), 5));
(void) fprintf(fp,
"ppoll %d, hpoll %d, keyid %u, version %d, association %u\n",
pp->ppoll, pp->hpoll, pp->keyid, pp->version, ntohs(pp->associd));
(void) fprintf(fp,
- "valid %d, reach %03o, unreach %d, trust %03o\n",
- pp->valid, pp->reach, pp->unreach, pp->trust);
+ "valid %d, reach %03o, unreach %d, flash %03o, ",
+ pp->valid, pp->reach, pp->unreach, pp->flash);
+
+ (void) fprintf(fp, "estbdelay %s, ttl %d\n",
+ mfptoa(0, ntohl(pp->estbdelay), 5), pp->ttl);
(void) fprintf(fp, "timer %ds, flags", ntohl(pp->timer));
if (pp->flags == 0) {
@@ -508,7 +509,8 @@ printpeer(pp, fp)
(void) fprintf(fp, "filter delay: ");
for (i = 0; i < NTP_SHIFT; i++) {
- (void) fprintf(fp, " %-8.8s", fptoa(HTONS_FP(pp->filtdelay[i]),4));
+ (void) fprintf(fp, " %-8.8s",
+ fptoa(HTONS_FP(pp->filtdelay[i]), 5));
if (i == (NTP_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
}
@@ -517,7 +519,7 @@ printpeer(pp, fp)
(void) fprintf(fp, "filter offset:");
for (i = 0; i < NTP_SHIFT; i++) {
HTONL_FP(&pp->filtoffset[i], &tempts);
- (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 5));
+ (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
if (i == (NTP_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
}
@@ -531,23 +533,13 @@ printpeer(pp, fp)
}
(void) fprintf(fp, "\n");
- (void) fprintf(fp, "bdelay filter:");
- for (i = 0; i < NTP_SHIFT; i++) {
- (void) fprintf(fp, " %-8.8s",
- mfptoa(0, ntohl(pp->bdelay[i]), 5));
- if (i == (NTP_SHIFT>>1)-1)
- (void) fprintf(fp, "\n ");
- }
- (void) fprintf(fp, "\n");
-
- (void) fprintf(fp, "delay %s, estbdelay %s\n",
- fptoa(HTONS_FP(pp->delay), 4),
- mfptoa(0, ntohl(pp->estbdelay), 4));
HTONL_FP(&pp->offset, &tempts);
- (void) fprintf(fp, "offset %s, dispersion %s\n",
- lfptoa(&tempts, 6),
- ufptoa(HTONS_FP(pp->dispersion), 4));
+ (void) fprintf(fp,
+ "offset %s, delay %s, dispersion %s, selectdisp %s\n",
+ lfptoa(&tempts, 6), fptoa(HTONS_FP(pp->delay), 5),
+ ufptoa(HTONS_FP(pp->dispersion), 5),
+ ufptoa(HTONS_FP(pp->selectdisp), 5));
}
@@ -781,11 +773,10 @@ sysinfo(pcmd, fp)
is->leap & 0x1 ? '1' : '0');
(void) fprintf(fp, "stratum: %d\n", (int)is->stratum);
(void) fprintf(fp, "precision: %d\n", (int)is->precision);
- (void) fprintf(fp, "select algorithm: %d\n", (int)is->selection);
(void) fprintf(fp, "sync distance: %s\n",
- fptoa(NTOHS_FP(is->rootdelay), 4));
+ fptoa(NTOHS_FP(is->rootdelay), 5));
(void) fprintf(fp, "sync dispersion: %s\n",
- ufptoa(NTOHS_FP(is->rootdispersion), 4));
+ ufptoa(NTOHS_FP(is->rootdispersion), 5));
if (is->stratum <= 1) {
junk[4] = 0;
memmove(junk, (char *)&is->refid, 4);
@@ -799,7 +790,8 @@ sysinfo(pcmd, fp)
(void) fprintf(fp, "reference time: %s\n", prettydate(&tempts));
(void) fprintf(fp, "system flags: ");
- if ((is->flags & (INFO_FLAG_BCLIENT|INFO_FLAG_AUTHENABLE)) == 0) {
+ if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_MCLIENT |
+ INFO_FLAG_AUTHENABLE)) == 0) {
(void) fprintf(fp, "none\n");
} else {
res = 0;
@@ -807,6 +799,10 @@ sysinfo(pcmd, fp)
(void) fprintf(fp, "bclient");
res = 1;
}
+ if (is->flags & INFO_FLAG_MCLIENT) {
+ (void) fprintf(fp, "mclient");
+ res = 1;
+ }
if (is->flags & INFO_FLAG_AUTHENABLE)
(void) fprintf(fp, "%sauthenticate",
res ? ", " : "");
@@ -818,8 +814,6 @@ sysinfo(pcmd, fp)
HTONL_FP(&is->authdelay, &tempts);
(void) fprintf(fp, "encryption delay: %s\n", lfptoa(&tempts, 7));
- (void) fprintf(fp, "maximum skew: %s\n",
- ufptoa(NTOHS_FP(is->maxskew), 4));
}
@@ -846,8 +840,12 @@ sysstats(pcmd, fp)
if (!check1item(items, fp))
return;
- if (!checkitemsize(itemsize, sizeof(struct info_sys_stats)))
+ if (itemsize != sizeof(struct info_sys_stats) &&
+ itemsize != sizeof(struct old_info_sys_stats)) {
+ /* issue warning according to new structure size */
+ checkitemsize(itemsize, sizeof(struct info_sys_stats));
return;
+ }
(void) fprintf(fp, "system uptime: %d\n",
ntohl(ss->timeup));
@@ -867,8 +865,11 @@ sysstats(pcmd, fp)
ntohl(ss->processed));
(void) fprintf(fp, "bad authentication: %d\n",
ntohl(ss->badauth));
- (void) fprintf(fp, "wander hold downs: %d\n",
- ntohl(ss->wanderhold));
+ if (itemsize != sizeof(struct info_sys_stats))
+ return;
+
+ (void) fprintf(fp, "limitation rejects: %d\n",
+ ntohl(ss->limitrejected));
}
@@ -1205,6 +1206,8 @@ doset(pcmd, fp, req)
for (items = 0; items < pcmd->nargs; items++) {
if (STREQ(pcmd->argval[items].string, "bclient"))
sys.flags |= SYS_FLAG_BCLIENT;
+ else if (STREQ(pcmd->argval[items].string, "mclient"))
+ sys.flags |= SYS_FLAG_MCLIENT;
else if (STREQ(pcmd->argval[items].string, "auth"))
sys.flags |= SYS_FLAG_AUTHENTICATE;
else {
@@ -1243,6 +1246,7 @@ static struct resflags resflags[] = {
{ "nopeer", RES_NOPEER },
{ "notrap", RES_NOTRAP },
{ "lptrap", RES_LPTRAP },
+ { "limited", RES_LIMITED },
{ "", 0 }
};
@@ -1463,6 +1467,7 @@ monlist(pcmd, fp)
FILE *fp;
{
struct info_monitor *ml;
+ struct old_info_monitor *oml;
int items;
int itemsize;
int res;
@@ -1476,23 +1481,49 @@ monlist(pcmd, fp)
if (!checkitems(items, fp))
return;
- if (!checkitemsize(itemsize, sizeof(struct info_monitor)))
- return;
+ if (itemsize == sizeof(struct info_monitor)) {
- (void) fprintf(fp,
- " address port count mode version lasttime firsttime\n");
- (void) fprintf(fp,
- "=====================================================================\n");
- while (items > 0) {
- (void) fprintf(fp, "%-20.20s %5d %9d %4d %3d %9u %9u\n",
- nntohost(ml->addr),
- ntohs(ml->port),
- ntohl(ml->count),
- ml->mode, ml->version,
- ntohl(ml->lasttime),
- ntohl(ml->firsttime));
- ml++;
- items--;
+ (void) fprintf(fp,
+ " address port count mode version lastdrop lasttime firsttime\n");
+ (void) fprintf(fp,
+ "===============================================================================\n");
+ while (items > 0) {
+ (void) fprintf(fp, "%-20.20s %5d %9d %4d %3d %9u %9u %9u\n",
+ nntohost(ml->addr),
+ ntohs(ml->port),
+ ntohl(ml->count),
+ ml->mode,
+ ml->version,
+ ntohl(ml->lastdrop),
+ ntohl(ml->lasttime),
+ ntohl(ml->firsttime));
+ ml++;
+ items--;
+ }
+ } else {
+ if (itemsize != sizeof(struct old_info_monitor)) {
+ /* issue warning according to new info_monitor size */
+ checkitemsize(itemsize, sizeof(struct info_monitor));
+ return;
+ }
+
+ oml = (struct old_info_monitor *)ml;
+ (void) fprintf(fp,
+ " address port count mode version lasttime firsttime\n");
+ (void) fprintf(fp,
+ "======================================================================\n");
+ while (items > 0) {
+ (void) fprintf(fp, "%-20.20s %5d %9d %4d %3d %9u %9u\n",
+ nntohost(oml->addr),
+ ntohs(oml->port),
+ ntohl(oml->count),
+ oml->mode,
+ oml->version,
+ ntohl(oml->lasttime),
+ ntohl(oml->firsttime));
+ oml++;
+ items--;
+ }
}
}
@@ -2247,39 +2278,6 @@ fudge(pcmd, fp)
return;
}
-
-
-/*
- * maxskew - set the server's maximum skew parameter
- */
-static void
-maxskew(pcmd, fp)
- struct parse *pcmd;
- FILE *fp;
-{
- u_fp Xmaxskew;
- l_fp tmp;
- int items;
- int itemsize;
- char *dummy;
- int res;
-
- if (!atolfp(pcmd->argval[0].string, &tmp)) {
- (void) fprintf(stderr, "What the heck does %s mean?\n",
- pcmd->argval[0].string);
- return;
- }
- Xmaxskew = HTONS_FP(LFPTOFP(&tmp));
-
- res = doquery(IMPL_XNTPD, REQ_SET_MAXSKEW, 1, 1, sizeof(u_fp),
- (char *)&Xmaxskew, &items, &itemsize, &dummy);
-
- if (res == 0)
- (void) fprintf(fp, "done!\n");
-}
-
-
-
/*
* clkbug - get and print clock debugging information
*/
@@ -2395,27 +2393,72 @@ setprecision(pcmd, fp)
}
-
/*
- * setselect - change the server's selection algorithm
+ * kerninfo - display the kernel pll/pps variables
*/
static void
-setselect(pcmd, fp)
+kerninfo(pcmd, fp)
struct parse *pcmd;
FILE *fp;
{
- U_LONG select_code;
+ struct info_kernel *ik;
int items;
int itemsize;
- char *dummy;
int res;
- select_code = htonl(pcmd->argval[0].uval);
+ res = doquery(IMPL_XNTPD, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
+ &items, &itemsize, (char **)&ik);
+ if (res != 0 && items == 0)
+ return;
+ if (!check1item(items, fp))
+ return;
+ if (!checkitemsize(itemsize, sizeof(struct info_kernel)))
+ return;
- res = doquery(IMPL_XNTPD, REQ_SET_SELECT_CODE, 1, 1, sizeof(U_LONG),
- (char *)&select_code, &items, &itemsize, &dummy);
-
- if (res == 0)
- (void) fprintf(fp, "done!\n");
- return;
+ /*
+ * pll variables
+ */
+ (void)fprintf(fp, "pll offset: %d us\n",
+ ntohl(ik->offset));
+ (void)fprintf(fp, "pll frequency: %s ppm\n",
+ fptoa((s_fp)ntohl(ik->freq), 3));
+ (void)fprintf(fp, "maximum error: %d us\n",
+ ntohl(ik->maxerror));
+ (void)fprintf(fp, "estimated error: %d us\n",
+ ntohl(ik->esterror));
+ (void)fprintf(fp, "status: %04x\n",
+ ntohs(ik->status & 0xffff));
+ (void)fprintf(fp, "pll time constant: %d\n",
+ ntohl(ik->constant));
+ (void)fprintf(fp, "precision: %d us\n",
+ ntohl(ik->precision));
+ (void)fprintf(fp, "frequency tolerance: %s ppm\n",
+ fptoa((s_fp)ntohl(ik->tolerance), 0));
+
+ /*
+ * For backwards compatibility (ugh), we find the pps variables
+ * only if the shift member is nonzero.
+ */
+ if (!ik->shift)
+ return;
+
+ /*
+ * pps variables
+ */
+ (void)fprintf(fp, "pps frequency: %s ppm\n",
+ fptoa((s_fp)ntohl(ik->ppsfreq), 3));
+ (void)fprintf(fp, "pps stability: %s ppm\n",
+ fptoa((s_fp)ntohl(ik->stabil), 3));
+ (void)fprintf(fp, "pps jitter: %d us\n",
+ ntohl(ik->jitter));
+ (void)fprintf(fp, "calibration interval: %d s\n",
+ 1 << ntohs(ik->shift));
+ (void)fprintf(fp, "calibration cycles: %d\n",
+ ntohl(ik->calcnt));
+ (void)fprintf(fp, "jitter exceeded: %d\n",
+ ntohl(ik->jitcnt));
+ (void)fprintf(fp, "stability exceeded: %d\n",
+ ntohl(ik->stbcnt));
+ (void)fprintf(fp, "calibration errors: %d\n",
+ ntohl(ik->errcnt));
}
diff --git a/contrib/xntpd/xntpres/xntpres.c b/contrib/xntpd/xntpres/xntpres.c
index ee88b1f3be98..47c6eda7dc12 100644
--- a/contrib/xntpd/xntpres/xntpres.c
+++ b/contrib/xntpd/xntpres/xntpres.c
@@ -46,6 +46,7 @@ struct conf_entry {
#define ce_minpoll ce_config.minpoll
#define ce_maxpoll ce_config.maxpoll
#define ce_flags ce_config.flags
+#define ce_ttl ce_config.ttl
#define ce_keyid ce_config.keyid
/*
@@ -100,8 +101,9 @@ int resolve_value; /* next value of resolve timer */
#define TOK_MINPOLL 3
#define TOK_MAXPOLL 4
#define TOK_FLAGS 5
-#define TOK_KEYID 6
-#define NUMTOK 7
+#define TOK_TTL 6
+#define TOK_KEYID 7
+#define NUMTOK 8
#define MAXLINESIZE 512
@@ -128,7 +130,7 @@ extern int errno;
static RETSIGTYPE bong P((int));
static void checkparent P((void));
static void removeentry P((struct conf_entry *));
-static void addentry P((char *, int, int, int, int, int, U_LONG));
+static void addentry P((char *, int, int, int, int, int, int, U_LONG));
static int findhostaddr P((struct conf_entry *));
static void openntp P((void));
static int request P((struct conf_peer *));
@@ -338,13 +340,14 @@ removeentry(entry)
* addentry - add an entry to the configuration list
*/
static void
-addentry(name, mode, version, minpoll, maxpoll, flags, keyid)
+addentry(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
char *name;
int mode;
int version;
int minpoll;
int maxpoll;
int flags;
+ int ttl;
U_LONG keyid;
{
register char *cp;
@@ -363,6 +366,7 @@ addentry(name, mode, version, minpoll, maxpoll, flags, keyid)
ce->ce_minpoll = (u_char)minpoll;
ce->ce_maxpoll = (u_char)maxpoll;
ce->ce_flags = (u_char)flags;
+ ce->ce_ttl = (u_char)ttl;
ce->ce_keyid = htonl(keyid);
ce->ce_next = NULL;
@@ -802,9 +806,9 @@ readconf(fp, name)
* This is as good as we can check it. Add it in.
*/
addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
- (int)intval[TOK_VERSION],
- (int)intval[TOK_MINPOLL], (int)intval[TOK_MAXPOLL],
- flags, intval[TOK_KEYID]);
+ (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
+ (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
+ intval[TOK_KEYID]);
}
}